Zephyr(RTOS)でCPU・スレッド負荷を確認してみました。
prj.confファイルに設定を書き込むだけで、RTOSでのCPU負荷が分かります。
実際にThread Analyzerを使った解析した例を紹介します。
Zephyr(RTOS)でCPU・スレッド負荷を確認してみた
Zephyr(RTOS)でCPU・スレッド負荷を確認してみました。
prj.confファイルに設定を書き込むだけで、RTOSでのCPU負荷が分かります。
実際にThread Analyzerを使った解析した例を紹介します。
はじめに
組み込み開発において、「原因不明のクラッシュ」や「システムの応答遅延」はつきものです。
その原因の多くは、スタックオーバーフローや特定のタスクによるCPU占有だったりします。
Zephyr RTOS には、これらを可視化する強力なツール 「Thread Analyzer(スレッドアナライザ)」 が標準で搭載されています。
今回は、設定ファイルに数行追加するだけで使えるこの機能の導入方法と、ログの見方を解説します。
1. Thread Analyzer とは?
Thread Analyzer は、Zephyr カーネル内で動作している各スレッド(タスク)の以下の情報を定期的にレポートしてくれる機能です。
- スタック使用量: 割り当てられたメモリのうち、どれくらい消費したか。
- スタック残量: あとどれくらい余裕があるか(オーバーフローの危険性)。
- CPU使用率: そのスレッドが CPU をどれくらい占有しているか。
特別なデバッグツール(J-Linkなど)を繋がなくても、シリアルコンソール(UART)だけでシステムの健康状態を監視できるのが最大のメリットです。
2. 有効化の手順 (prj.conf)
プロジェクトの設定ファイル prj.conf に以下の設定を追加するだけで有効になります。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# ============================================================================== # Thread Analyzer & Runtime Statistics # ============================================================================== # Thread Analyzer機能を有効化 CONFIG_THREAD_ANALYZER=y # 結果をprintk(シリアルコンソール)に出力 CONFIG_THREAD_ANALYZER_USE_PRINTK=y # 自動実行を有効化 CONFIG_THREAD_ANALYZER_AUTO=y # 実行間隔を秒単位で指定(ここでは5秒ごと) CONFIG_THREAD_ANALYZER_AUTO_INTERVAL=5 # スレッド名を表示(デバッグしやすくする) CONFIG_THREAD_NAME=y # CPU使用率の計測を有効化 CONFIG_SCHED_THREAD_USAGE=y CONFIG_SCHED_THREAD_USAGE_ALL=y |
3. ログ出力の見方
ビルドして書き込むと、指定した間隔(例:5秒)ごとに以下のようなログが流れてきます。
特にMainプログラムは何もしなくても、勝手に表示してくれます。
下記例では、加速度センサのEdgeAI処理をしている際に測定してみました。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
[00:00:27.987,080] <inf> main: Collecting 208 samples for the next inference... [00:00:29.883,032] <inf> main: Data collection complete. [00:00:29.921,301] <inf> main: Predictions (DSP: 37 ms, Classification: 0 ms, Anomaly: 0 ms): [00:00:29.921,318] <inf> main: circle: 0.00000 [00:00:29.921,329] <inf> main: flick: 0.00000 [00:00:29.921,339] <inf> main: idle: 0.99219 [00:00:29.921,350] <inf> main: updown: 0.00781 [00:00:29.921,358] <inf> main: anomaly score: -0.058 [00:00:29.921,364] <inf> main: Collecting 208 samples for the next inference... Thread analyze: thread_analyzer : STACK: unused 496 usage 528 / 1024 (51 %); CPU: 0 % : Total CPU cycles used: 5493 logging : STACK: unused 408 usage 616 / 1024 (60 %); CPU: 3 % : Total CPU cycles used: 1016597 idle : STACK: unused 272 usage 48 / 320 (15 %); CPU: 93 % : Total CPU cycles used: 28040473 main : STACK: unused 6752 usage 1440 / 8192 (17 %); CPU: 2 % : Total CPU cycles used: 898190 ISR0 : STACK: unused 1824 usage 224 / 2048 (10 %) [00:00:31.812,791] <inf> main: Data collection complete. [00:00:31.851,067] <inf> main: Predictions (DSP: 38 ms, Classification: 0 ms, Anomaly: 0 ms): [00:00:31.851,084] <inf> main: circle: 0.00000 [00:00:31.851,095] <inf> main: flick: 0.00000 [00:00:31.851,105] <inf> main: idle: 0.99609 [00:00:31.851,116] <inf> main: updown: 0.00391 [00:00:31.851,124] <inf> main: anomaly score: -0.060 [00:00:31.851,130] <inf> main: Collecting 208 samples for the next inference... |
実際にデータ収集中が大半を占めており、idle状態が93%のほぼであることが分かりました。
また別例として、ADCサンプリングの負荷をかけたものも実施しました。
adcのスレッドが44%と負荷をかけていることが分かります
|
1 2 3 4 5 6 7 8 9 10 11 12 |
Thread analyze: thread_analyzer : STACK: unused 464 usage 560 / 1024 (54 %); CPU: 0 % : Total CPU cycles used: 424501 adc_thread_id : STACK: unused 736 usage 288 / 1024 (28 %); CPU: 44 % : Total CPU cycles used: 48563822 logging : STACK: unused 408 usage 616 / 1024 (60 %); CPU: 2 % : Total CPU cycles used: 2860368 idle : STACK: unused 272 usage 48 / 320 (15 %); CPU: 48 % : Total CPU cycles used: 52800137 main : STACK: unused 6752 usage 1440 / 8192 (17 %); CPU: 3 % : Total CPU cycles used: 3708115 ISR0 : STACK: unused 1752 usage 296 / 2048 (14 %) |
STACK: unused (スタック残量)
最も重要な項目です。
- この数値が 0 に近いほど危険 です(スタックオーバーフロー寸前)。
- 逆に、この数値が大きすぎる(例:
unused 6752)場合は、メモリを無駄に確保しすぎている可能性があります。CONFIG_MAIN_STACK_SIZEなどを減らして RAM を節約できます。 - usage: これまでの最大使用量(ハイウォーターマーク)です。
CPU: % (CPU使用率)
- 計測期間内(例:5秒間)に、そのスレッドが CPU を使用した時間の割合です。
- idle: アイドル状態(何も処理していない時間)。この数値が高いほど、システムは余裕があり、省電力状態にあると言えます。
- main: メインループの負荷。ここが 100% に張り付いている場合、他の低優先度のタスクが動けなくなっている可能性があります。
ISR0 (割り込みスタック)
- Interrupt Service Routine の略です。
- スレッドではなく、タイマーや通信などの「ハードウェア割り込み処理」が使用する共有スタック領域です。
- ここが溢れるとシステムは即座にクラッシュします。
4. 活用テクニック
メモリのチューニング
開発初期はスタックサイズを大きめに確保しておき、Thread Analyzer で実際の使用量(usage)を確認します。 例えば usage 1440 なのに 8192 確保しているなら、2048 程度に減らすことで、他の機能にメモリを回すことができます。
CPU負荷の監視
「センサーの読み取り間隔を短くしたら動作が重くなった」という場合、main やセンサー処理スレッドの CPU 使用率を確認します。もし idle が 0% になっていたら、処理が追いついていません。
まとめ
Zephyr の Thread Analyzer は、コードを書かずに設定だけでシステムの「健康診断」ができる非常に便利な機能です。
- 開発中: 常時 ON にしてメモリリークやスタック溢れを監視。
- リリース時: オーバーヘッドになるため OFF にする(またはシェルコマンドから手動実行できるようにする)。
という使い分けがおすすめです。ぜひ活用して、堅牢な組み込みアプリケーション開発に役立ててください。

コメント