組み込みRust RTOS対C RTOS

2026/09/03 3:32

組み込みRust RTOS対C RTOS

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

主な発見は、協業型マルチタスクを使用した場合、Rust 非同期フレームワークである Embassy が STM32 マイクロコントローラー上で FreeRTOS よりもメモリフットプリント、コードサイズ、割り込み遅延の面で優れているということです。比較は 180MHz で動作する STM32F446ZET6 上で行われ、プログラムサイズ、静的 RAM 使用量、プログラミングの容易さを含む指標のために標準アプリケーション(LED ブlinking、除振なしのボタン割り込み(遅延測定に影響を与えないように)、UART 送信)が評価されました。Embassy はコンパイル時に既知の静的タスク割当を必要とする協業型マルチタスク非同期エグゼキューターを利用するのに対し、FreeRTOS は完全なプロセッサコンテキストスィッチを行う独立したスレッドを管理する優先制御マルチスレディングを採用しています。結果はすべての初期指標において Embassy が勝利しました:平均割り込み時間は 51.0%、プログラムサイズは 31.0%、静的メモリ(精度のために C ヒープの 15kb を除外)は 84.1% 低減されました。重要なトレードオフは、スレッドの目覚め時のコンテキストスィッチ遅延において FreeRTOS が Embassy の状態機械再開に比べてより高速であることです。ただし、Embassy の割り込みハンドラマクロは複数のエグゼキューターを通じて高優先度コンテキストが低優先度の非同期タスクを効果的に優先制御することを可能にします。結局のところ、Rust ベースの非同期ソリューションである Embassy は最小電力消費と小さなバイナリサイズを重視するプロジェクトに対して優れており、FreeRTOS はスレッド目覚め時間の急速さが重要である場合に依然として関連性を持ちます。将来の分析では効率化指標をさらに改善し、Embassy と比較して平均割り込み時間を 52.8% 削減し、スレッド時間を 49.1% 高速化するというベンチマーク結果を示す RTIC フレームワークを検討できるかもしれません。開発者はリソース制約のある組み込みデバイスで低割り込み遅延を必要とする場合 Embassy を選択し、即応するマルチスレッド応答性を求めるアプリケーションには FreeRTOS を保留すべきです。

本文

STM32F446 上での Async Rust (Embassy) と FreeRTOS (C) 対決:パフォーマンスと実装性の検証

STM32F446 マイコンにおいて、非同期 Rust フレームワーク Embassy とリアルタイムオペレーティングシステム **FreeRTOS **(C) を対決させました。両者は同一の動作を行うアプリケーションを実行し、以下の 4 つの指標で比較を行いました。

  • 割り込み遅延
  • プログラムサイズ (Flash)
  • RAM 使用量 (静的メモリ)
  • **プログラミングのしやすさ **(Ergonomics)

既存の Rust vs C の議論とは異なり、今回は「通常的な」アプリケーション構成(移植性、シンプルさ、標準最適化)を前提とした比較です。


環境と対戦カード

使用環境

  • マイコン: STM32F446ZET6 (180MHz)
  • 計測機器: Rigol DS1054Z オシロスコープ
  • C プロジェクト: STMCube 1.8 を使用
  • Rust プロジェクト: 標準的な
    cargo
    バイナリを使用

アプリケーションのガイドライン

双方のプロジェクトは以下の条件で構築されています。

  • 移植性: HAL に依存しない部分は、他チップやアーキテクチャへの移植が可能 (Portable-ish)。
  • シンプルさ: コードが直感的で理解しやすい構成。
  • 最適化: コンパイルオプション、RTOS 設定、スレッド優先度などは通常の設定。

アプリケーション機能 (3 つのタスク)

  1. LED タスク: 200ms に 1 回点灯し、その間に 100ms 間隔で実行エンジン遅延関数を使用(ボタンのみ)。
  2. ボタン入力処理:
    • ユーザーボタンが押された場合、別のスレッドから通知される(レジスター直接アクセスなし)。
    • GPIO 割り込みで状態変化を検知。
    • 共有原子変数でボタン High/Low を通信し、メッセージキューへ
      Button is <0/1> (N)\n
      を登録。
  3. UART 送信タスク: メッセージキューの文字列をシリアルポートに出力。

アーキテクチャ解説

非同期 Rust (Future & Task)

Rust の非同期関数は

Future
(未来) を返す構文糖衣です。

  • 状態機械: ポーリング可能で、
    await
    点を跨ぐ変数を追跡し、以前の状態から再開できる。
  • **怠惰性 **(Lazy): 実行はポーリングが開始されるまで待機する。
  • **Waker **(ワーカー): 「未来を再びポーリングすべき」と実行エンジンにシグナルを送る機構。
  • タスク: トップレベルの未来。

Embassy の制約と特徴

  • タスクは静的アロケーションのみ(動的アロケータ非依存)。
  • コンパイル時に既知のタスク構成。
  • Rust Nightly (
    type_alias_impl_trait
    機能) 必須。
  • **協調的多任務 **(Cooperative Multitasking): アクティブなタスクが
    await
    中のみ、より重要なタスクへの切り替えが可能(プリエンプション不可)。

RTOS (FreeRTOS)

  • スレッドベース: 状態機械ではなく通常のコードを実行。
  • コンテキストスイッチ: スレッド停止時にプロセッサ全体の状態を保存・復元。
  • プリエンプティブ: カーネルが強制終了可能な優先度制御と公平な実行時間確保。

対決結果の測定項目

項目詳細
パフォーマンスボタン GPIO 割り込み処理速度、スレッド再開までの時間。
割り込み遅延割り込み開始からボタンスレッドの再開(ピン立ち上がり)までの時間差。
プログラムサイズ
arm-none-eabi-size
で測定したテキストセクションサイズ (Flash)。動的メモリは除外。
プログラミングのしやすさ主観的評価。最適化競争ではなく、比較的大きなプログラムの構築効率を重視。

コード実装の詳細

1. ボタン割り込みの通知

  • **Rust **(Embassy): ハードウェア割り込み処理が内部で管理されており、追加作業不要。
  • **C **(FreeRTOS): 割り込みハンドラ内で明示的にスレッドにフラグを設定 (
    osThreadFlagsSet
    ) する必要がある。
// C: FreeRTOS
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if (GPIO_Pin == USER_Btn_Pin) {
        osThreadFlagsSet(buttonWaiterHandle, 1);
    }
}

2. LED の点滅処理

  • Rust:
    #[embassy::task]
    注釈付きの静的アロケーション。原子変数による同期。
  • C: グローバル変数を介した同期。C11 アトミック型を使用。
// Rust: Embassy
#[embassy::task]
async fn blink_led(mut led: Output<'static, PB0>, button_high: &'static AtomicBool) {
    loop {
        Timer::after(Duration::from_millis(100)).await;
        if !button_high.load(Ordering::SeqCst) {
            led.set_high().unwrap();
        }
        Timer::after(Duration::from_millis(100)).await;
        led.set_low().unwrap();
    }
}

// C: FreeRTOS
void StartBlinkLedTask(void *argument)
{
    for (;;) {
        osDelay(100);
        if (atomic_load(&buttonPressed) == GPIO_PIN_RESET) {
            HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_SET);
        }
        osDelay(100);
        HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_RESET);
    }
}

3. メッセージキューの UART 送信

  • Rust:
    ArrayVec
    とスタック割当済みの型を使用。シンプル。
  • C: 構造体定義 (
    UartMessage
    ) を作成し、メッセージ長を管理。
// C: FreeRTOS
typedef struct {
    char data[32];
} UartMessage;

void StartUartWriter(void *argument) {
    for (;;) {
        UartMessage message;
        CheckStatus(
            osMessageQueueGet(uartQueueHandle, &message, NULL, osWaitForever)
        );
        size_t len = strnlen(message.data, sizeof(message.data));
        CheckStatus(
            HAL_UART_Transmit(&huart3, (uint8_t*)&message.data, (uint16_t)len, 1000)
        );
    }
}

4. ボタンの待機・デバウンシング処理

  • Rust:
    ExtiInput
    を使用。
    wait_for_rising_edge
    /
    falling_edge
  • C: EXTI 設定 (
    RTSR
    /
    FTSR
    ) をコード内で記述。ピン状態を直接制御。
// Rust: Embassy
#[embassy::task]
async fn button_waiter(
    mut button: ExtiInput<'static, PC13>,
    button_pressed: &'static AtomicBool,
    sender: Sender<'static, Noop, ArrayString<32>, 8>,
    mut button_processed: Output<'static, PG1>,
) {
    let mut trigger_count = 0;
    loop {
        // Rising edge detection...
        button.wait_for_rising_edge().await; 
        // Message send & state update...
        
        // Falling edge detection...
        button.wait_for_falling_edge().await;
        // Message send & state update...
    }
}

// C: FreeRTOS
void StartButtonWaiterTask(void *argument) {
    for (;;) {
        EXTI->RTSR |= USER_Btn_Pin; // Rising edge setup
        osThreadFlagsWait(...);     // Wait for flag
        
        // Process message & toggle pin...
        
        EXTI->FTSR &= ~USER_Btn_Pin; // Falling edge setup (Reset FTSR to ignore falling)
        // Logic repeats...
    }
}

割り込みハンドラの調整 (Rust Embassy)

Embassy の標準ではピンを即座に High にできないため、以下のマクロを追加。

macro_rules! impl_irq {
    ($e:ident) => {
        #[interrupt]
        unsafe fn $e() {
            pac::gpio::Gpio(0x40021800 as *mut u8).odr().modify(|odr| odr.set_odr(0, stm32_metapac::gpio::vals::Odr::HIGH));
            let x = on_irq();
            pac::gpio::Gpio(0x40021800 as *mut u8).odr().modify(|odr| odr.set_odr(0, stm32_metapac::gpio::vals::Odr::LOW));
            x
        }
    };
}

メasurement Results (結果)

ボタンを 100 回押し、200 サンプルを測定・平均化および標準偏差を算出しました。

比較表:Embassy vs FreeRTOS

項目Rust (Embassy)C (FreeRTOS)差 (絶対値)差 (%)
**割り込み時間 **(平均)2.962 µs1.450 µs-1.512 µs-51.0% (Rust 遅い)
**割り込み時間 **(SD)124.8 ns4.96 ns-119.84 ns-96.0% (Rust 変動大)
**スレッド時間 **(平均)16.19 µs11.64 µs-4.55 µs-28.1% (Rust 遅い)
**スレッド時間 **(SD)248.2 ns103.0 ns-145.2 ns-56.2% (Rust 変動大)
**割り込み遅延 **(平均)4.973 µs3.738 µs-1.235 µs-24.8% (Rust 遅い)
プログラムサイズ20,676 B14,272 B-6,404 B-31.0% (Rust 大きい)
静的メモリ使用量5,480 B872 B-4,608 B-84.1% (Rust 大きい*)

*注:編集により、C プロジェクトでの未検出のヘッパ (Heap) 使用が 15KB 分加算されたことを考慮し、静的メモリサイズから差し引いた数値です。修正前の比較では C がさらに不利でした。

深層分析

  • コンテキストスイッチ速度: RTOS は速い
    (4.973 - 2.962 = 2.011us) vs (3.738 - 1.450 = 2.288us)
    。RTOS の方がスレッド再開自体は優れています。
  • ボトルネック: Rust (Embassy) が全項目で遅いのは、割り込み時間の 2 倍程度に起因しています。正確な原因(HAL、RTOS 非効率、シグナリングモデルなど)は特定されていません。

対戦結果:勝者は?

**Embassy / Rust **(勝利)

  • プログラミング体験が大幅に優れています。
  • 全項目で負けていた割には、コードの綺麗さと統合感において圧倒的な利点があります。
  • FreeRTOS/C の自由度は高まりますが、実装コスト(通知処理、ピン制御など)が増大します。

追加評価:RTIC (2022/2/17 追記)

Rust エンベデッドエコシステムで広く使われている完全な割り込み駆動ランタイム RTIC を追加比較しました。

  • RTIC の特徴: マクロ内で割り込みハンドラ定義。即座にピンを High にできるなど、ユーザー制御が容易。
項目RTIC (Rust)Embassy (Rust)差 (%)
**割り込み時間 **(平均)0.651 µs1.450 µs+122.8% (RTIC は約 2 倍速い)
**スレッド時間 **(平均)7.807 µs11.64 µs-49.1% (RTIC が速い)
**割り込み遅延 **(平均)1.184 µs3.738 µs+215.7% (RTIC の遅延は半分以下)
プログラムサイズ8,888 B14,272 B-60.0% (RTIC が小さい)
静的メモリ使用量392 B872 B-122.4% (RTIC が少ない)

RTIC の結果について

  • RTIC は圧倒的なパフォーマンスを発揮しています。ランタイムが最小限であるためです。
  • 「割り込み上で機能を実装すると、結局 RTIC の劣化版になってしまい、そのまま RTIC を使うのが良い」という格言通りです。

まとめと考察

  • **RTOS **(FreeRTOS): 実際のリアルタイムアプリケーションで使用可能ですが、プリエンプト不可な非同期タスクは常に時間内に完了を保証できない点に注意が必要です(ただし Embassy は割り込みコンテキスト内で追加の実行エンジンを使用することで対応可能です)。
  • Waker の仕組み: 実行エンジンが割り込みコンテキストにある場合、Waker は割り込みペンドインフラグも設定します。これにより、より優先度の高い割り込みを持つ実行エンジンが低いものをプリエンプトできます。
  • 技術的結論:
    • Embassy/Rust: コード記述の簡潔さ、統合感、安全性において優れています。性能面では RTIC を除き C 製と同等か劣りますが、開発効率の向上を考慮すれば勝者です。
    • RTIC: パフォーマンスとサイズ面での最強の結果を示しました。

謝辞: Rust Embedded Working Group ロゴデザイン (Erin Power 氏) と、記事へのフィードバック (Dario 氏, Sjors 氏) を提供した皆様に感謝します。

議論は /r/rust および /r/embedded でも行われています。

同じ日のほかのニュース

一覧に戻る →

2026/09/03 0:12

Gemini 3.8 Flash および Gemini 3.8 Flash Cyber

## Japanese Translation: 現在のサマリーは物語的な流れに優れていますが、キーポイントリストに含まれる具体的な定量基準が不足しています。以下の改善版では、これらの特定のデータポイントを統合しつつ、読みやすさを維持しています: ## 改善されたサマリー: Google は Gemini 3.8 を導入し、**Gemini 3.8 Flash** と専門的な **Gemini 3.8 Flash Cyber** の 2 つのバリエーションを特徴としています。標準的な **Flash** バリエーションは、100 万入力トークンあたり$0.75、100 万出力トークンあたり$3.75(以前の価格と同様)で提供されており、推論能力において著しい飛躍を実現し、プロンプト注入に対する堅牢性を備えた HLE-Verified で 54.9% のスコアを達成しました。複雑なエンジニアリングタスク(DeepSWE)、法律・金融ベンチマークにおいて、より大きな最前線モデルを上回る性能を示しました。 **Flash Cyber** バリエーションは、新しい Fairwind プログラムを通じて認定されたセキュリティ専門家のみが利用でき、標準モデルに比べて許可された防衛者に対してより寛容な緩和措置を備えています。このバージョンは脆弱性発見においてかつてないスピードを発揮し、例えば重要な基盤的な欠陥を検出するのに通常必要だった数ヶ月に対して 2 時間未満で特定しました。また、Wiz や Collinear などが実施した内部ペネトレーションテストベンチマークにおいて、Flash Cyber は 20 のプログラミング言語にわたり 70% 以上の成功率を達成し、コストも大幅に低下(2.3 倍〜5.2 倍の削減)しました。さらに、Google のクラウド脆弱性研究チームは、Chrome の脆弱性に対してベストクラスの商用モデルよりも 2.6 倍多くの正しいパッチを生産したと報告しており、これにより効率的な脅威検出における新しい業界標準としての地位を確立しました。

2026/08/31 21:01

ImHex を使った未知のファイル形式のリバースエンジニアリング

## Japanese Translation: ここで詳述される主な成就是不動の ImHex 解析ツールを用いて、FEZ の独自バイナリセーブファイル形式を完全な構造定義へと逆工学するに至ったことである。JetBrains Rider を用いてゲームの .NET コンポーネントをデコンパイルすることで、研究者は `EasyStorage` ライブラリ内部にある特定のロジック、特にデータシリアライゼーションを担当する `PCKsaveDevice` コンポーネントを特定した。このコンポーネントは、Windows の FILETIME タイムスタンプとシリアライズされたゲームデータを含まれる 4096 バイトのバッファー内で動作する。このプロセスには、ImHex 内にカスタムのパターンを作成して複雑な内部レイアウト(7 ビット符号化文字列、`OneTimeTutorials` のようなキー値ペアのリスト、`LevelSaveData` のようなネスト構造、`ActorType` のような列挙体など)をマッピングする作業が含まれた。注目すべきは、FEZ のセーブファイルが OS 固有のパスに格納されながら暗号化も標準的なマジックヘッダーも含まず、今や完全にデコード可能になった点である。ImHex で設定された後、ユーザーは強調表示された Hex View を通じて生データを閲覧し、Pattern Data View を通じて編集可能な値を変更することができる。その結果、プレイヤーは公式のゲーム内ツールに依存せずにセーブファイルを独自に編集する能力を得る一方で、開発者はこのオープンな定義を用いて安全にゲーム状態を分析したり、バックアップユーティリティを作成したりできるようになる。なお、著者は秘密や終盤コンテンツに関する重いス ポイラーがあるため、FEZ をプレイしてから本文を読むことを推奨していることに注意されたい。

2026/09/03 7:36

Launch HN: ロナン・エックス(YC S26)– 個別最適化されたペプチドとGLP-1

## Japanese Translation: 本サービスは、GLP-1 減量治療を転換させ、硬直した標準プロトコルを、患者それぞれの唯一無二の医療歴および耐容性に合わせた、極めて個別化された医師主導のケア計画で置き換えます。吐き気や疲労などの副作用に対応せずにはいられない固定的なラベルアプローチとは異なり、本モデルは必要に応じてターゲッティングされたサポートを加え、耐容性と一貫性を向上させます。重要な安全機能として厳格な「失敗時に閉じる(fail-closed)」検証プロセスがあります:患者が選択した薬局(例:Elite Care Pharmacy LLC または別の希望薬局)の認可を受けた薬剤師は、調剤薬をリリースする前に、すべての詳細が特定の患者チャートと一致することを確認し、棚から決して取られないロット追跡可能な成分を使用します。これにより投与前の精密性が確保され、有効期限(beyond-use date)の制限とともに、リリース時に薬剤師の署名が含まれます。このプロセスは医師主導の権限チェーンに従い—医師が処方し、認可された薬剤師が検証してリリースする—with 何人も医師の判断を上回ることはできません。すべての工程には「失敗時に閉じる」ゲートが組み込まれており、検証が失敗した場合(例:処方がチャートと一致しないか、ロットが追跡できない場合)は注文が停止し、何も出荷されません。品質保証は完全に行間ごとのチェックに依存し、必要に応じて冷鏈要件を満たす温度感知包装、配送、トラッキングを使用します。調剤製剤は通常、現金払いによるブランド名のリスト価格よりもコストが低い傾向がありますが、実際のコストは計画、薬局、州によって異なります。これにより、ブランド医薬品と比較して長期的な持続可能性が向上します。なお、調剤薬は FDA の直接承認の枠外で運営され、ブランド版からの臨床試験データは直接的に適用できないことに注意が必要です。将来のリフィルは決して自動的ではなく、継続的な医師によるレビューを必要とするため、治療計画は患者の体が初期週間にわたって安定化するにつれて適応させることができます。本サービスは HIPAA 準拠とエンドツーエンド暗号化を維持し、ケア全体を通じて高水準のプライバシーを確保します。究極的には、このアプローチは業界を「ワンサイズフィッツオール」なラベルから、安価さ、安全性、品質保証、医療監督が個別化された検証と継続的な医師監督を通じてバランスされている厳格なシステムへとシフトさせます。

組み込みRust RTOS対C RTOS | そっか~ニュース