低レイテンシー操作のための RHEL 9 for Real Time の最適化
Red Hat Enterprise Linux での RHEL for Real Time カーネルの最適化
概要
Red Hat ドキュメントへのフィードバック (英語のみ) リンクのコピーリンクがクリップボードにコピーされました!
Red Hat ドキュメントに関するご意見やご感想をお寄せください。また、改善点があればお知らせください。
Jira からのフィードバック送信 (アカウントが必要)
- Jira の Web サイトにログインします。
- 上部のナビゲーションバーで Create をクリックします。
- Summary フィールドにわかりやすいタイトルを入力します。
- Description フィールドに、ドキュメントの改善に関するご意見を記入してください。ドキュメントの該当部分へのリンクも追加してください。
- ダイアログの下部にある Create をクリックします。
第1章 RHEL 9 におけるリアルタイムカーネルチューニング リンクのコピーリンクがクリップボードにコピーされました!
待ち時間、または応答時間は、イベントからの時間とシステム応答を指します。通常、マイクロ秒 (μs) で測定されます。
Linux 環境で実行されているほとんどのアプリケーションでは、基本的なパフォーマンスチューニングにより、レイテンシーを十分に改善できます。レイテンシーが低く、パフォーマンスの優劣に直結し、予測可能でなければならない業界向けに、Red Hat には、レイテンシーがそれらの要件を満たすようにチューニングできる代替のカーネルがあります。RHEL for Real Time カーネルは、RHEL 9 とのシームレスな統合を提供し、クライアントが組織内のレイテンシーを測定、設定、および記録する機会を提供します。
RHEL for Real Time カーネルは、適切にチューニングされたシステム上で、非常に高い決定論要件を持つアプリケーションに使用します。カーネルシステムをチューニングすると、決定論を大幅に向上させることができます。まず、標準の RHEL 9 システムの一般的なシステムチューニングを実行してから、RHEL for Real Time カーネルをデプロイします。
これらのタスクを実行しないと、RHEL for Real Time デプロイメントから一貫したパフォーマンスが得られなくなる可能性があります。
1.1. チューニングガイドライン リンクのコピーリンクがクリップボードにコピーされました!
リアルタイムチューニングは反復的なプロセスで、いくつかの変数を微調整するだけで最適な変更が得られることはありません。お使いのシステムに最適なチューニング設定のセットを絞り込むためには、数日または数週間かかると思ってください。
また、必ず長時間のテストを実行してください。あるチューニングパラメーターを変更してから 5 分間のテストを実行しても、特定のチューニング変更のセットを適切に検証したとは言えません。テストの長さを調整可能にして、数分間ではなくより長い時間実行してください。数時間のテストを実行して、いくつかの異なるチューニング設定のセットに絞り込み、それらのセットを一度に数時間から数日間実行することで、レイテンシーまたはリソース消費が大きい特殊なケースを検出できます。
- アプリケーションに測定メカニズムを構築し、特定のチューニング変更がアプリケーションのパフォーマンスにどのように影響を及ぼすかを正確に測定できるようにします。たとえば、"マウスの動きがよりスムーズになる" などの事例証拠は、正しくないことがほとんどで、人によって異なります。ハード的に測定を行い、後で分析できるようにそれらを記録します。
- テスト実行の間でチューニング変数に複数の変更を加えがちです。しかし、そうすると、テスト結果に影響を及ぼしたチューニングパラメーターを絞り込むことができなくなります。テスト間のチューニング変更は、可能な限り小さくします。
- また、チューニングを行う場合、大きな変更を加えがちですが、ほとんどの場合、増分変更を行う方が適切です。優先度の低い値から高い値に向かってテストを進めることで、長期的に見て良い結果が得られます。
-
利用可能なツールを使用してください。
tunaチューニングツールを使用すると、スレッドと割り込みに対するプロセッサーアフィニティー、スレッドの優先順位を簡単に変更したり、アプリケーションで使用するプロセッサーを分離したりできます。tasksetおよびchrtコマンドラインユーティリティーを使用すると、tunaが実行するほとんどのことを実行できます。パフォーマンスの問題が発生した場合、ftraceおよびperfユーティリティーがレイテンシーの問題の特定に役立ちます。 - アプリケーションで値をハードコーディングするのではなく、外部ツールを使用してポリシー、優先度、アフィニティーを変更します。外部ツールを使用すると、さまざまな組み合わせを試すことができ、ロジックが簡素化されます。良好な結果が得られる設定をいくつか見つけたら、それらをアプリケーションに追加するか、アプリケーションの起動時に設定が実装されるように起動ロジックを設定します。
1.2. スレッドスケジューリングポリシー リンクのコピーリンクがクリップボードにコピーされました!
Linux では、3 つの主要なスレッドスケジューリングポリシーが使用されます。
SCHED_OTHER(SCHED_NORMALとも呼ばれます)これはデフォルトのスレッドポリシーで、カーネルが制御する動的な優先度を持ちます。優先度はスレッドアクティビティーに基づいて変更されます。このポリシーを持つスレッドは、リアルタイム優先度が 0 と見なされます。
SCHED_FIFO(先入れ先出し)優先度の範囲が
1 - 99までのリアルタイムポリシー。ここでは、1が最も低く、99が最も高くなります。SCHED_FIFOスレッドは常にSCHED_OTHERスレッドよりも優先度が高くなります (たとえば、優先度が1のSCHED_FIFOスレッドは どのSCHED_OTHERスレッドよりも優先度が高くなります)。SCHED_FIFOスレッドとして作成されたスレッドの優先度はどれも固定され、優先度の高いスレッドによってブロックまたはプリエンプションされるまで実行されます。SCHED_RR(ラウンドロビン)SCHED_RRは、SCHED_FIFOを変更したものです。同じ優先度のスレッドにはクォンタムがあり、同じ優先度のすべてのSCHED_RRスレッド間でラウンドロビン方式でスケジュールされます。このポリシーはほとんど使用されません。
1.3. ロギングパラメーターのバランシング リンクのコピーリンクがクリップボードにコピーされました!
syslog サーバーは、プログラムからのログメッセージをネットワーク経由で送信します。送信の頻度が低いほど、保留中のトランザクションが大きくなる可能性があります。トランザクションが非常に大きい場合、I/O スパイクが発生する可能性があります。これを防ぐには、間隔を合理的な範囲で小さい値に維持します。
システムロギングデーモン syslogd は、さまざまなプログラムからメッセージを収集するために使用されます。また、カーネルが報告する情報をカーネルロギングデーモン klogd から収集します。通常、syslogd によりローカルファイルにログが記録されますが、リモートロギングサーバーにネットワーク経由でログを記録するように設定することもできます。
手順
リモートロギングを有効にするには、以下を実行します。
- ログの送信先となるマシンを設定します。詳細は、Red Hat Enterprise Linux での rsyslog を使用したリモート Syslog を参照してください。
ログをリモートログサーバーに送信する各システムを設定して、
syslog出力がローカルファイルシステムではなくサーバーに書き込まれるようにします。これを行うには、各クライアントシステムの/etc/rsyslog.confファイルを編集します。そのファイルで定義されているロギングルールごとに、ローカルログファイルをリモートロギングサーバーのアドレスに置き換えます。# Log all kernel messages to remote logging host. kern.* @my.remote.logging.server上記の例では、すべてのカーネルメッセージをリモートマシン (
@my.remote.logging.server) に記録するようにクライアントシステムを設定します。または、以下の行を
/etc/rsyslog.confファイルに追加して、ローカルに生成されたすべてのシステムメッセージをログに記録するようにsyslogdを設定できます。# Log all messages to a remote logging server: . @my.remote.logging.server
syslogd デーモンには、生成されたネットワークトラフィックに対する組み込みのレート制限は含まれていません。したがって、Red Hat は、RHEL for Real Time システムを使用する場合は、組織がリモートでのログ記録を要求するメッセージのみをログに記録することを推奨します。たとえば、カーネルの警告、認証要求などです。その他のメッセージはローカルに記録する必要があります。
1.4. 不要なアプリケーションの実行を回避することによるパフォーマンスの改善 リンクのコピーリンクがクリップボードにコピーされました!
実行中のアプリケーションはすべて、システムリソースを使用します。システムで不要なアプリケーションが実行されないようにすることで、パフォーマンスを大幅に向上させることができます。
前提条件
- システムの root 権限がある。
手順
絶対に必要とされない場所 (特にサーバー) では、グラフィカルインターフェイス を実行しないでください。
システムが、デフォルトで GUI で起動するように設定されているかどうかを確認します。
# systemctl get-defaultコマンドの出力が
graphical.targetの場合は、システムがテキストモードに起動するように設定します。# systemctl set-default multi-user.targetチューニングしているシステムで Mail Transfer Agent (MTA) をアクティブに使用している場合を除き、無効にしてください。MTA が必要な場合は、適切にチューニングされていることを確認するか、専用のマシンに移動することを検討してください。
詳細は MTA のドキュメントを参照してください。
重要MTA は、
cronなどのプログラムで実行されるシステム生成メッセージを送信するために使用されます。これには、logwatch()などのロギング機能によって生成されるレポートが含まれます。マシン上の MTA が無効になっていると、これらのメッセージを受信することはできません。マウス、キーボード、Web カムなどの 周辺機器 は、レイテンシーに悪影響を与える可能性のある割り込みを送信します。グラフィカルインターフェイスを使用していない場合は、未使用の周辺機器をすべて取り外して無効にします。
詳細は、デバイスのドキュメントを参照してください。
パフォーマンスに影響を及ぼす可能性のある自動
cronジョブの有無を確認します。# crontab -lcrondサービスまたは不要なcronジョブを無効にします。- サードパーティーのアプリケーションおよび外部のハードウェアベンダーが追加したコンポーネントの有無についてシステムを確認し、不要なものをすべて削除します。
関連情報
-
システム上の
cron(8)man ページ
1.5. 不均等メモリーアクセス (NUMA) リンクのコピーリンクがクリップボードにコピーされました!
taskset ユーティリティーは CPU アフィニティーでのみ機能し、メモリーノードなどの他の NUMA リソースは認識しません。プロセスバインディングを NUMA と併用する場合は、taskset の代わりに numactl を使用します。
NUMA API の詳細は、Andi Kleen 氏のホワイトペーパー An NUMA API for Linux を参照してください。
1.6. debugfs のマウントの確認 リンクのコピーリンクがクリップボードにコピーされました!
debugfs ファイルシステムは、デバッグや、ユーザーへの情報提供を目的として特別に設計されています。RHEL 8 では、これは /sys/kernel/debug/ ディレクトリーに自動的にマウントされます。
debugfs ファイルシステムは、ftrace コマンドおよび trace-cmd コマンドを使用してマウントされます。
手順
debugfs がマウントされていることを確認するには、以下を行います。
以下のコマンドを実行します。
# mount | grep ^debugfs debugfs on /sys/kernel/debug type debugfs (rw,nosuid,nodev,noexec,relatime,seclabel)debugfsがマウントされている場合は、debugfsのマウントポイントとプロパティーが表示されます。debugfsがマウントされていない場合は、何も返されません。
1.7. RHEL for Real Time の InfiniBand リンクのコピーリンクがクリップボードにコピーされました!
InfiniBand は、帯域幅を増やし、サービス品質 (QOS) を向上させ、フェイルオーバーを提供するためによく使用される通信アーキテクチャーの一種です。また、RDMA (Remote Direct Memory Access) メカニズムでのレイテンシー改善にも使用できます。
RHEL for Real Time での InfiniBand のサポートは、Red Hat Enterprise Linux 9 で利用可能なサポートと同じです。詳細は、InfiniBand および RDMA ネットワークの設定 を参照してください。
1.8. RoCEE および高パフォーマンスネットワークの使用 リンクのコピーリンクがクリップボードにコピーされました!
RoCEE (RDMA over Converged Enhanced Ethernet) は、イーサネットネットワークを介した RDMA (Remote Direct Memory Access) を実装するプロトコルです。これにより、重要なトランザクションに対して決定論ベースの低レイテンシーデータ転送を提供する一方で、データセンターで一貫性のある高速環境を維持できます。
High Performance Networking (HPN) は、RoCEE インターフェイスをカーネルに提供する共有ライブラリーセットです。HPN は、独立したネットワークインフラストラクチャーを経由する代わりに、標準のイーサネットインフラストラクチャーを使用してリモートシステムメモリーにデータを直接配置するため、CPU オーバーヘッドが少なく、インフラストラクチャーコストが削減されます。
RHEL for Real Time の RoCEE および HPN へのサポートは、RHEL 8 で提供されるサポートと同じです。
1.9. RHEL for Real Time のコンテナー調整 リンクのコピーリンクがクリップボードにコピーされました!
メイン RHEL カーネル上で実行されているコンテナーでリアルタイムのワークロードをテストする場合は、必要に応じて podman run コマンドに次のオプションを追加します。
-
--cpuset-cpus=<cpu_list>は、使用する分離 CPU コアのリストを指定します。複数の CPU がある場合は、コンテナーが使用できる CPU の範囲をコンマ区切りまたはハイフン区切りで指定します。 -
--cpuset-mems=<number-of-memory-nodes>は、使用する Non-Uniform Memory Access (NUMA) メモリーノードを指定します。そのため、NUMA ノード間のメモリーアクセスが回避されます。 -
--memory-reservation=<limit> <my_rt_container_image>は、コンテナーで実行されるリアルタイムのワークロードに必要な最小量のメモリーが、コンテナーの起動時に利用可能であることを確認します。
手順
コンテナーでリアルタイムのワークロードを起動します。
# podman run --cpuset-cpus=<cpu_list> --cpuset-mems=<number_of_memory_nodes> --memory-reservation=<limit> <my_rt_container_image>
第2章 RHEL for Real Time のスケジューリングポリシー リンクのコピーリンクがクリップボードにコピーされました!
リアルタイムでは、スケジューラーは、実行する実行可能なスレッドを決定するカーネルコンポーネントです。各スレッドには、関連付けられたスケジューリングポリシーおよび静的スケジューリング優先度 (sched_priority) があります。スケジューリングはプリエンプティブであるため、静的優先度の高いスレッドの実行の準備ができると、現在実行中のスレッドは停止します。その後、実行中のスレッドは静的優先度の waitlist に戻ります。
すべての Linux スレッドには、以下のいずれかのスケジューリングポリシーがあります。
-
SCHED_OTHERまたはSCHED_NORMAL: デフォルトのポリシーです。 -
SCHED_BATCH:SCHED_OTHERに似ていますが、増分指向です。 -
SCHED_IDLE:SCHED_OTHERより優先度の低いポリシーです。 -
SCHED_FIFO: 先入れ先出しのリアルタイムポリシーです。 -
SCHED_RR: ラウンドロビンのリアルタイムポリシーです。 -
SCHED_DEADLINE: ジョブの期限に従ってタスクに優先度を割り当てるスケジューラーポリシーです。絶対期限が最も早いジョブが最初に実行されます。
2.1. スケジューラーポリシー リンクのコピーリンクがクリップボードにコピーされました!
リアルタイムスレッドは標準スレッドよりも優先度が高くなります。ポリシーには、最小値 1 から最大値 99 までの範囲のスケジューリング優先順位値があります。
次のポリシーは、リアルタイムにとって重要です。
SCHED_OTHERまたはSCHED_NORMALポリシーこれは、Linux スレッドのデフォルトスケジューリングポリシーです。スレッドの特性に基づいてシステムによって変更される動的な優先度があります。
SCHED_OTHERスレッドの nice 値は、最高優先度の -20 から最低優先度の 19 までになります。SCHED_OTHERスレッドのデフォルトの nice 値は 0 です。SCHED_FIFOポリシーSCHED_FIFOを持つスレッドは、SCHED_OTHERタスクよりも高い優先度で実行されます。SCHED_FIFOは、nice 値を使用する代わりに、最低が 1 で最高が 99 の固定された優先度を使用します。優先度 1 のSCHED_FIFOスレッドは、SCHED_OTHERスレッドよりも常に先にスケジュールされます。SCHED_RRポリシーSCHED_RRポリシーは、SCHED_FIFOポリシーに似ています。同じ優先度のスレッドは、ラウンドロビン方式でスケジュールされます。SCHED_FIFOおよびSCHED_RRスレッドは以下のイベントのいずれかが発生するまで実行されます。- スレッドはスリープ状態になるか、イベントを待機します。
優先度の高いリアルタイムスレッドを実行する準備が整います。
上記のイベントのいずれかが発生しない限り、スレッドは指定されたプロセッサーで無期限に実行されますが、優先度の低いスレッドは実行を待機しているキューに残ります。これにより、システムサービススレッドが常駐し、スワップアウトが妨げられ、ファイルシステムデータのフラッシュが失敗する可能性があります。
SCHED_DEADLINEポリシーSCHED_DEADLINEポリシーはタイミング要件を指定します。タスクの期限に従って各タスクをスケジュールします。Earliest Deadline First (EDF) スケジュールを持つタスクが最初に実行されます。カーネルは、
runtime⇐deadline⇐periodが true である必要があります。必要なオプション間の関係は、runtime⇐deadline⇐periodです。
2.2. SCHED_DEADLINE ポリシーのパラメーター リンクのコピーリンクがクリップボードにコピーされました!
各 SCHED_DEADLINE タスクは、period、runtime、および deadline パラメーターによって特徴付けられます。これらのパラメーターの値は、ナノ秒の整数です。
| パラメーター | 説明 |
|---|---|
|
|
たとえば、ビデオ処理タスクで 1 秒あたり 60 フレームの処理が必要な場合、新しいフレームは 16 ミリ秒ごとにサービスのキューに入れられます。したがって、 |
|
|
たとえば、ビデオ処理ツールが画像を処理するのに最悪の場合で 5 ミリ秒かかる場合、 |
|
|
たとえば、タスクが処理されたフレームを 10 ミリ秒以内に配信する必要がある場合、 |
2.3. SCHED_DEADLINE パラメーターの設定 リンクのコピーリンクがクリップボードにコピーされました!
Red Hat Enterprise Linux の sched_deadline_period_max_us および sched_deadline_period_min_us パラメーターは、SCHED_DEADLINE スケジューリングポリシーの調整可能なカーネルパラメーターです。これらのパラメーターは、このリアルタイムスケジューリングクラスを使用して、タスクの最大および最小許容期間をマイクロ秒単位で制御します。
sched_deadline_period_max_us と sched_deadline_period_min_us は連携して機能し、SCHED_DEADLINE タスクの期間値の許容範囲を定義します。
-
min_usは、リソースを過剰に使用する可能性のある高頻度タスクを防止します。 -
max_usは、他のタスクのパフォーマンス低下につながる可能性のある、非常に長い期間のタスクを防止します。
パラメーターのデフォルト設定を使用してください。パラメーターの値を変更する必要がある場合は、ライブ環境で設定する前に、カスタム値を必ずテストしてください。
パラメーターの値はマイクロ秒単位です。たとえば、1 秒は 100000 マイクロ秒に相当します。
前提条件
- システムの root 権限がある。
手順
sysctlコマンドのいずれかを使用して、必要な値を一時的に設定します。sched_deadline_period_max_usパラメーターを使用するには、次のコマンドを実行します。# sysctl -w kernel.sched_deadline_period_max_us=2000000sched_deadline_period_min_usパラメーターを使用するには、次のコマンドを実行します。# sysctl -w kernel.sched_deadline_period_min_us=100
値を永続的に設定します。
max_usの場合、/etc/sysctl.confを編集して次の行を追加します。kernel.sched_deadline_period_max_us = 2000000min_usの場合、/etc/sysctl.confを編集して次の行を追加します。kernel.sched_deadline_period_min_us = 100
変更を適用します。
# sysctl -p
検証
max_usのカスタム値を確認します。$ cat /proc/sys/kernel/sched_deadline_period_max_us 2000000min_usのカスタム値を確認します。$ cat /proc/sys/kernel/sched_deadline_period_min_us 100
第3章 永続的なカーネルチューニングパラメーターの設定 リンクのコピーリンクがクリップボードにコピーされました!
システムで機能するチューニング設定を決定したら、変更を永続化して再起動後も維持できます。
デフォルトでは、編集したカーネルチューニングパラメーターは、システムが再起動するか、パラメーターが明示的に変更されるまで有効になります。この方法は、初期チューニング設定を確立するために有効です。また、安全性のメカニズムも提供します。編集したパラメーターによって、マシンの動作が不安定になった場合、マシンを再起動すると、パラメーターが以前の設定に戻ります。
3.1. カーネルチューニングパラメーターの変更の永続化 リンクのコピーリンクがクリップボードにコピーされました!
パラメーターを /etc/sysctl.conf ファイルに追加することにより、カーネルチューニングパラメーターに永続的な変更を加えることができます。
この手順では、現在のセッションのカーネルチューニングパラメーターは 変更されません。/etc/sysctl.conf に入力した変更は、今後のセッションにのみ影響します。
前提条件
- システムの root 権限がある。
手順
-
テキストエディターで
/etc/sysctl.confを開きます。 パラメーターの値を使用して、新規エントリーをファイルに挿入します。
/proc/sys/パスを削除し、残りのスラッシュ (/) をピリオド (.) に変更して、パラメーターの値を追加することで、パラメーター名を変更します。たとえば、
echo 0 > /proc/sys/kernel/hung_task_panicコマンドを永続化するには、以下を/etc/sysctl.confに入力します。# Enable gettimeofday(2) kernel.hung_task_panic = 0- ファイルを保存してから閉じます。
- システムを再起動して、変更を有効にします。
検証
設定を確認するには、以下を実行します。
# cat /proc/sys/kernel/hung_task_panic 0
第4章 アプリケーションのチューニングとデプロイメント リンクのコピーリンクがクリップボードにコピーされました!
最適な設定を組み合わせてリアルタイムカーネルをチューニングすると、RHEL for Real Time アプリケーションの改良と開発に役立ちます。
一般に、POSIX 定義の API (アプリケーションプログラミングインターフェイス) を使用するようにしてください。RHEL for Real Time は POSIX 標準に準拠しています。RHEL for Real Time カーネルのレイテンシー削減も、POSIX をベースにしています。
4.1. リアルタイムアプリケーションでのシグナル処理 リンクのコピーリンクがクリップボードにコピーされました!
従来の UNIX および POSIX シグナルは、特にエラー処理に使用されますが、リアルタイムアプリケーションでのイベント配信メカニズムとしての使用には適していません。その理由は、現在の Linux カーネルシグナル処理コードが、非常に複雑なためです。これは主に、従来の動作と多くの API をサポートする必要があるためです。この複雑さは、シグナルの配信時に使用されるコードパスが常に最適とは限らず、アプリケーションでレイテンシーが長くなる可能性があることを意味します。
UNIX シグナルの本来の目的は、実行の異なる "スレッド" 間で 1 つの制御スレッド (プロセス) を多重化することでした。シグナルはオペレーティングシステムの割り込みのように動作します。つまり、シグナルがアプリケーションに配信されると、アプリケーションのコンテキストが保存され、事前に登録したシグナルハンドラーの実行を開始します。シグナルハンドラーが完了すると、アプリケーションはシグナルの配信時の地点から処理を再開します。この動作は、実際には複雑になる可能性があります。
シグナルは、決定論ベースではないので、リアルタイムアプリケーションでは信頼できません。POSIX スレッド (pthreads) を使用してワークロードを分散し、さまざまなコンポーネント間の通信を行うことが望ましいオプションです。ミューテックスの pthreads メカニズム、条件変数、およびバリアを使用して、スレッドのグループを調整できます。このような比較的新しい構造によるコードパスは、シグナルに対する従来の処理コードよりもはるかにクリーンです。
4.2. スレッドの同期 リンクのコピーリンクがクリップボードにコピーされました!
sched_yield 機能は、優先度の低いスレッドを実行できる同期メカニズムです。このタイプの要求は、適切に作成されていないアプリケーション内から発行すると失敗する可能性があります。
優先度が高いスレッドは sched_yield() を呼び出して、他のスレッドに実行の機会を与えることができます。呼び出しプロセスは、その優先度で実行されているプロセスのキューの末尾に移動します。これは、同じ優先度で他のプロセスが実行していない状況で発生すると、呼び出しプロセスの実行は継続されます。プロセスの優先度が高い場合は、ビジーループが発生し、マシンが使用できなくなる可能性があります。
SCHED_DEADLINE タスクが sched_yield() を呼び出すと、設定された CPU が放棄され、残りのランタイムには次の期間まで直ちにスロットリングが適用されます。sched_yield() の動作により、タスクは次の期間の開始時に起動できます。
スケジューラーは、実際に実行する他のスレッドがあるかどうかを判別できます。リアルタイムタスクで sched_yield() は使用しないでください。
手順
sched_yield()関数を呼び出すには、以下のコードを実行します。for(;;) { do_the_computation(); /* * Notify the scheduler at the end of the computation * This syscall will block until the next replenishment */ sched_yield(); }SCHED_DEADLINEタスクには、次の期間 (次のループ実行を開始する) まで、競合ベースの検索 (CBS) アルゴリズムによってスロットリングが適用されます。
4.3. リアルタイムスケジューラーの優先度 リンクのコピーリンクがクリップボードにコピーされました!
systemd は、システムの起動時に実行するサービスのリアルタイムの優先度を設定します。一部のカーネルスレッドには非常に高い優先度が設定される場合があります。これにより、デフォルトの優先度を Real Time Specification for Java (RTSJ) の要件と適切に統合することができます。RTSJ には 10 から 89 までの優先度の範囲が必要です。
RTSJ が使用されていないデプロイメントでは、アプリケーションが使用できるスケジューリングの優先度が幅広くあります (90 未満)。重要なシステムサービスが実行されなくなる可能性があるため、49 を超える優先度をスケジューリングする場合は細心の注意を払ってください。これには、ファイルシステムのジャーナリングがブロックされ、ファイルシステムジャーナリングがブロックされているため、予測できない動作(ネットワークトラフィックのブロック、仮想メモリーのページングのブロック、データ破損など)が発生する可能性があります。
アプリケーションスレッドが優先度 89 を超えてスケジュールされている場合は、スレッドが非常に短いコードパスのみを実行するようにしてください。これを行わないと、RHEL for Real Time カーネルの低レイテンシー機能が損なわれます。
必須の権限を持たないユーザーに対するリアルタイム優先度の設定
デフォルトでは、アプリケーションに対して root 権限を持つユーザーのみが優先度とスケジュール情報を変更できます。root 権限を付与するには、設定を変更します。推奨される方法は、ユーザーを realtime グループに追加することです。
また、/etc/security/limits.conf ファイルを編集して、ユーザー権限を変更することもできます。ただし、これにより重複が発生し、通常のユーザーがシステムを使用できなくなる可能性があります。このファイルを編集する場合は、変更を行う前に必ずコピーを作成してください。
4.4. 動的ライブラリーの読み込み リンクのコピーリンクがクリップボードにコピーされました!
リアルタイムアプリケーションの開発時には、プログラムの実行中に決定論ベースではないレイテンシーが発生しないように、システムの起動時にシンボルを解決することを検討してください。システムの起動時にシンボルを解決すると、プログラムの初期化に時間がかかる場合があります。動的リンカー/ローダーである ld.so を使用して LD_BIND_NOW 変数を設定することにより、動的ライブラリーをアプリケーションの起動時に読み込むように指示できます。
たとえば、このスクリプトは LD_BIND_NOW 変数を 1 の値でエクスポートしてから、FIFO のスケジューラーポリシーと 1 の優先度でプログラムを実行します。
#!/bin/sh
LD_BIND_NOW=1
export LD_BIND_NOW
chrt --fifo 1 /opt/myapp/myapp-server &
第5章 システムチューニング用の BIOS パラメーターの設定 リンクのコピーリンクがクリップボードにコピーされました!
BIOS は、システムの機能において重要な役割を果たします。BIOS パラメーターを正しく設定すると、システムのパフォーマンスを大幅に向上できます。
システムおよび BIOS ベンダーはすべて、さまざまな用語とナビゲーション方法を使用します。BIOS 設定の詳細は、BIOS のドキュメントを参照するか、BIOS ベンダーにお問い合わせください。
5.1. 電源管理の無効化による応答時間の改善 リンクのコピーリンクがクリップボードにコピーされました!
BIOS 電源管理オプションは、システムクロックの周波数を変更したり、CPU をさまざまなスリープ状態の 1 つにすることで、電力を節約できるようにします。このようなアクションは、システムが外部イベントに応答する速度に影響を与える可能性があります。
応答時間を改善するには、BIOS の電源管理オプションをすべて無効にします。
5.2. エラー検出と修正ユニットの無効化による応答時間の改善 リンクのコピーリンクがクリップボードにコピーされました!
Error Detection and Correction (EDAC) ユニットは、Error Correcting Code (ECC) メモリーから通知されたエラーを検出および修正するためのデバイスです。通常 EDAC には、ECC をチェックしないオプションから、エラーに関するすべてのメモリーノードを定期的にスキャンするオプションまで、さまざまなオプションがあります。EDAC レベルが高いほど、BIOS が使用する時間が長くなります。これにより、重要なイベントの期限を逃す可能性があります。
応答時間を改善するには、EDAC をオフにします。これができない場合は、EDAC を最小機能レベルに設定します。
5.3. システム管理割り込みの設定による応答時間の改善 リンクのコピーリンクがクリップボードにコピーされました!
System Management Interrupts (SMI) は、システムが正常に動作していることを確認するハードウェアベンダーの機能です。BIOS コードは、通常、SMI 割り込みを処理します。SMI は通常、温度管理、リモートコンソール管理 (IPMI)、EDAC チェック、およびその他のハウスキーピングタスクに使用されます。
BIOS に SMI オプションが含まれる場合は、ベンダーおよび関連ドキュメントを確認して、それらを無効にしても安全な範囲を判断してください。
SMI を完全に無効にすることは可能ですが、Red Hat ではこれを行わないことを強く推奨します。SMI を生成してサービスするシステムの機能を削除すると、壊滅的なハードウェア障害が発生する可能性があります。
第6章 リアルタイムカーネルのランタイム検証 リンクのコピーリンクがクリップボードにコピーされました!
ランタイム検証は、システムイベントとその正式な仕様における動作等価性をチェックするための軽量かつ厳密な方法です。ランタイム検証では、tracepoints に接続するカーネルに統合されたモニターを使用します。システムの状態が定義された仕様から逸脱した場合、ランタイム検証プログラムはリアクターをアクティブにして、ログファイルにイベントをキャプチャーしたり、極端なケースでは障害伝播を防止するためにシステムをシャットダウンしたりするなどの対応を、通知するか可能にします。
6.1. ランタイムモニターとリアクター リンクのコピーリンクがクリップボードにコピーされました!
ランタイム検証 (RV) モニターは、RV モニター抽象概念にカプセル化され、定義された仕様とカーネルトレースの間で調整を行い、ランタイムイベントをトレースファイルにキャプチャーします。RV モニターには以下が含まれます。
- 参照モデル。これはシステムの参照モデルです。
- モニターインスタンス。これは、CPU ごとのモニターやタスクごとのモニターなどの、モニターのインスタンスのセットです。
- モニターをシステムに接続するヘルパー関数。
ランタイム時にシステムを検証および監視することに加えて、予期しないシステムイベントへの応答を有効にすることができます。反応の形式は、トレースファイルへのイベントのキャプチャーから、極端な反応 (安全性が重要なシステムでシステム障害を回避するためのシャットダウンなど) の開始まで、さまざまです。
リアクターは、必要に応じてシステムイベントへの反応を RV モニターが定義するために使用できる反応方法です。デフォルトでは、モニターはアクションのトレース出力を提供します。
6.2. オンラインランタイムモニター リンクのコピーリンクがクリップボードにコピーされました!
ランタイム検証 (RV) モニターは次のタイプに分類されます。
オンラインモニターは、システムの実行中にトレースにイベントをキャプチャーします。
イベント処理がシステム実行に関連付けられている場合、オンラインモニターは同期されます。これにより、イベント監視中はシステムがブロックされます。オンラインモニターは、実行がシステムから切り離されて別のマシンで実行される場合は非同期です。ただし、その場合は保存された実行ログファイルが必要です。
オフラインモニターは、イベントの発生後に生成されるトレースを処理します。
オフラインのランタイム検証は、保存されたトレースログファイルを通常は永続ストレージから読み取ることによって情報をキャプチャーします。オフラインモニターは、イベントがファイルに保存されている場合にのみ機能します。
6.3. ユーザーインターフェイス リンクのコピーリンクがクリップボードにコピーされました!
ユーザーインターフェイスは /sys/kernel/tracing/rv にあり、トレースインターフェイスに類似しています。ユーザーインターフェイスには、以下のファイルとフォルダーが含まれています。
| Settings | 説明 | コマンドの例 |
|---|---|---|
|
| 利用可能なモニターを 1 行に 1 つずつ表示します。 |
|
|
| 利用可能なリアクターを 1 行に 1 つずつ表示します。 |
|
|
| 有効なモニターを 1 行に 1 つずつ表示します。複数のモニターを同時に有効にすることができます。 モニター名に '!' 接頭辞を付けて入力すると当該モニターが無効になり、ファイルを切り捨てると有効なモニターがすべて無効になります。 |
|
|
|
|
|
|
|
利用可能なリアクターをリスト表示します。特定のモニターに対して選択された反応を "[]" 内に表示します。デフォルトは、操作なし ( リアクターの名前を書き込むと、そのリアクターが特定のモニターに統合されます。 |
|
|
|
トレースインターフェイスで
| |
|
|
リアクターを有効にします。 | |
|
| モニターの説明を表示します | |
|
|
モニターの現在のステータスを表示します。 |
第7章 ハードウェアおよびファームウェアのレイテンシーテストの実行および解釈 リンクのコピーリンクがクリップボードにコピーされました!
hwlatdetect プログラムを使用すると、潜在的なハードウェアプラットフォームがリアルタイム操作の使用に適しているかどうかをテストして検証できます。
前提条件
-
RHEL-RT(RHEL for Real Time) パッケージおよびrealtime-testsパッケージがインストールされている。 低レイテンシー操作に必要なチューニング手順は、ベンダーのドキュメントを参照してください。
ベンダーのドキュメントは、システムを System Management Mode (SMM) に移行する System Management Interrupts (SMI) を減らしたり、削除したりする手順を提供できます。システムが SMM にある間、ファームウェアを実行し、オペレーティングシステムのコードは実行しません。これは、SMM にある間にタイプアップするすべてのタイマーが、システムが通常の操作に戻るまで待機することを意味します。Linux では SMI をブロックできないため、これにより原因不明のレイテンシーが発生する可能性があります。実際に SMI を取得したことを示す唯一の兆候は、ベンダー固有のパフォーマンスカウンターレジスターにしかありません。
警告致命的なハードウェア障害が発生する可能性があるため、Red Hat は SMI を完全に無効にしないことを強く推奨します。
7.1. ハードウェアおよびファームウェアのレイテンシーテストの実行 リンクのコピーリンクがクリップボードにコピーされました!
テストは、ハードウェアアーキテクチャー、または BIOS もしくは EFI ファームウェアに起因する遅延を検出するため、hwlatdetect プログラムの実行中にシステムに負荷を掛ける必要はありません。hwlatdetect のデフォルト値では、毎秒 0.5 秒間ポーリングを行い、時刻を取得する連続した呼び出しの間に 10 マイクロ秒を超えるギャップがあれば、それを報告します。hwlatdetect は、システムで 最大限保証可能な 最大レイテンシーを返します。したがって、10μs 未満の最大レイテンシー値を要求するアプリケーションがある場合、hwlatdetect がギャップの 1 つを 20μs と報告する場合、システムは 20μs のレイテンシーしか保証できません。
hwlatdetect が、システムがアプリケーションのレイテンシー要件を満たせないことを示した場合は、BIOS 設定を変更するか、システムベンダーと協力して、アプリケーションのレイテンシー要件を満たす新しいファームウェアを入手してみてください。
前提条件
RHEL-RT および realtime-tests パッケージがインストールされている。
手順
hwlatdetectを実行し、テスト期間を秒単位で指定します。hwlatdetectは、クロックソースをポーリングし、原因不明のギャップを探すことにより、ハードウェアおよびファームウェアに起因するレイテンシーを探します。# hwlatdetect --duration=60s hwlatdetect: test duration 60 seconds detector: tracer parameters: Latency threshold: 10us Sample window: 1000000us Sample width: 500000us Non-sampling period: 500000us Output File: None Starting test test finished Max Latency: Below threshold Samples recorded: 0 Samples exceeding threshold: 0
7.2. ハードウェアおよびファームウェアのレイテンシーテストの解釈 リンクのコピーリンクがクリップボードにコピーされました!
ハードウェア遅延検出器 (hwlatdetect) は、トレーサーメカニズムを使用して、ハードウェアアーキテクチャーまたは BIOS/EFI ファームウェアによる遅延を検出します。hwlatdetect によって測定された遅延をチェックすることで、潜在的なハードウェアが RHEL for Real Time カーネルのサポートに適しているかどうかを判断できます。
例
この結果の例は、ファームウェアによるシステム中断を最小限に抑えるように調整されたシステムを表しています。このような場合、
hwlatdetectの出力は以下のようになります。# hwlatdetect --duration=60s hwlatdetect: test duration 60 seconds detector: tracer parameters: Latency threshold: 10us Sample window: 1000000us Sample width: 500000us Non-sampling period: 500000us Output File: None Starting test test finished Max Latency: Below threshold Samples recorded: 0 Samples exceeding threshold: 0この結果の例は、ファームウェアによるシステムの中断を最小限に抑えるようにチューニングできなかったシステムを表しています。このような場合、
hwlatdetectの出力は以下のようになります。# hwlatdetect --duration=10s hwlatdetect: test duration 10 seconds detector: tracer parameters: Latency threshold: 10us Sample window: 1000000us Sample width: 500000us Non-sampling period: 500000us Output File: None Starting test test finished Max Latency: 18us Samples recorded: 10 Samples exceeding threshold: 10 SMIs during run: 0 ts: 1519674281.220664736, inner:17, outer:15 ts: 1519674282.721666674, inner:18, outer:17 ts: 1519674283.722667966, inner:16, outer:17 ts: 1519674284.723669259, inner:17, outer:18 ts: 1519674285.724670551, inner:16, outer:17 ts: 1519674286.725671843, inner:17, outer:17 ts: 1519674287.726673136, inner:17, outer:16 ts: 1519674288.727674428, inner:16, outer:18 ts: 1519674289.728675721, inner:17, outer:17 ts: 1519674290.729677013, inner:18, outer:17----この出力は、システム
clocksourceの連続読み取り中に、15-18 us の範囲で 10 回の遅延が発生したことを示しています。注記以前のバージョンでは、
ftraceトレーサーではなくカーネルモジュールを使用していました。
結果について
テスト方法、パラメーター、および結果に関する情報は、hwlatdetect ユーティリティーによって検出された遅延パラメーターと遅延値を理解するのに役立ちます。
テスト方法、パラメーター、および結果の表には、hwlatdetect ユーティリティーによって検出されたパラメーターと遅延値が記載されています。
| パラメーター | 値 | 説明 |
|---|---|---|
|
|
| テストの期間 (秒単位) |
|
|
|
|
|
| ||
|
|
| 許容可能な最大レイテンシー |
|
|
| 1 秒 |
|
|
| 0.05 秒 |
|
|
| 0.05 秒 |
|
|
| 出力が保存されるファイル。 |
|
| ||
|
|
|
|
|
|
| テストによって記録されたサンプルの数。 |
|
|
|
テストによって記録された、レイテンシーが |
|
|
| テストの実行中に発生した System Management Interrupts (SMI) の数。 |
内部および外部の hwlatdetect ユーティリティーによって出力される値は、最大レイテンシー値です。これらは、現在のシステムクロックソース (通常は TSC または TSC レジスターですが、HPET または ACPI 電力管理クロックの可能性があります) の連続した読み取り間のデルタと、ハードウェアとファームウェアの組み合わせによって導入された連続した読み取り間の遅延です。
適切なハードウェアとファームウェアの組み合わせを見つけたら、次のステップは、負荷がかかった状態でシステムのリアルタイムパフォーマンスをテストすることです。
第8章 システムレイテンシーテストの実行および解釈 リンクのコピーリンクがクリップボードにコピーされました!
RHEL for Real Time は、負荷がかかった状態でシステムのリアルタイムパフォーマンスをテストするための rteval ユーティリティーを提供します。
8.1. システムレイテンシーテストの実行 リンクのコピーリンクがクリップボードにコピーされました!
rteval ユーティリティーを使用すると、負荷がかかった状態でシステムのリアルタイムパフォーマンスをテストできます。
前提条件
-
RHEL for Real Timeパッケージグループがインストールされている。 - システムの root 権限がある。
手順
rtevalユーティリティーを実行します。# rtevalrtevalユーティリティーは、SCHED_OTHERタスクの高いシステム負荷を開始します。次に、それぞれのオンライン CPU でリアルタイムの応答を測定します。負荷は、ループの Linux カーネルツリーとhackbenchの合成ベンチマークの並列のmakeになります。その目的は、システムを、それぞれのコアに常にスケジュールするジョブがある状態にすることです。ジョブは、メモリーの割り当て/解放、ディスク I/O、コンピュートタスク、メモリーコピーなどのさまざまなタスクを実行します。
負荷が開始されると、
rtevalはcyclictest測定プログラムを開始します。このプログラムは、各オンラインコアでSCHED_FIFOリアルタイムスレッドを起動します。その後、リアルタイムスケジューリングの応答時間を測定します。各測定スレッドはタイムスタンプを取得し、ある間隔スリープした後、ウェイクアップ後に再度タイムスタンプを取得します。測定されたレイテンシーは
t1 - (t0 + i)です。これは、実際のウェイクアップ時刻t1と、最初のタイムスタンプの理論的なウェイクアップ時刻t0にスリープ間隔iを加えたものとの差になります。rteval実行の詳細は、システムのブートログと共に XML ファイルに書き込まれます。このレポートは画面に表示され、圧縮されたファイルに保存されます。ファイル名は
rteval-<date>-N-tar.bz2の形式になっています。ここで、<date>はレポートが生成された日付に置き換えます。Nは<date>の N 番目の実行のカウンターになります。以下は、
rtevalレポートの例です。System: Statistics: Samples: 1440463955 Mean: 4.40624790712us Median: 0.0us Mode: 4us Range: 54us Min: 2us Max: 56us Mean Absolute Dev: 1.0776661507us Std.dev: 1.81821060672us CPU core 0 Priority: 95 Statistics: Samples: 36011847 Mean: 5.46434910711us Median: 4us Mode: 4us Range: 38us Min: 2us Max: 40us Mean Absolute Dev: 2.13785341159us Std.dev: 3.50155558554usレポートには、システムハードウェア、実行の長さ、使用したオプション、およびタイミング結果 (CPU ごとおよびシステム全体) の詳細が表示されます。
注記生成されたファイルから
rtevalレポートを再生成するには、以下を実行します。# rteval --summarize rteval-<date>-N.tar.bz2
第9章 リアルタイムタスク実行のための rteval コンテナーの使用 リンクのコピーリンクがクリップボードにコピーされました!
Red Hat Enterprise Linux (RHEL) for Real Time の rteval (リアルタイム評価)コンテナーにより、重要なタスクの実行が低レイテンシーになります。リアルタイムの応答を維持し、タスクの実行を保証するために、さまざまなシステムの負荷下でタイマーウェイクタイムを測定します。
rteval ツールは、( cyclictest や rtlaなどのツールを使用して)測定プロセスを優先度の高いタスクとして設定します。この測定プロセスは、マシンで生成された負荷よりも優先されます。その結果、rteval コンテナーは、異なる負荷のリアルタイムタスクのウェイクアップ時間を測定し、システムがリアルタイムのワークロードを効果的に処理できるようにします。
9.1. rteval コンテナーのホストのテスト リンクのコピーリンクがクリップボードにコピーされました!
レイテンシーの影響を受けやすいワークロードで rteval コンテナーを実行するには、コンテナーテクノロジーが仮想化スタックで追加のカーネルを必要としないため、ホストマシンを調整する必要があります。ベアメタルに適用されるほとんどのチューニングストラテジーは、コンテナー環境にも適用されます。
ファイルで定義されたデフォルトのパラメーターを使用して、realtime -variables.conftuned-adm でリアルタイムプロファイルを適用する必要があります。
リアルタイム プロファイルは、次のタスクを実行します。
- さまざまなカーネルコマンドラインオプションを設定します。
- NUMA (Non-Uniform Memory Access)トポロジーを検出します。
-
複数の NUMA ノードが存在する場合、各ノードの最初の CPU を除くすべての CPU を
isolcpusセットに割り当てます。
rteval コンテナー用のホストマシンを設定します。
前提条件
- ホストマシンが Red Hat Enterprise Linux バージョン 9.6 以降で実行されている。
-
tunedパッケージおよびtuned-profiles-realtimeパッケージがインストールされている。 -
tunedサービスを実行している。 -
podmanアプリケーションがインストールされ、実行されている。
手順
必要なパッケージをインストールします。
$ sudo dnf install rteval kernel-rt podman -yインストールされたカーネルを表示します。
$ sudo grubby --info=ALL index=0 kernel="/boot/vmlinuz-5.XX.0-XX.X.X.el9_6.x86_64+rt" args="ro crashkernel=2G-64G:256M,64G-:512M resume=UUID=3e14acf4-a359-4045-b8fc-990ff83743ec rd.lvm.lv=rhel_rt-qe-11/root rd.lvm.lv=rhel_rt-qe-11/swap console=ttyS0,115200n81 $tuned_params" root="/dev/mapper/rhel_rt--qe--11-root" initrd="/boot/initramfs-5.XX.0-XX.X.X.el9_6.x86_64+rt.img $tuned_initrd" title="Red Hat Enterprise Linux (5.XX.0-XX.X.X.el9_6.x86_64+rt) 9.6 (Plow)" id="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-5.XX.0-XX.X.X.el9_6.x86_64+rt" index=1 kernel="/boot/vmlinuz-5.XX.0-XX.X.X.el9_6.x86_64" args="ro crashkernel=2G-64G:256M,64G-:512M resume=UUID=3e14acf4-a359-4045-b8fc-990ff83743ec rd.lvm.lv=rhel_rt-qe-11/root rd.lvm.lv=rhel_rt-qe-11/swap console=ttyS0,115200n81 $tuned_params" root="/dev/mapper/rhel_rt--qe--11-root" initrd="/boot/initramfs-5.XX.0-XX.X.X.el9_6.x86_64.img $tuned_initrd" title="Red Hat Enterprise Linux (5.XX.0-XX.X.X.el9_6.x86_64) 9.6 (Plow)" id="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-5.XX.0-XX.X.X.el9_6.x86_64" index=2 kernel="/boot/vmlinuz-0-rescue-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" args="ro crashkernel=2G-64G:256M,64G-:512M resume=UUID=3e14acf4-a359-4045-b8fc-990ff83743ec rd.lvm.lv=rhel_rt-qe-11/root rd.lvm.lv=rhel_rt-qe-11/swap console=ttyS0,115200n81" root="/dev/mapper/rhel_rt--qe--11-root" initrd="/boot/initramfs-0-rescue-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.img" title="Red Hat Enterprise Linux (0-rescue-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX) 9.6 (Plow)" id="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-0-rescue"リアルタイムカーネルをデフォルトのカーネルとして設定します。
$ select a in /boot/vmlinuz-*rt*; do grubby --set-default=$a; break; donetuned-admを使用してリアルタイムプロファイルを適用します。$ sudo tuned-adm profile realtimeホストマシンを再起動します。
$ sudo reboot
検証
カーネルのバージョンおよびチューニングパラメーターを検証します。
$ sudo uname -r 5.XX.0-XX.X.X.el9_6.x86_64+rt$ sudo cat /proc/cmdline BOOT_IMAGE=(hd0,gpt2)/vmlinuz-5.XX.0-XX.X.X.el9_6.x86_64+rt root=/dev/mapper/rhel_rt--qe--11-root ro crashkernel=2G-64G:256M,64G-:512M resume=UUID=3e14acf4-a359-4045-b8fc-990ff83743ec rd.lvm.lv=rhel_rt-qe-11/root rd.lvm.lv=rhel_rt-qe-11/swap console=ttyS0,115200n81 skew_tick=1 tsc=reliable rcupdate.rcu_normal_after_boot=1 isolcpus=managed_irq,domain,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,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47 intel_pstate=disable nosoftlockup
9.2. ベースライン結果についてベアメタルのテスト リンクのコピーリンクがクリップボードにコピーされました!
基本的なオペレーティングシステムおよび rteval コンテナー以外の追加ソフトウェアなしで、ベアメタルでシステムを実行します。これにより、システムが低レイテンシーのパフォーマンスに最適化され、結果が他のソフトウェアまたはプロセスの影響を受けなくなります。
前提条件
- NUMA ポリシーの設定詳細は、systemd を使用した NUMA ポリシーの設定 を参照してください。
手順
rtevalコンテナーを実行するには、2 つのシナリオがあります。単一の NUMA ノードで以下を行います。
$ rteval --duration 2h複数の NUMA ノードで
rtevalコンテナーを実行します。$ rteval --duration 2h --loads-cpulist 0,1 --measurement-cpulist 2-47
ベアメタルテストが完了したら、rteval コンテナーをベースラインとして使用し、アプリケーションやサービスで実際のシナリオを設定します。
9.3. コンテナー配置による CPU パフォーマンスの最適化 リンクのコピーリンクがクリップボードにコピーされました!
リアルタイムプロファイルを使用してホストをチューニングした後、コンテナーを選択的に特定の CPU に配置してコンテナーランタイムの動作を調整することで、パフォーマンスをさらに最適化できます。これらの戦略により、CPU の分離および cgroup 設定がコンテナー化されたワークロードのレイテンシーにどのように影響するかを調べることができます。
9.3.1. すべての CPU での podman の実行 リンクのコピーリンクがクリップボードにコピーされました!
rteval コンテナーで podman を実行するには、チューニングされたリアルタイムプロファイルまたはカスタムシステムチューニングを使用して、システムを調整します。測定するシナリオに CPU 分離が必要かどうかを判別します。特定のシナリオでコンテナーを実行する際にの問題を回避するために、CPU 分離を正しく設定してください。
/proc/cmdline で isolcpus= 引数を確認します。isolcpus が設定されていない場合、システムは CPU を分離せず、すべての CPU でコンテナーを実行できます。
前提条件
-
/proc/cmdlineのisolcpus=引数は、すべての CPU でコンテナーを実行するように設定されていません。 - ホストマシンが Red Hat Enterprise Linux バージョン 9.6 以降で実行されている。
-
podmanサービスが実行している。 -
rtevalコンテナーがインストールされ、実行中である。
手順
podmanレジストリーにログインします。$ podman login registry.redhat.iortevalコンテナーを実行します。次のいずれかの方法を選択して、コンテナーを実行します。単一の NUMA ノードボックス上のすべての CPU で、以下を実行します。
$ podman run -it --rm --privileged --pids-limit=0 registry.redhat.io/rhel10/rteval \ /bin/bash -c 'rteval --duration 2h’マルチ NUMA ノードマシンで以下を行います。
$ podman run -it --rm --privileged --pids-limit=0 registry.redhat.io/rhel10/rteval \ /bin/bash -c 'rteval --duration 2h --loads-cpulist 0,1 --measurement-cpulist 2-47--pids-limit=0kcompileは、コンテナーランタイムのデフォルト制限に到達せずに実行できます。kcompileは、カーネル全体を再ビルドすることなく、現在実行中のカーネルのカーネルモジュールをコンパイルするために使用されるコマンドラインユーティリティーです。--privileged-
コンテナーは、ホストシステム上のすべてのデバイスにアクセスできます。これは、
rtevalが正常に実行されるために必要です。
これらのコマンドは、利用可能なすべてのノードで単一のコンテナーを実行します。tuned サービスはホストのチューニングを管理するため、CPU を 1 つだけ使用する場合にベアメタルのパフォーマンスを評価できます。
検証
新しいターミナルで、
rtevalコンテナーを含むすべてのコンテナーを一覧表示し、正しく実行されていることを確認します。$ podman ps -a
9.3.2. 分割された CPU 割り当てによる podman の実行 リンクのコピーリンクがクリップボードにコピーされました!
負荷の分離や測定をテストするために、異なるコンテナーを異なる CPU セットに割り当てることができます。たとえば、1 つの NUMA ノードのみが存在し、負荷と測定をコンテナーに分割したい場合などに、2 つの異なるコンテナーを実行できます。この場合、両方のコンテナーがすべての CPU で実行され、チューニングにはパーティションは使用されません。
コマンドの例:
コンテナーを読み込み ます。
$ podman run -it --rm --privileged --pids-limit=0 registry.redhat.io/rhel10/rteval \ /bin/bash -c 'rteval --duration 2h --onlyload'コンテナーを測定 します。
$ podman run -it --rm --privileged --pids-limit=0 registry.redhat.io/rhel10/rteval \ /bin/bash -c 'rteval --duration 2h --onlymeasure'
複数の NUMA ノードを持つボックスまたは手動でパーティショニングされたマシンを持つパーティショニングを使用するシナリオでは、コマンド例は次のとおりです。
コンテナーを読み込み ます。
$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 0,1 registry.redhat.io/rhel10/rteval \ /bin/bash -c 'rteval --duration 2h --onlyload --loads-cpulist 0,1'コンテナーを測定 します。
$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 2-47 registry.redhat.io/rhel10/rteval \ /bin/bash -c 'rteval --duration 2h --noload --measurement-cpulist 2-47'
これらのコマンドを実行すると、負荷コンテナーはハウスキーピングコアの負荷を生成し、測定コンテナーは isol_cpu セットで動作します。
パーティショニングが設定されていない場合、あるコンテナーがシステム上のすべての CPU 間で負荷を生成し、別のノードでのレイテンシーを測定します。
どちらのシナリオでも、負荷と測定は 2 つのコンテナー間で正常に分離されます。
9.3.3. リアルタイムプロファイルでの NUMA ごとのハウスキーピングの調整 リンクのコピーリンクがクリップボードにコピーされました!
リアルタイムプロファイルで、NUMA ノードごとにハウスキーピング CPU セットを調整できます。これにより、ハウスキーピングタスクが NUMA ノード全体に均等に分散されるようにすることで、システムのパフォーマンスを最適化します。
これは、競合の削減および全体的なパフォーマンスを向上させるのに役立つため、複数の NUMA ノードを持つシステムに特に役立ちます。
デフォルトのリアルタイム tuned プロファイルは、NUMA ノードごとに 1 つのハウスキーピング CPU を確保します(hk_per_numa=1)。コンテナーワークロードにより多くの CPU が必要な場合は、この動作を変更できます。
前提条件
- ホストマシンが Red Hat Enterprise Linux バージョン 9.6 以降で実行されている。
-
tunedサービスを実行している。 -
rtevalコンテナーがインストールされ、実行中である。 -
podmanサービスが実行している。 -
tuned-profiles-realtimeパッケージがインストールされている。
手順
realtime-variables.confファイルを変更して、NUMA ノードごとにハウスキーピング CPU セットを調整します。テキストエディターで
/etc/tunedにあるrealtime-variables.confファイルを開きます。$ sudo vi /etc/tuned/realtime-variables.confisolated_cores変数を見つけます。デフォルトでは、これは1に設定されています。つまり、NUMA ノードごとに 1 つのコアが分離またはハウスキーピング以外の使用用に予約されます。この値を大きくすることができますが、NUMA ノードあたりの CPU の総数より小さくなければなりません。以下の例では、NUMA ノードごとに 24 コアを持つシステムで、
isolated_coresを3に設定します。isolated_cores=${f:calc_isolated_cores:3}
- 変更を保存してファイルを閉じます。
tunedリアルタイムプロファイルを再適用します。$ sudo tuned-adm profile realtime
これにより、テスト中に合計 6 つの CPU (NUMA ノードあたり 3)が負荷を生成し、システムは残りのコアを isolcpus セット用に予約します。この設定は測定に使用されます。場合によっては、優先度の設定が混在すると、isolcpus セットではなく、カスタムトポロジーにコンテナーがデプロイされる可能性があります。
または、ノードごとの自動数に依存する代わりに、カスタム CPU 範囲を手動で指定することもできます。これにより、分離されたコアを完全に制御できるようになり、不均一のトポロジーまたは特殊な CPU レイアウトを使用するシステムを微調整しやすくなります。
検証
-
realtime-variables.confファイルの変更を確認します。 - システムを再起動して変更を適用します。
/proc/cmdlineファイルを表示して、isolcpus設定を確認します。$ cat /proc/cmdline BOOT_IMAGE=(hd0,gpt2)/vmlinuz-5.XX.X-XX.X.X.el9_6.x86_64+rt root=/dev/mapper/rhel_rt--qe--11-root ro crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M resume=UUID=00cbf36d-ffaa-4285-a381-5c1d868eb3e3 rd.lvm.lv=rhel_rt-qe-11/root rd.lvm.lv=rhel_rt-qe-11/swap console=ttyS0,115200n81 skew_tick=1 tsc=reliable rcupdate.rcu_normal_after_boot=1 isolcpus=managed_irq,domain,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47 intel_pstate=disable nosoftlockup
9.3.4. 分離された CPU 間で複数のコンテナーの分散 リンクのコピーリンクがクリップボードにコピーされました!
分離された CPU 全体で複数のコンテナーを実行するには、the-- cpuset-cpus オプションを使用して各コンテナーが使用する CPU を指定します。これにより、負荷が複数の分離された CPU に分割され、パフォーマンスが向上し、競合が軽減されます。
isolcpus セットを複数のコンテナーに分けて、以下のタスクをシミュレートできます。
- 同時レイテンシーの影響を受けやすいタスク。
- パーティションが分割されたシステムに複数ロードします。
9.3.4.1. 同時レイテンシーの影響を受けやすいタスクのシミュレーション リンクのコピーリンクがクリップボードにコピーされました!
レイテンシーの影響を受けやすいタスクをシミュレートするには、特定の分離された CPU を各コンテナーに割り当てることができます。以下の例は、異なる CPU セット間でコンテナーを設定して実行する方法を示しています。
1 つのコンテナーを CPU 0 - 6 上で、もう 1 つは CPU 7 - 28 で、3 番目のコンテナーを CPU 29-47 で実行します。以下のコマンドを使用します。
$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 0-6 registry.redhat.io/rhel10/rteval \
/bin/bash -c 'rteval --duration 2h --onlyload --loads-cpulist 0-6'
$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 7-28 registry.redhat.io/rhel10/rteval \
/bin/bash -c 'rteval --duration 2h --onlyload --loads-cpulist 7-28'
$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 29-47 registry.redhat.io/rhel10/rteval \
/bin/bash -c 'rteval --duration 2h --onlyload --loads-cpulist 29-47'
9.3.4.2. パーティション化されたシステム全体で複数の負荷のシミュレーション リンクのコピーリンクがクリップボードにコピーされました!
分離されていない CPU セットで rteval ロードジェネレーターを開始します。次に、isolcpus セットの一部で高速データベースコンテナーなどの高スループットのアプリケーションをシミュレートします。この例では、高速データベースコンテナーを表す CPU 7-28 が使用されます。別のターミナルセッションで以下のコマンドを実行して、読み込みを開始します。
$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 0-6 registry.redhat.io/rhel10/rteval \
/bin/bash -c 'rteval --duration 2h --onlyload --loads-cpulist 0-6'
次に、別のターミナルで、分離された CPU のサブセットの一部に負荷を生成します。
$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 20-30 registry.redhat.io/rhel10/rteval \
/bin/bash -c 'rteval --duration 2h --onlyload --loads-cpulist 20-30'
ここで、残りの CPU で測定スレッドを実行するには、2 つのオプションがあります。分離された CPU の残りの 2 つのサブセットをデプロイするか、残りの CPU サブセットの両方を使用する単一の測定コンテナーを実行できます。
オプション 1: 2 つの測定コンテナーをデプロイします。
$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 7-19 registry.redhat.io/rhel10/rteval \ /bin/bash -c 'rteval --duration 2h --noload --measurement-cpulist 7-19'$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 31-47 registry.redhat.io/rhel10/rteval \ /bin/bash -c 'rteval --duration 2h --noload --measurement-cpulist 31-47'オプション 2: 単一の測定コンテナーをデプロイします。
$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 7-19,31-47 registry.redhat.io/rhel10/rteval \ /bin/bash -c 'rteval --duration 2h --noload --measurement-cpulist 7-19,31-47'
第10章 cgroupfs を使用して cgroup を手動で管理する リンクのコピーリンクがクリップボードにコピーされました!
cgroupfs 仮想ファイルシステムにディレクトリーを作成することにより、システム上の cgroup 階層を管理できます。ファイルシステムはデフォルトで /sys/fs/cgroup/ ディレクトリーにマウントされ、専用の制御ファイルで必要な設定を指定できます。
一般に、Red Hat では、システムリソースの使用を制御するために systemd を使用することを推奨します。特別な場合にのみ、cgroups 仮想ファイルシステムを手動で設定する必要があります。たとえば、cgroup-v2 階層に同等のものがない cgroup-v1 コントローラーを使用する必要がある場合です。
10.1. cgroups-v2 ファイルシステムでの cgroup の作成とコントローラーの有効化 リンクのコピーリンクがクリップボードにコピーされました!
ディレクトリーを作成または削除したり、cgroups 仮想ファイルシステム内のファイルに書き込んだりすることで、control groups (cgroups) を管理できます。ファイルシステムは、デフォルトで /sys/fs/cgroup/ ディレクトリーにマウントされます。cgroups コントローラーの設定を使用するには、子 cgroups に対して目的のコントローラーを有効にする必要もあります。ルート cgroup は、デフォルトで、その子 cgroups の memory および pids コントローラーを有効にしました。したがって、Red Hat は、/sys/fs/cgroup/ ルート cgroup 内に少なくとも 2 つのレベルの子 cgroups を作成することを推奨します。このようにして、オプションで子 cgroups から memory と pids コントローラーを削除し、cgroup ファイルの組織の明確さを維持します。
前提条件
- root 権限がある。
手順
/sys/fs/cgroup/Example/ディレクトリーを作成します。# mkdir /sys/fs/cgroup/Example//sys/fs/cgroup/Example/ディレクトリーはサブグループを定義します。/sys/fs/cgroup/Example/ディレクトリーを作成すると、一部のcgroups-v2インターフェイスファイルがディレクトリーに自動的に作成されます。/sys/fs/cgroup/Example/ディレクトリーには、memoryおよびpidsコントローラー用のコントローラー固有のファイルも含まれます。オプション: 新しく作成された子コントロールグループを確認します。
# ll /sys/fs/cgroup/Example/ -r—r—r--. 1 root root 0 Jun 1 10:33 cgroup.controllers -r—r—r--. 1 root root 0 Jun 1 10:33 cgroup.events -rw-r—r--. 1 root root 0 Jun 1 10:33 cgroup.freeze -rw-r--r--. 1 root root 0 Jun 1 10:33 cgroup.procs … -rw-r—r--. 1 root root 0 Jun 1 10:33 cgroup.subtree_control -r—r—r--. 1 root root 0 Jun 1 10:33 memory.events.local -rw-r—r--. 1 root root 0 Jun 1 10:33 memory.high -rw-r—r--. 1 root root 0 Jun 1 10:33 memory.low … -r—r—r--. 1 root root 0 Jun 1 10:33 pids.current -r—r—r--. 1 root root 0 Jun 1 10:33 pids.events -rw-r—r--. 1 root root 0 Jun 1 10:33 pids.max出力例は、
cgroup.procsやcgroup.controllersなどの一般的なcgroup制御インターフェイスファイルを示しています。これらのファイルは、有効なコントローラーに関係なく、すべてのコントロールグループに共通です。memory.highおよびpids.maxなどのファイルは、memoryおよびpidsコントローラーに関連し、ルートコントロールグループ (/sys/fs/cgroup/) にあり、systemdによってデフォルトで有効になります。デフォルトでは、新しく作成された子グループは、親
cgroupからすべての設定を継承します。この場合、ルートcgroupからの制限はありません。目的のコントローラーが
/sys/fs/cgroup/cgroup.controllersファイルで使用可能であることを確認します。# cat /sys/fs/cgroup/cgroup.controllers cpuset cpu io memory hugetlb pids rdma目的のコントローラーを有効にします。この例では、
cpuおよびcpusetコントローラーです。# echo "+cpu" >> /sys/fs/cgroup/cgroup.subtree_control # echo "+cpuset" >> /sys/fs/cgroup/cgroup.subtree_controlこれらのコマンドにより、
/sys/fs/cgroup/ルートコントロールグループ直下のサブグループに対してcpuおよびcpusetコントローラーが有効になります。新しく作成されたExampleコントロールグループを含みます。サブグループ で指定した各プロセスに対して、基準に基づいてコントロールチェックを適用できます。ユーザーは任意のレベルの
cgroup.subtree_controlファイルの内容を読み取り、直下のサブグループで有効にするコントローラーを把握することができます。注記デフォルトでは、ルートコントロールグループの
/sys/fs/cgroup/cgroup.subtree_controlファイルにはmemoryとpidsコントローラーが含まれます。Exampleコントロールグループの子cgroupsに必要なコントローラーを有効にします。# echo "+cpu +cpuset" >> /sys/fs/cgroup/Example/cgroup.subtree_controlこのコマンドにより、直下のサブコントロールグループに、(
memoryまたはpidsコントローラーではなく) CPU 時間の配分の調整に関係するコントローラー だけ が設定されるようになります。/sys/fs/cgroup/Example/tasks/ディレクトリーを作成します。# mkdir /sys/fs/cgroup/Example/tasks//sys/fs/cgroup/Example/tasks/ディレクトリーは、cpuおよびcpusetコントローラーにのみ関連するファイルを持つサブグループを定義します。これで、このコントロールグループにプロセスを割り当て、プロセスにcpuおよびcpusetコントローラーオプションを利用できます。オプション: 子コントロールグループを確認します。
# ll /sys/fs/cgroup/Example/tasks -r—r—r--. 1 root root 0 Jun 1 11:45 cgroup.controllers -r—r—r--. 1 root root 0 Jun 1 11:45 cgroup.events -rw-r—r--. 1 root root 0 Jun 1 11:45 cgroup.freeze -rw-r—r--. 1 root root 0 Jun 1 11:45 cgroup.max.depth -rw-r—r--. 1 root root 0 Jun 1 11:45 cgroup.max.descendants -rw-r—r--. 1 root root 0 Jun 1 11:45 cgroup.procs -r—r—r--. 1 root root 0 Jun 1 11:45 cgroup.stat -rw-r—r--. 1 root root 0 Jun 1 11:45 cgroup.subtree_control -rw-r—r--. 1 root root 0 Jun 1 11:45 cgroup.threads -rw-r—r--. 1 root root 0 Jun 1 11:45 cgroup.type -rw-r—r--. 1 root root 0 Jun 1 11:45 cpu.max -rw-r—r--. 1 root root 0 Jun 1 11:45 cpu.pressure -rw-r—r--. 1 root root 0 Jun 1 11:45 cpuset.cpus -r—r—r--. 1 root root 0 Jun 1 11:45 cpuset.cpus.effective -rw-r—r--. 1 root root 0 Jun 1 11:45 cpuset.cpus.partition -rw-r—r--. 1 root root 0 Jun 1 11:45 cpuset.mems -r—r—r--. 1 root root 0 Jun 1 11:45 cpuset.mems.effective -r—r—r--. 1 root root 0 Jun 1 11:45 cpu.stat -rw-r—r--. 1 root root 0 Jun 1 11:45 cpu.weight -rw-r—r--. 1 root root 0 Jun 1 11:45 cpu.weight.nice -rw-r—r--. 1 root root 0 Jun 1 11:45 io.pressure -rw-r—r--. 1 root root 0 Jun 1 11:45 memory.pressure
cpu コントローラーは、該当のサブコントロールグループに、同じ CPU の CPU 時間を取り合うプロセスが 2 つ以上ある場合にのみ、有効になります。
検証
オプション: 目的のコントローラーのみがアクティブな状態で新しい
cgroupを作成したことを確認します。# cat /sys/fs/cgroup/Example/tasks/cgroup.controllers cpuset cpu
10.2. CPU の重みの調整によるアプリケーションへの CPU 時間配分の制御 リンクのコピーリンクがクリップボードにコピーされました!
特定の cgroup ツリーの下にあるアプリケーションへの CPU 時間の配分を調整するには、cpu コントローラーの関連ファイルに値を割り当てる必要があります。
前提条件
- root 権限がある。
- CPU 時間の配分を制御するアプリケーションがある。
次の例のように、
/sys/fs/cgroup/root control group 内に、child control groups グループの 2 階層を作成しました。… ├── Example │ ├── g1 │ ├── g2 │ └── g3 …-
cgroups-v2 ファイルシステムでの cgroup の作成とコントローラーの有効化 で説明したのと同様に、親コントロールグループと子コントロールグループで
cpuコントローラーを有効にしました。
手順
コントロールグループ内のリソース制限を実現するために、希望する CPU の重みを設定します。
# echo "150" > /sys/fs/cgroup/Example/g1/cpu.weight # echo "100" > /sys/fs/cgroup/Example/g2/cpu.weight # echo "50" > /sys/fs/cgroup/Example/g3/cpu.weightアプリケーションの PID を
g1、g2、およびg3サブグループに追加します。# echo "33373" > /sys/fs/cgroup/Example/g1/cgroup.procs # echo "33374" > /sys/fs/cgroup/Example/g2/cgroup.procs # echo "33377" > /sys/fs/cgroup/Example/g3/cgroup.procs上記のコマンドの例は、目的のアプリケーションが
Example/g*/子 cgroup のメンバーになり、それらの cgroup の設定に従って CPU 時間を分散させることを保証します。実行中のプロセスを持つサブ cgroups(
g1、g2、g3) の重みは、親 cgroup のレベルで合算されます (例)。その後、CPU リソースはそれぞれの重みに基づいて相対的に配分されます。その結果、すべてのプロセスが同時に実行されると、カーネルはそれぞれの cgroup の
cpu.weightファイルに基づいて、それぞれのプロセスに比例配分の CPU 時間を割り当てます。Expand サブ cgroup cpu.weightファイルCPU 時間の割り当て g1
150
約 50% (150/300)
g2
100
約 33% (100/300)
g3
50
約 16% (50/300)
cpu.weightコントローラーファイルの値はパーセンテージではありません。1 つのプロセスが実行を停止し、cgroup
g2が実行中のプロセスのない状態になると、計算では cgroupg2が省略され、cgroupsg1およびg3の重みだけが考慮されます。Expand サブ cgroup cpu.weightファイルCPU 時間の割り当て g1
150
約 75% (150/200)
g3
50
約 25% (50/200)
重要子 cgroup に複数の実行中のプロセスがある場合、cgroup に割り当てられた CPU 時間が、そのメンバープロセス間で均等に分配されます。
検証
アプリケーションが指定のコントロールグループで実行されていることを確認します。
# cat /proc/33373/cgroup /proc/33374/cgroup /proc/33377/cgroup 0::/Example/g1 0::/Example/g2 0::/Example/g3コマンド出力は、
Example/g*/サブ cgroups で実行される指定されたアプリケーションのプロセスを示しています。スロットリングされたアプリケーションの現在の CPU 使用率を確認します。
# top top - 05:17:18 up 1 day, 18:25, 1 user, load average: 3.03, 3.03, 3.00 Tasks: 95 total, 4 running, 91 sleeping, 0 stopped, 0 zombie %Cpu(s): 18.1 us, 81.6 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.3 hi, 0.0 si, 0.0 st MiB Mem : 3737.0 total, 3233.7 free, 132.8 used, 370.5 buff/cache MiB Swap: 4060.0 total, 4060.0 free, 0.0 used. 3373.1 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 33373 root 20 0 18720 1748 1460 R 49.5 0.0 415:05.87 sha1sum 33374 root 20 0 18720 1756 1464 R 32.9 0.0 412:58.33 sha1sum 33377 root 20 0 18720 1860 1568 R 16.3 0.0 411:03.12 sha1sum 760 root 20 0 416620 28540 15296 S 0.3 0.7 0:10.23 tuned 1 root 20 0 186328 14108 9484 S 0.0 0.4 0:02.00 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthread ...注記わかりやすくするために、すべてのプロセスを単一の CPU 上で実行しています。CPU の重みは、複数の CPU で使用される場合にも、同じ原則を適用します。
PID 33373、PID 33374、およびPID 33377の CPU リソースが、それぞれの子 cgroups に割り当てた 150、100、および 50 の重みに基づいて割り当てられていることに注意してください。重みは、各アプリケーションの CPU 時間の約 50%、33%、および 16% の配分に対応します。
10.3. cgroups-v1 のマウント リンクのコピーリンクがクリップボードにコピーされました!
RHEL 9 は、システムの起動プロセス中に、デフォルトで cgroup-v2 仮想ファイルシステムをマウントします。cgroup-v1 機能を使用してアプリケーションのリソースを制限するには、システムを手動で設定します。
cgroup-v1 と cgroup-v2 の両方がカーネルで完全に有効になっている。カーネルから見た場合、デフォルトのコントロールグループバージョンはありません。また、システムの起動時にマウントするかどうかは、systemd により決定します。
前提条件
- root 権限がある。
手順
systemdシステムおよびサービスマネージャーによるシステムブート中に、デフォルトでcgroups-v1をマウントするようにシステムを設定します。# grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"これにより、必要なカーネルコマンドラインパラメーターが現在のブートエントリーに追加されます。
すべてのカーネルブートエントリーに同じパラメーターを追加するには:
# grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"- システムを再起動して、変更を有効にします。
検証
cgroups-v1ファイルシステムがマウントされたことを確認します。# mount -l | grep cgroup tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,seclabel,size=4096k,nr_inodes=1024,mode=755,inode64) cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd) cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,perf_event) cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpu,cpuacct) cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,pids) cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpuset) cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,net_cls,net_prio) cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,hugetlb) cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,memory) cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,blkio) cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,devices) cgroup on /sys/fs/cgroup/misc type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,misc) cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,freezer) cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,rdma)さまざまな
cgroup-v1コントローラーに対応するcgroups-v1ファイルシステムが、/sys/fs/cgroup/ディレクトリーに正常にマウントされました。/sys/fs/cgroup/ディレクトリーの内容を確認します。# ll /sys/fs/cgroup/ dr-xr-xr-x. 10 root root 0 Mar 16 09:34 blkio lrwxrwxrwx. 1 root root 11 Mar 16 09:34 cpu → cpu,cpuacct lrwxrwxrwx. 1 root root 11 Mar 16 09:34 cpuacct → cpu,cpuacct dr-xr-xr-x. 10 root root 0 Mar 16 09:34 cpu,cpuacct dr-xr-xr-x. 2 root root 0 Mar 16 09:34 cpuset dr-xr-xr-x. 10 root root 0 Mar 16 09:34 devices dr-xr-xr-x. 2 root root 0 Mar 16 09:34 freezer dr-xr-xr-x. 2 root root 0 Mar 16 09:34 hugetlb dr-xr-xr-x. 10 root root 0 Mar 16 09:34 memory dr-xr-xr-x. 2 root root 0 Mar 16 09:34 misc lrwxrwxrwx. 1 root root 16 Mar 16 09:34 net_cls → net_cls,net_prio dr-xr-xr-x. 2 root root 0 Mar 16 09:34 net_cls,net_prio lrwxrwxrwx. 1 root root 16 Mar 16 09:34 net_prio → net_cls,net_prio dr-xr-xr-x. 2 root root 0 Mar 16 09:34 perf_event dr-xr-xr-x. 10 root root 0 Mar 16 09:34 pids dr-xr-xr-x. 2 root root 0 Mar 16 09:34 rdma dr-xr-xr-x. 11 root root 0 Mar 16 09:34 systemd/sys/fs/cgroup/ディレクトリーは、デフォルトでは root control group とも呼ばれ、cpusetなどのコントローラー固有のディレクトリーが含まれています。さらに、systemdに関連するディレクトリーがいくつかあります。
10.4. cgroups-v1 を使用したアプリケーションへの CPU 制限の設定 リンクのコピーリンクがクリップボードにコピーされました!
コントロールグループバージョン 1 (cgroups-v1) を使用してアプリケーションに対する CPU 制限を設定するには、/sys/fs/ 仮想ファイルシステムを使用します。
前提条件
- root 権限がある。
- CPU 消費制限の対象とするアプリケーションがシステムにインストールされている。
systemdシステムおよびサービスマネージャーによるシステムの起動時に、デフォルトでcgroups-v1をマウントするようにシステムを設定している。# grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"これにより、必要なカーネルコマンドラインパラメーターが現在のブートエントリーに追加されます。
手順
CPU 消費を制限するアプリケーションのプロセス ID (PID) を特定します。
# top top - 11:34:09 up 11 min, 1 user, load average: 0.51, 0.27, 0.22 Tasks: 267 total, 3 running, 264 sleeping, 0 stopped, 0 zombie %Cpu(s): 49.0 us, 3.3 sy, 0.0 ni, 47.5 id, 0.0 wa, 0.2 hi, 0.0 si, 0.0 st MiB Mem : 1826.8 total, 303.4 free, 1046.8 used, 476.5 buff/cache MiB Swap: 1536.0 total, 1396.0 free, 140.0 used. 616.4 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 6955 root 20 0 228440 1752 1472 R 99.3 0.1 0:32.71 sha1sum 5760 jdoe 20 0 3603868 205188 64196 S 3.7 11.0 0:17.19 gnome-shell 6448 jdoe 20 0 743648 30640 19488 S 0.7 1.6 0:02.73 gnome-terminal- 1 root 20 0 245300 6568 4116 S 0.3 0.4 0:01.87 systemd 505 root 20 0 0 0 0 I 0.3 0.0 0:00.75 kworker/u4:4-events_unbound ...PID 6955を持つsha1sumサンプルアプリケーションが、大量の CPU リソースを消費しています。cpuリソースコントローラーディレクトリーにサブディレクトリーを作成します。# mkdir /sys/fs/cgroup/cpu/Example/このディレクトリーはコントロールグループを表します。ここに特定のプロセスを配置して、そのプロセスに特定の CPU 制限を適用できます。同時に、いくつかの
cgroups-v1インターフェイスファイルとcpuコントローラー固有のファイルがディレクトリーに作成されます。オプション: 新しく作成されたコントロールグループを確認します。
# ll /sys/fs/cgroup/cpu/Example/ -rw-r—r--. 1 root root 0 Mar 11 11:42 cgroup.clone_children -rw-r—r--. 1 root root 0 Mar 11 11:42 cgroup.procs -r—r—r--. 1 root root 0 Mar 11 11:42 cpuacct.stat -rw-r—r--. 1 root root 0 Mar 11 11:42 cpuacct.usage -r—r—r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_all -r—r—r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_percpu -r—r—r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_percpu_sys -r—r—r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_percpu_user -r—r—r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_sys -r—r—r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_user -rw-r—r--. 1 root root 0 Mar 11 11:42 cpu.cfs_period_us -rw-r—r--. 1 root root 0 Mar 11 11:42 cpu.cfs_quota_us -rw-r—r--. 1 root root 0 Mar 11 11:42 cpu.rt_period_us -rw-r—r--. 1 root root 0 Mar 11 11:42 cpu.rt_runtime_us -rw-r—r--. 1 root root 0 Mar 11 11:42 cpu.shares -r—r—r--. 1 root root 0 Mar 11 11:42 cpu.stat -rw-r—r--. 1 root root 0 Mar 11 11:42 notify_on_release -rw-r—r--. 1 root root 0 Mar 11 11:42 taskscpuacct.usage、cpu.cfs._period_usなどのファイルは、Exampleコントロールグループ内のプロセスに設定できる特定の設定や制限を表しています。ファイル名の先頭に、それが属するコントロールグループコントローラーの名前が付いていることに注意してください。デフォルトでは、新しく作成されたコントロールグループは、システムの CPU リソース全体へのアクセスを制限なしで継承します。
コントロールグループの CPU 制限を設定します。
# echo "1000000" > /sys/fs/cgroup/cpu/Example/cpu.cfs_period_us # echo "200000" > /sys/fs/cgroup/cpu/Example/cpu.cfs_quota_us-
cpu.cfs_period_usファイルは、コントロールグループの CPU リソースへのアクセスを再割り当てする必要がある頻度を表します。期間はマイクロ秒 (µs、"us") 単位です。上限は 1,000,000 マイクロ秒、下限は 1,000 マイクロ秒です。 cpu.cfs_quota_usファイルは、コントロールグループ内のすべてのプロセスが 1 つの期間 (cpu.cfs_period_usで定義) 中にまとめて実行できる合計時間をマイクロ秒単位で表します。コントロールグループ内のプロセスが 1 つの期間中にクォータで指定された時間をすべて使い果たすと、そのプロセスは残り期間にわたってスロットリングされ、次の期間まで実行できなくなります。下限は 1000 マイクロ秒です。上記のコマンド例は、CPU 時間制限を設定して、
Exampleコントロールグループでまとめられているすべてのプロセスは、1 秒ごと (cpu.cfs_period_usに定義されている) に、0.2 秒間だけ (cpu.cfs_quota_usに定義されている) 実行できるようにしています。
-
オプション: 制限を確認します。
# cat /sys/fs/cgroup/cpu/Example/cpu.cfs_period_us /sys/fs/cgroup/cpu/Example/cpu.cfs_quota_us 1000000 200000アプリケーションの PID を
Exampleコントロールグループに追加します。# echo "6955" > /sys/fs/cgroup/cpu/Example/cgroup.procsこのコマンドによって、特定のアプリケーションが
Exampleコントロールグループのメンバーとなり、Exampleコントロールグループに設定された CPU 制限を超えないようになります。PID はシステム内の既存のプロセスを表す必要があります。このPID 6955は、プロセスsha1sum /dev/zero &に割り当てられており、cpuコントローラーの使用例を示すために使用されています。
検証
アプリケーションが指定のコントロールグループで実行されていることを確認します。
# cat /proc/6955/cgroup 12:cpuset:/ 11:hugetlb:/ 10:net_cls,net_prio:/ 9:memory:/user.slice/user-1000.slice/user@1000.service 8:devices:/user.slice 7:blkio:/ 6:freezer:/ 5:rdma:/ 4:pids:/user.slice/user-1000.slice/user@1000.service 3:perf_event:/ 2:cpu,cpuacct:/Example 1:name=systemd:/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.serviceアプリケーションのプロセスは、アプリケーションのプロセスに CPU 制限を適用する
Exampleコントロールグループで実行されます。スロットルしたアプリケーションの現在の CPU 使用率を特定します。
# top top - 12:28:42 up 1:06, 1 user, load average: 1.02, 1.02, 1.00 Tasks: 266 total, 6 running, 260 sleeping, 0 stopped, 0 zombie %Cpu(s): 11.0 us, 1.2 sy, 0.0 ni, 87.5 id, 0.0 wa, 0.2 hi, 0.0 si, 0.2 st MiB Mem : 1826.8 total, 287.1 free, 1054.4 used, 485.3 buff/cache MiB Swap: 1536.0 total, 1396.7 free, 139.2 used. 608.3 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 6955 root 20 0 228440 1752 1472 R 20.6 0.1 47:11.43 sha1sum 5760 jdoe 20 0 3604956 208832 65316 R 2.3 11.2 0:43.50 gnome-shell 6448 jdoe 20 0 743836 31736 19488 S 0.7 1.7 0:08.25 gnome-terminal- 505 root 20 0 0 0 0 I 0.3 0.0 0:03.39 kworker/u4:4-events_unbound 4217 root 20 0 74192 1612 1320 S 0.3 0.1 0:01.19 spice-vdagentd ...PID 6955の CPU 消費が 99% から 20% に減少していることに注意してください。
cpu.cfs_period_us および cpu.cfs_quota_us に対応する cgroups-v2 は、cpu.max ファイルです。cpu.max ファイルは、cpu コントローラーから入手できます。
第11章 コントロールグループについて リンクのコピーリンクがクリップボードにコピーされました!
コントロールグループ (cgroups) カーネル機能を使用すると、アプリケーションのリソース使用状況を制御して、より効率的に使用できます。
cgroups は、以下のタスクで使用できます。
- システムリソース割り当ての制限を設定します。
- 特定のプロセスへのハードウェアリソースの割り当てにおける優先順位を設定する。
- 特定のプロセスをハードウェアリソースの取得から分離する。
11.1. コントロールグループの概要 リンクのコピーリンクがクリップボードにコピーされました!
コントロールグループ の Linux カーネル機能を使用して、プロセスを階層的に順序付けされたグループ (cgroups) に編成できます。階層 (コントロールグループツリー) は、デフォルトで /sys/fs/cgroup/ ディレクトリーにマウントされている cgroups 仮想ファイルシステムに構造を提供して定義します。
systemd サービスマネージャーは、cgroups を使用して、管理するすべてのユニットとサービスを整理します。/sys/fs/cgroup/ ディレクトリーのサブディレクトリーを作成および削除することで、cgroups の階層を手動で管理できます。
続いて、カーネルのリソースコントローラーは、cgroups 内のプロセスのシステムリソースを制限、優先順位付け、または割り当てることで、これらのプロセスの動作を変更します。これらのリソースには以下が含まれます。
- CPU 時間
- メモリー
- ネットワーク帯域幅
- これらのリソースの組み合わせ
cgroups の主なユースケースは、システムプロセスを集約し、アプリケーションとユーザー間でハードウェアリソースを分割することです。これにより、環境の効率、安定性、およびセキュリティーを強化できます。
- コントロールグループ 1
コントロールグループバージョン 1 (
cgroups-v1) はリソースごとのコントローラー階層を提供します。CPU、メモリー、I/O などのリソースごとに、独自のコントロールグループ階層があります。異なるコントロールグループ階層を組み合わせることで、1 つのコントローラーが別のコントローラーと連携してそれぞれのリソースを管理できるようになります。ただし、2 つのコントローラーが異なるプロセス階層に属している場合、連携が制限されます。cgroups-v1コントローラーは長期間にわたって開発されたため、コントロールファイルの動作と命名に一貫性がありません。- コントロールグループ 2
Control groups version 2 (
cgroups-v2) は、すべてのリソースコントローラーがマウントされる単一のコントロールグループ階層を提供します。コントロールファイルの動作と命名は、さまざまなコントローラーにおいて一貫性があります。
RHEL 9 では、デフォルトで cgroups-v2 をマウントして使用します。
11.2. カーネルリソースコントローラーの概要 リンクのコピーリンクがクリップボードにコピーされました!
カーネルリソースコントローラーは、コントロールグループの機能を有効化します。RHEL 9 は、コントロールグループバージョン 1 (cgroups-v1) および コントロールグループバージョン 2 (cgroups-v2) のさまざまなコントローラーをサポートします。
コントロールグループサブシステムとも呼ばれるリソースコントローラーは、1 つのリソース (CPU 時間、メモリー、ネットワーク帯域幅、ディスク I/O など) を表すカーネルサブシステムです。Linux カーネルは、systemd サービスマネージャーによって自動的にマウントされるリソースコントローラーの範囲を提供します。現在マウントされているリソースコントローラーの一覧は、/proc/cgroups ファイルで確認できます。
cgroups-v1 で利用可能なコントローラー
blkio- ブロックデバイスへの入出力アクセスを制限します。
cpu-
コントロールグループのタスク用の Completely Fair Scheduler (CFS) パラメーターを調整します。
cpuコントローラーは、同じマウント上のcpuacctコントローラーとともにマウントされます。 cpuacct-
コントロールグループ内のタスクが使用する CPU リソースに関する自動レポートを作成します。
cpuacctコントローラーは、同じマウント上のcpuコントローラーとともにマウントされます。 cpuset- コントロールグループタスクが、指定された CPU のサブセットでのみ実行されるように制限し、指定されたメモリーノードでのみメモリーを使用するようにタスクに指示します。
devices- コントロールグループ内のタスクのデバイスへのアクセスを制御します。
freezer- コントロールグループ内のタスクを一時停止または再開します。
memory- コントロールグループ内のタスクによるメモリー使用の制限を設定し、それらのタスクが使用したメモリーリソースに関する自動レポートを生成します。
net_cls-
特定のコントロールグループタスクから発信されたパケットを識別するために Linux トラフィックコントローラー (
tcコマンド) を有効化するクラス識別子 (classid) でネットワークパケットをタグ付けします。net_clsのサブシステムnet_ filter(iptables) でも、このタグを使用して、そのようなパケットに対するアクションを実行することができます。net_filterは、ファイアウォール識別子 (fwid) でネットワークソケットをタグ付けします。これにより、Linux ファイアウォールは、(iptablesコマンドを使用して) 特定のコントロールグループタスクから発信されたパケットを識別できるようになります。 net_prio- ネットワークトラフィックの優先度を設定します。
pids- コントロールグループ内の複数のプロセスとその子プロセスに制限を設定します。
perf_event-
perfパフォーマンス監視およびレポートユーティリティーにより、監視するタスクをグループ化します。 rdma- コントロールグループ内の Remote Direct Memory Access/InfiniB 固有リソースに制限を設定します。
hugetlb- コントロールグループ内のタスクによる大容量の仮想メモリーページの使用を制限します。
cgroups-v2 で利用可能なコントローラー
io- ブロックデバイスへの入出力アクセスを制限します。
memory- コントロールグループ内のタスクによるメモリー使用の制限を設定し、それらのタスクが使用したメモリーリソースに関する自動レポートを生成します。
pids- コントロールグループ内の複数のプロセスとその子プロセスに制限を設定します。
rdma- コントロールグループ内の Remote Direct Memory Access/InfiniB 固有リソースに制限を設定します。
cpu- コントロールグループのタスクの Completely Fair Scheduler (CFS) パラメーターを調整し、コントロールグループのタスクで使用される CPU リソースに関する自動レポートを作成します。
cpuset-
コントロールグループタスクが、指定された CPU のサブセットでのみ実行されるように制限し、指定されたメモリーノードでのみメモリーを使用するようにタスクに指示します。新しいパーティション機能により、コア機能 (
cpus{,.effective},mems{,.effective}) のみがサポートされます。 perf_event-
perfパフォーマンス監視およびレポートユーティリティーにより、監視するタスクをグループ化します。perf_evenは v2 階層で自動的に有効になります。
リソースコントローラーは、cgroups-v1 階層または cgroups-v 2 階層のいずれかで使用できますが、両方を同時に使用することはできません。
11.3. 名前空間の概要 リンクのコピーリンクがクリップボードにコピーされました!
名前空間は、ソフトウェアオブジェクトを整理および識別するための個別の空間を作成するものです。これにより、オブジェクトが相互に影響を及ぼすことがなくなります。その結果、各ソフトウェアオブジェクトが同じシステムを共有しているにもかかわらず、独自のリソースセット (マウントポイント、ネットワークデバイス、ホスト名など) が各オブジェクトに格納されます。
名前空間を使用する最も一般的なテクノロジーの 1 つとしてコンテナーが挙げられます。
特定のグローバルリソースへの変更は、その名前空間のプロセスにのみ表示され、残りのシステムまたは他の名前空間には影響しません。
プロセスがどの名前空間に所属するかを確認するには、/proc/<PID>/ns/ ディレクトリーのシンボリックリンクを確認します。
| 名前空間 | 分離 |
|---|---|
| Mount | マウントポイント |
| UTS | ホスト名および NIS ドメイン名 |
| IPC | System V IPC、POSIX メッセージキュー |
| PID | プロセス ID |
| Network | ネットワークデバイス、スタック、ポートなど。 |
| User | ユーザーおよびグループ ID |
| Control groups | コントロールグループの root ディレクトリー |
第12章 RHEL for Real Time での CPU アフィニティーの設定 リンクのコピーリンクがクリップボードにコピーされました!
システム内のすべてのスレッドと割り込みソースには、プロセッサーアフィニティープロパティーがあります。オペレーティングシステムスケジューラーは、この情報を使用して、CPU で実行するスレッドと割り込みを決定します。プロセッサーアフィニティーを効果的なポリシーおよび優先度設定とともに設定することで、パフォーマンスを最大限に高めることができます。アプリケーションは、特に CPU 時間などのリソースに対して、他のプロセスと常に競合します。アプリケーションによっては、関連するスレッドが同じコアで実行されることがよくあります。1 つのアプリケーションスレッドを 1 つのコアに割り当てることができます。
マルチタスクを実行するシステムは、一般的に非決定論の傾向にあります。優先度の高いアプリケーションであっても、優先度の低いアプリケーションがコードの重要なセクションにある場合は、アプリケーションの実行が遅延する可能性があります。優先度の低いアプリケーションが重要なセクションを終了すると、カーネルは優先度の低いアプリケーションのプリエンプションを安全に実行し、プロセッサーで高い優先順位のアプリケーションをスケジュールします。また、キャッシュの無効化により、ある CPU から別の CPU への移行の負荷が大きくなることがあります。RHEL for Real Time には、これらの問題の一部に対処し、レイテンシーをより適切に制御できるようにするツールが含まれています。
アフィニティーはビットマスクで表され、マスクの各ビットが CPU コアを表します。ビットが 1 に設定されている場合は、スレッドまたは割り込みがそのコアで実行されます。0 を指定すると、スレッドまたは割り込みがコア上の実行から除外されます。アフィニティービットマスクのデフォルト値はすべて 1 です。つまり、スレッドまたは割り込みがシステムの任意のコアで実行できます。
デフォルトでは、プロセスは任意の CPU で実行できます。ただし、プロセスのアフィニティーを変更することにより、所定の CPU セットで実行するプロセスを定義できます。子プロセスは、そのロールの CPU アフィニティーを継承します。
次の一般的なアフィニティー設定を設定すると、最大限のパフォーマンスを実現できます。
- すべてのシステムプロセスに単一の CPU コアを使用し、残りのコアで実行するようにアプリケーションを設定する。
-
同じ CPU 上でスレッドアプリケーションと特定のカーネルスレッド (ネットワーク
softirqやドライバースレッドなど) を設定する。 - 各 CPU でプロデューサーとコンシューマーのスレッドをペアリングする。プロデューサーとコンシューマーは 2 つのクラスのスレッドであり、プロデューサーはデータをバッファーに挿入し、コンシューマーはデータをバッファーから削除します。
リアルタイムシステムでアフィニティーを調整するための通常のグッドプラクティスは、アプリケーションの実行に必要なコアの数を決定してから、それらのコアを分離することです。これは、Tuna ツールまたはシェルスクリプトを使用して、taskset コマンドなどのビットマスク値を変更することで実現できます。taskset コマンドはプロセスのアフィニティーを変更し、/proc/ ファイルシステムエントリーを変更すると割り込みのアフィニティーが変更されます。
12.1. taskset コマンドを使用したプロセッサーアフィニティーの調整 リンクのコピーリンクがクリップボードにコピーされました!
リアルタイムでは、taskset コマンドは、実行中のプロセスの CPU アフィニティーを設定または取得するのに役立ちます。taskset コマンドは、-p オプションおよび -c オプションを取ります。-p オプションまたは --pid オプションは既存のプロセスを機能させ、新しいタスクを開始しません。-c または --cpu-list は、bitmask の代わりにプロセッサーの数値リストを指定します。リストには、コンマで区切られた複数の項目、およびプロセッサーの範囲を含めることができます。たとえば、0,5,7,9-11 です。
前提条件
- システムの root 権限がある。
手順
特定のプロセスのプロセスアフィニティーを確認するには、次の手順を実行します。
# taskset -p -c 1000 pid 1000’s current affinity list: 0,1このコマンドは、プロセスのアフィニティーを PID 1000 で出力します。プロセスは、CPU 0 または CPU 1 を使用するように設定されています。
オプション: プロセスをバインドするように特定の CPU を設定するには、以下を実行します。
# taskset -p -c 1 1000 pid 1000’s current affinity list: 0,1 pid 1000’s new affinity list: 1オプション: 複数の CPU アフィニティーを定義するには、以下を実行します。
# taskset -p -c 0,1 1000 pid 1000’s current affinity list: 1 pid 1000’s new affinity list: 0,1オプション: 特定の CPU で優先度レベルとポリシーを設定するには、以下を実行します。
# taskset -c 5 chrt -f 78 /bin/my-appさらに細かく設定するために、優先度とポリシーを指定することもできます。この例では、コマンドは
SCHED_FIFOポリシーと優先度値 78 を使用して CPU 5 で/bin/my-appアプリケーションを実行します。
12.2. sched_setaffinity() システムコールを使用したプロセッサーアフィニティーの設定 リンクのコピーリンクがクリップボードにコピーされました!
リアルタイム sched_setaffinity() システムコールを使用して、プロセッサーアフィニティーを設定することもできます。
前提条件
- システムの root 権限がある。
手順
sched_setaffinity()でプロセッサーアフィニティーを設定するには、以下を実行します。#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <sched.h> int main(int argc, char **argv) { int i, online=0; ulong ncores = sysconf(_SC_NPROCESSORS_CONF); cpu_set_t *setp = CPU_ALLOC(ncores); ulong setsz = CPU_ALLOC_SIZE(ncores); CPU_ZERO_S(setsz, setp); if (sched_getaffinity(0, setsz, setp) == -1) { perror("sched_getaffinity(2) failed"); exit(errno); } for (i=0; i < CPU_COUNT_S(setsz, setp); i) { if (CPU_ISSET_S(i, setsz, setp)) online; } printf("%d cores configured, %d cpus allowed in affinity mask\n", ncores, online); CPU_FREE(setp); }
12.3. 単一の CPU を分離して、使用率の高いタスクを実行 リンクのコピーリンクがクリップボードにコピーされました!
cpusets メカニズムを使用すると、SCHED_DEADLINE タスクに一連の CPU とメモリーノードを割り当てることができます。CPU 使用率の高いタスクと低いタスクが混在するタスクセットにおいて、使用率の高いタスクを実行する CPU を分離し、使用率の低いタスクを異なる CPU セットでスケジューリングすることで、すべてのタスクが与えられた runtime を満たすことが可能になります。`cpusets' の設定は手動で追加する必要があります。
前提条件
- システムの root 権限がある。
手順
cluster と partition という名前の 2 つのコントロールグループを作成します。
# cd /sys/fs/cgroup # echo +cpuset > cgroup.subtree_control # mkdir cluster # mkdir partition # echo +cpuset | tee cluster/cgroup.subtree_control partition/cgroup.subtree_controlcluster コントロールグループで、使用率の低いタスクが CPU 1 - 7 で実行されるようにスケジュールします。メモリーサイズを検証し、コントロールグループを排他的として指定します。
# cd cluster # echo 1-7 | tee cpuset.cpus cpuset.cpus.exclusive # echo root > cpuset.cpus.partition使用率の低いタスクをすべて cluster コントロールグループに移動します。
# ps -eLo lwp | while read thread; do echo $thread > cgroup.procs ; donepartitionコントロールグループで、使用率の高いタスクを割り当てます。# echo 0 | tee cpuset.cpus cpuset.cpus.exclusive # echo isolated > cpuset.cpus.partitionシェルを partition コントロールグループに追加して起動します。
# echo $$ > cgroup.procsこの設定により、
partitionコントロールグループで分離されたタスクが、clusterコントロールグループ内のタスクに干渉しなくなります。これにより、すべてのリアルタイムタスクがスケジューラーの期限に間に合うようになります。期限スケジューラーを使用している場合、通常はこの変更を行わなくても期限は満たされます。他のタスクには独自の期限があることに注意してください。
アプリケーションが適切なピニングを使用する準備ができている場合は、cgroups を調整して partition cgroup にさらに多くの CPU を割り当て、すべてのリアルタイムタスクをそれに割り当てることで、ノイズをさらに削減できます。
# cd ..
# echo 4-7 | tee cluster/{cpuset.cpus,cpuset.cpus.exclusive}
# echo 0-3 | tee partition/{cpuset.cpus,cpuset.cpus.exclusive}
12.4. CPU パフォーマンスのスパイクの低減 リンクのコピーリンクがクリップボードにコピーされました!
レイテンシーが急増する一般的な原因は、複数の CPU がカーネルタイマーティックハンドラー内の共通のロックで競合することです。競合の原因となるロックは、通常 xtime_lock です。これは時間管理システムと Read-Copy-Update (RCU) 構造のロックによって使用されます。skew_tick=1 を使用すると、CPU ごとのタイマーティックをオフセットして別の時間に開始させ、潜在的なロックの競合を回避できます。
skew_tick カーネルコマンドラインパラメーターは、コア数が多く、レイテンシーの影響を受けやすいワークロードを備えた中規模から大規模のシステムでのレイテンシーの変動を防ぐ可能性があります。
前提条件
- 管理者権限がある。
手順
grubbyでskew_tick=1パラメーターを有効にします。# grubby --update-kernel=ALL --args="skew_tick=1"変更を有効にするために再起動します。
# reboot
skew_tick=1 を有効にすると消費電力が大幅に増加します。そのため、レイテンシーの影響を受けやすいリアルタイムワークロードを実行しており、安定したレイテンシーが消費電力よりも重要な考慮事項である場合にのみ、skew ブートパラメーターを有効にしてください。
検証
/proc/cmdline ファイルを表示し、skew_tick=1 が指定されていることを確認します。/proc/cmdline ファイルには、カーネルに渡されるパラメーターが表示されます。
/proc/cmdlineファイルの新しい設定を確認します。# cat /proc/cmdline
12.5. PC カードデーモンの無効化による CPU 使用量の削減 リンクのコピーリンクがクリップボードにコピーされました!
pcscd デーモンは、並列通信 (PC または PCMCIA) およびスマートカード (SC) リーダーへの接続を管理します。通常 pcscd は優先度が低いタスクですが、多くの場合、他のデーモンよりも多くの CPU を使用する場合があります。したがって、背景でさらにノイズが発生することで、リアルタイムのタスクに対してプリエンプションコストが増え、決定論にその他の悪影響を及ぼす可能性があります。
前提条件
- システムの root 権限がある。
手順
pcscdデーモンのステータスを確認します。# systemctl status pcscd ● pcscd.service - PC/SC Smart Card Daemon Loaded: loaded (/usr/lib/systemd/system/pcscd.service; indirect; vendor preset: disabled) Active: active (running) since Mon 2021-03-01 17:15:06 IST; 4s ago TriggeredBy: ● pcscd.socket Docs: man:pcscd(8) Main PID: 2504609 (pcscd) Tasks: 3 (limit: 18732) Memory: 1.1M CPU: 24ms CGroup: /system.slice/pcscd.service └─2504609 /usr/sbin/pcscd --foreground --auto-exitActiveパラメーターは、pcsdデーモンの状態を表示します。pcsdデーモンを実行している場合は停止します。# systemctl stop pcscd Warning: Stopping pcscd.service, but it can still be activated by: pcscd.socketシステム起動時に
pcsdデーモンが再起動しないようにシステムを設定します。# systemctl disable pcscd Removed /etc/systemd/system/sockets.target.wants/pcscd.socket.
検証
pcscdデーモンのステータスを確認します。# systemctl status pcscd ● pcscd.service - PC/SC Smart Card Daemon Loaded: loaded (/usr/lib/systemd/system/pcscd.service; indirect; vendor preset: disabled) Active: inactive (dead) since Mon 2021-03-01 17:10:56 IST; 1min 22s ago TriggeredBy: ● pcscd.socket Docs: man:pcscd(8) Main PID: 4494 (code=exited, status=0/SUCCESS) CPU: 37ms-
Activeパラメーターの値がinactive (dead)であることを確認します。
第13章 RHEL for Real Time での mlock() システムコールの使用 リンクのコピーリンクがクリップボードにコピーされました!
RHEL for Real-Time メモリーロック (mlock()) 関数を使用すると、リアルタイムの呼び出しプロセスで、アドレス空間の指定された範囲をロックまたはロック解除できます。この範囲は、Linux がメモリースペースを交換するときに、ロックされたメモリーをページングすることを防ぎます。ページテーブルエントリーに物理ページを割り当てると、そのページへの参照が高速になります。mlock() システムコールには、mlock() と mlockall() の 2 つの関数が含まれています。同様に、munlock() システムコールには、munlock() 関数および munlockall() 関数が含まれています。
13.1. mlock() および munlock() システムコール リンクのコピーリンクがクリップボードにコピーされました!
mlock() および mlockall() システムコールは、指定されたメモリー範囲をロックし、このメモリーをページングしません。以下は、mlock() システムコールグループです。
-
mlock()システムコール: 指定された範囲のアドレスをロックします。 -
munlock()システムコール: 指定された範囲のアドレスのロックを解除します。
mlock() システムは、addr から始まり、len バイトまで続くアドレス範囲のロックページを呼び出します。呼び出しが正常に戻ると、指定されたアドレス範囲の一部を含むすべてのページは、後でロックが解除されるまでメモリーに残ります。
mlockall() システムコールを使用すると、マップされたすべてのページを指定されたアドレス範囲にロックできます。メモリーロックはスタックしません。いくつかの呼び出しによってロックされたページは、単一の munlock() システム呼び出しで、指定されたアドレス範囲または領域全体のロックを解除します。munlockall() システムコールを使用すると、プログラム空間全体をロック解除できます。
特定の範囲に含まれるページのステータスは、flags 引数の値によって異なります。flags 引数は 0 または MLOCK_ONFAULT です。
メモリーロックは fork によって子プロセスに継承されず、プロセスが終了すると自動的に削除されます。
mlock() システムコールは注意して使用してください。過度に使用すると、メモリー不足 (OOM) エラーが発生する可能性があります。アプリケーションが大きい、またはアプリケーションに大きなデータドメインがあるとき、システムが他のタスクにメモリーを割り当てることができない場合は、mlock() 呼び出しによってスラッシングが発生する可能性があります。
リアルタイムプロセスに mlockall() 呼び出しを使用する場合は、十分なスタックページを予約してください。
13.2. mlock() システムコールを使用したページのロック リンクのコピーリンクがクリップボードにコピーされました!
リアルタイム mlock() システムコールは、addr パラメーターを使用してアドレス範囲の開始を指定し、len を使用してアドレス空間の長さをバイト単位で定義します。この alloc_workbuf() 関数はメモリーバッファーを動的に割り当ててロックします。メモリー割り当ては、posix_memalig() 関数によって行われ、メモリー領域がページに整列されます。free_workbuf() 関数は、メモリー領域のロックを解除します。
前提条件
-
root 権限、または大きなバッファーで
mlockall()またはmlock()を使用するためのCAP_IPC_LOCK機能を持っている。
手順
次のコードは、
mlock()システムコールでページをロックします。#include <stdlib.h> #include <unistd.h> #include <sys/mman.h> void *alloc_workbuf(size_t size) { void *ptr; int retval; // alloc memory aligned to a page, to prevent two mlock() in the same page. retval = posix_memalign(&ptr, (size_t) sysconf(_SC_PAGESIZE), size); // return NULL on failure if (retval) return NULL; // lock this buffer into RAM if (mlock(ptr, size)) { free(ptr); return NULL; } return ptr; } void free_workbuf(void *ptr, size_t size) { // unlock the address range munlock(ptr, size); // free the memory free(ptr); }
検証
リアルタイムの mlock() および munlock() 呼び出しは、成功すると 0 を返します。エラーの場合は、-1 を返し、エラーを示す errno を設定します。
13.3. mlockall() システムコールを使用して、マップされたすべてのページをロックする リンクのコピーリンクがクリップボードにコピーされました!
mlockall() および munlockall() システムコールを使用してリアルタイムメモリーをロックおよびロック解除するには、flags 引数を 0、もしくは定数 MCL_CURRENT または MCL_FUTURE のいずれかに設定します。MCL_FUTURE を使用すると、ロックされたバイト数が許可された最大値を超えるため、mmap(2)、sbrk(2)、malloc(3) などのシステムコールが後で失敗する可能性があります。
前提条件
- システムの root 権限がある。
手順
mlockall()およびmunlockall()リアルタイムシステムコールを使用するには、以下を実行します。mlockall()システムコールを使用して、マップされたすべてのページをロックします。#include <sys/mman.h> int mlockall (int flags)munlockall()システムコールを使用して、マップされたすべてのページのロックを解除します。#include <sys/mman.h> int munlockall (void)
13.4. mmap() システムコールを使用してファイルまたはデバイスをメモリーにマップする リンクのコピーリンクがクリップボードにコピーされました!
リアルタイムシステムで大量のメモリーを割り当てる場合、メモリー割り当て (malloc) メソッドは mmap() システムコールを使用してメモリー空間を見つけます。flags パラメーターに MAP_LOCKED を設定することで、メモリー領域を割り当てて、ロックできます。mmap() はページ単位でメモリーを割り当てるため、同じページで 2 つのロックが行われるのを回避し、二重ロックまたは単一ロック解除の問題を防ぎます。
前提条件
- システムの root 権限がある。
手順
特定のプロセスアドレス空間をマッピングするには、次のようにします。
#include <sys/mman.h> #include <stdlib.h> void *alloc_workbuf(size_t size) { void *ptr; ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED, -1, 0); if (ptr == MAP_FAILED) return NULL; return ptr; } void free_workbuf(void *ptr, size_t size) { munmap(ptr, size); }
検証
-
mmap()関数が正常に完了すると、マップされた領域へのポインターが返されます。エラーの場合は、MAP_FAILED値を返し、エラーを示すerrnoを設定します。 -
munmap()関数が正常に完了すると、0が返されます。エラーの場合は-1を返し、エラーを示すerrnoを設定します。
13.5. mlock() システムコールのパラメーター リンクのコピーリンクがクリップボードにコピーされました!
mlock パラメーターの表で、メモリーロックシステムコールのパラメーターとそれらが実行する機能を一覧にして説明します。
| パラメーター | 説明 |
|---|---|
|
|
ロックまたはロック解除するプロセスアドレス空間を指定します。NULL の場合、カーネルはメモリー内のデータのページ整列配置を選択します。 |
|
| マッピングの長さを指定します。これは 0 より大きくなければなりません。 |
|
| ファイル記述子を指定します。 |
|
|
|
|
|
同じファイルをマップする他のプロセスへのマッピングの可視性を制御します。 |
|
| 現在プロセスにマップされているすべてのページをロックします。 |
|
| 後続のメモリー割り当てをロックするモードを設定します。これらは、増大するヒープとスタックに必要な新しいページ、新しいメモリーマップファイル、または共有メモリー領域である可能性があります。 |
第14章 RHEL for Real Time での timerlat を使用したスケジューリングレイテンシーの測定 リンクのコピーリンクがクリップボードにコピーされました!
rtla-timerlat ツールは、timerlat トレーサーのインターフェイスです。timerlat トレーサーは、リアルタイムスレッドのウェイクアップレイテンシーの原因を検出します。timerlat トレーサーは、リアルタイム優先度の CPU ごとにカーネルスレッドを作成します。これらのスレッドは、ウェイクアップするため、およびスリープに戻るための定期的なタイマーを設定します。ウェイクアップ時に、timerlat は情報を検索して収集します。この情報は、オペレーティングシステムのタイマーレイテンシーのデバッグに役立ちます。timerlat トレーサーは、アクティブになるたびに出力を生成し、次の 2 行を出力します。
-
timerlatトレーサーは、タイマー割り込み要求 (IRQ) ハンドラーで見られたタイマーレイテンシーを定期的に出力します。これは、スレッドのアクティブ化の前に、hardirqコンテキストで表示される最初の出力です。 -
2 番目の出力は、スレッドのタイマーレイテンシーです。
ACTIVATION IDフィールドには、それぞれのスレッド実行に対する割り込み要求 (IRQ) のパフォーマンスが表示されます。
14.1. スケジューリングレイテンシーを測定するための timerlat トレーサーの設定 リンクのコピーリンクがクリップボードにコピーされました!
トレースシステムの curret_tracer ファイルに timerlat を追加することで、timerlat トレーサーを設定できます。current_tracer ファイルは通常、/sys/kernel/tracing ディレクトリーにマウントされます。timerlat トレーサーは、スレッドのレイテンシーが 100 マイクロ秒を超えた場合に割り込み要求 (IRQ) を測定し、分析用にトレース出力を保存します。
手順
現在のトレーサーをリストします。
# cat /sys/kernel/tracing/current_tracer nopno operations(nop) がデフォルトのトレーサーです。トレースシステムの
current_tracerファイルにtimerlatトレーサーを追加します。# cd /sys/kernel/tracing/ # echo timerlat > current_tracerトレース出力を生成します。
# cat trace # tracer: timerlat
検証
次のコマンドを入力して、
timerlatが現在のトレーサーとして有効になっているかどうかを確認します。# cat /sys/kernel/tracing/current_tracer timerlat
14.2. timerlat トレーサーのオプション リンクのコピーリンクがクリップボードにコピーされました!
timerlat トレーサーは、osnoise トレーサーをベースに構築されています。したがって、/osnoise/config ディレクトリーにオプションを設定して、スレッドスケジューリングのレイテンシーに関する情報をトレースおよびキャプチャーできます。
timerlat のオプション
- cpus
-
timerlatスレッドを実行する CPU を設定します。 - timerlat_period_us
-
timerlatスレッドの期間をマイクロ秒単位で設定します。 - stop_tracing_us
-
irqコンテキストでのタイマーレイテンシーが設定値を超えた場合、システムトレースを停止します。0 に設定すると、このオプションは無効になります。 - stop_tracing_total_us
- 合計ノイズが設定値を超えた場合、システムのトレースを停止します。0 に設定すると、このオプションは無効になります。
- print_stack
- 発生した割り込み要求 (IRQ) のスタックを保存します。スタックは、スレッドコンテキストイベントの後に、または IRQ ハンドラーが設定値を超えた場合に、発生した IRQ を保存します。
14.3. rtla-timerlat-top を使用したタイマーレイテンシーの測定 リンクのコピーリンクがクリップボードにコピーされました!
rtla-timerlat-top トレーサーは、timerlat tracer からの定期的な出力のサマリーを表示します。トレーサー出力は、osnoise、tracepoints など、各オペレーティングシステムのノイズとイベントに関する情報も提供します。この情報は、-t オプションを使用して表示できます。
手順
タイマーレイテンシーを測定するには、以下を実行します。
# rtla timerlat top -s 30 -T 30 -t
14.4. rtla timerlat top トレーサーのオプション リンクのコピーリンクがクリップボードにコピーされました!
rtla timerlat top --help コマンドを使用すると、rtla-timerlat-top tracer のオプションの使用法に関するヘルプを表示できます。
timerlat-top-tracer オプション
- -p、--period us
-
timerlatトレーサーの期間をマイクロ秒単位で設定します。 - -i、--irq us
- 割り込み要求 (IRQ) のレイテンシーが引数 (マイクロ秒単位) を超えた場合、トレースを停止します。
- -T、--thread us
- スレッドのレイテンシーが引数 (マイクロ秒単位) を超えた場合、トレースを停止します。
- -t、--trace
-
停止したトレースを
timerlat_trace.txtファイルに保存します。 - -s、--stack us
- スレッドのレイテンシーが引数を超えた場合、割り込み要求 (IRQ) 時にスタックトレースを保存します。
第15章 RHEL for Real Time での rtla-osnoise を使用したスケジューリングレイテンシーの測定 リンクのコピーリンクがクリップボードにコピーされました!
超低レイテンシーとは、遅延に対する許容度が低く、大量のデータパケットを処理するように最適化された環境です。超低レイテンシー環境では、CPU などの専用リソースをアプリケーションに提供することが一般的に行われます。たとえば、ネットワーク機能仮想化 (NFV) アプリケーションにおける高パフォーマンスネットワーク処理では、単一のアプリケーションに、タスクを継続的に実行するための CPU 電力制限が設定されます。
Linux カーネルには、オペレーティングシステムノイズ (osnoise) トレーサーのインターフェイスを提供するリアルタイム分析 (rtla) ツールが搭載されています。オペレーティングシステムノイズとは、オペレーティングシステム内のアクティビティーの結果としてアプリケーションで発生する干渉のことです。Linux システムでは、次の原因でノイズが発生する可能性があります。
- マスク不可割り込み (NMI)
- 割り込み要求 (IRQ)
- ソフトウェア割り込み要求 (SoftIRQ)
- その他のシステムスレッドアクティビティー
- マスク不可能な高優先度のシステム管理割り込み (SMI) など、ハードウェア関連ジョブ
15.1. rtla-osnoise トレーサー リンクのコピーリンクがクリップボードにコピーされました!
Linux カーネルには、オペレーティングシステムノイズ (osnoise) トレーサーのインターフェイスを提供するリアルタイム分析 (rtla) ツールが搭載されています。rtla-osnoise トレーサーは、指定された期間にわたって定期的に実行されるスレッドを作成します。period の開始時に、スレッドは割り込みを無効にして、サンプリングを開始し、ループで時間をキャプチャーします。
rtla-osnoise トレーサーは次の機能を提供します。
- CPU が受けるオペレーティングノイズを測定します。
- CPU で発生するオペレーティングシステムノイズの種類を特徴付けます。
- 予期せぬ結果の根本原因を特定するのに役立つ、最適化されたトレースレポートを出力します。
- 干渉源ごとに干渉カウンターを保存します。マスク不可割り込み (NMI)、割り込み要求 (IRQ)、ソフトウェア割り込み要求 (SoftIRQ)、およびスレッドの干渉カウンターは、ツールがこれらの干渉のエントリーイベントを検出すると増加します。
rtla-osnoise トレーサーは、期間の終了時に、ノイズ源に関する次の情報を含む実行レポートを出力します。
- ノイズの総量。
- ノイズの最大量。
- スレッドに割り当てられている CPU の割合。
- ノイズ源のカウンター。
15.2. スケジューリングレイテンシーを測定するための rtla-osnoise トレーサーの設定 リンクのコピーリンクがクリップボードにコピーされました!
トレースシステムの curret_tracer ファイルに osnoise を追加することで、rtla-osnoise トレーサーを設定できます。current_tracer ファイルは通常、/sys/kernel/tracing/ ディレクトリーにマウントされます。rtla-osnoise トレーサーは、スレッドのレイテンシーが 1 回のノイズ発生で 20 マイクロ秒を超えた場合に割り込み要求 (IRQ) を測定し、分析用にトレース出力を保存します。
手順
現在のトレーサーをリストします。
# cat /sys/kernel/tracing/current_tracer nopno operations(nop) がデフォルトのトレーサーです。トレースシステムの
current_tracerファイルにtimerlatトレーサーを追加します。# cd /sys/kernel/tracing/ # echo osnoise > current_tracerトレース出力を生成します。
# cat trace # tracer: osnoise
15.3. rtla-osnoise の設定オプション リンクのコピーリンクがクリップボードにコピーされました!
rtla-osnoise トレーサーの設定オプションは、/sys/kernel/tracing/ ディレクトリーにあります。
rtla-osnoise の設定オプション
- osnoise/cpus
-
osnoiseスレッドを実行する CPU を設定します。 - osnoise/period_us
-
osnoiseスレッドを実行するperiodを設定します。 - osnoise/runtime_us
-
osnoiseスレッドの実行時間を設定します。 - osnoise/stop_tracing_us
-
単一のノイズが設定値を超えた場合、システムトレースを停止します。
0に設定すると、このオプションは無効になります。 - osnoise/stop_tracing_total_us
-
合計ノイズが設定値を超えた場合、システムのトレースを停止します。
0に設定すると、このオプションは無効になります。 - tracing_thresh
-
ノイズとみなす 2 回の
time()呼び出しの読み取り間の最小差をマイクロ秒単位で設定します。0に設定すると、tracing_threshはデフォルト値 (5 マイクロ秒) を使用します。
15.4. rtla-osnoise のトレースポイント リンクのコピーリンクがクリップボードにコピーされました!
rtla-osnoise には、オペレーティングシステムノイズ (osnoise) のソースを特定するための tracepoints のセットが含まれています。
rtla-osnoise のトレースポイント
- osnoise:sample_threshold
-
ノイズが設定されたしきい値 (
tolerance_ns) を超える場合にノイズを表示します。 - osnoise:nmi_noise
- マスク不可割り込み (NMI) からのノイズとノイズ継続時間を表示します。
- osnoise:irq_noise
- 割り込み要求 (IRQ) からのノイズとノイズ継続時間を表示します。
- osnoise:softirq_noise
- ソフトウェア割り込み要求 (SoftIRQ) からのノイズとノイズ継続時間を表示します。
- osnoise:thread_noise
- スレッドからのノイズとノイズの継続時間を表示します。
15.5. rtla-osnoise トレーサーのオプション リンクのコピーリンクがクリップボードにコピーされました!
osnoise/options ファイルには、rtla-osnoise トレーサーの on および off 設定オプションのセットが含まれています。
rtla-osnoise のオプション
- DEFAULTS
- オプションをデフォルト値にリセットします。
- OSNOISE_WORKLOAD
-
osnoiseワークロードのディスパッチを停止します。 - PANIC_ON_STOP
-
トレーサーが停止した場合に、
panic()呼び出しを設定します。このオプションは、vmcoreダンプファイルをキャプチャーします。 - OSNOISE_PREEMPT_DISABLE
-
osnoiseワークロードのプリエンプションを無効にし、割り込み要求 (IRQ) とハードウェア関連のノイズのみを許容します。 - OSNOISE_IRQ_DISABLE
-
osnoiseワークロードの割り込み要求 (IRQ) を無効にし、マスク不可割り込み (NMI) とハードウェア関連のノイズのみを許容します。
15.6. rtla-osnoise-top トレーサーを使用したオペレーティングシステムノイズの測定 リンクのコピーリンクがクリップボードにコピーされました!
rtla osnoise-top トレーサーは、干渉源の発生カウンターに関する情報とともに、osnoise トレーサーからの定期的なサマリーを測定し、出力します。
手順
システムのノイズを測定します。
# rtla osnoise top -P F:1 -c 0-3 -r 900000 -d 1M -qコマンドの出力には、リアルタイム優先度、スレッドを実行するために割り当てられた CPU、および実行期間 (マイクロ秒単位) に関する情報を含む定期的なサマリーが表示されます。
15.7. rtla-osnoise-top トレーサーのオプション リンクのコピーリンクがクリップボードにコピーされました!
rtla osnoise top --help コマンドを使用すると、rtla-osnoise-top トレーサーで利用できるオプションの使用法に関するヘルプを表示できます。
rtla-osnoise-top のオプション
- -a、--auto us
-
自動トレースモードを設定します。このモードは、システムのデバッグ時に一般的に使用するオプションを設定します。これは、
-sus-T1および-tを使用した場合と同じです。 - -p、--period us
-
osnoiseトレーサーの期間をマイクロ秒単位で設定します。 - -r、--runtime us
-
osnoiseトレーサーの実行時間をマイクロ秒単位で設定します。 - -s、--stop us
-
単一のサンプルが引数 (マイクロ秒単位) を超えた場合、トレースを停止します。
-tを指定すると、トレースが出力に保存されます。 - -S、--stop-total us
-
合計サンプルがマイクロ秒単位の引数を超えた場合、トレースを停止します。
-Tを指定すると、トレースが出力に保存されます。 - -T、--threshold us
- ノイズとみなす 2 回の時間読み取り間の最小差を指定します。デフォルトのしきい値は 5 us です。
- -q、--quiet
- 実行の最後にサマリーのみを出力します。
- -c、--cpus cpu-list
-
割り当てられた
cpu-listでサンプルスレッドを実行するようにosnoiseトレーサーを設定します。 - -d、--duration time[s|m|h|d]
- 実行時間を設定します。
- -D、--debug
- デバッグ情報を出力します。
- -t、--trace[=file]
-
停止したトレースを
[file|osnoise_trace.txt]ファイルに保存します。 - -e、--event sys:event
-
トレース (
-t) セッションでイベントを有効にします。引数には、-e sched:sched_switchなどの特定のイベント、または-e schedなどのシステムグループのすべてのイベントを指定できます。 - --filter <filter>
-
フィルター式を使用して、前の
-e sys:eventシステムイベントをフィルターします。 - --trigger <trigger>
-
以前の
-e sys:eventシステムイベントに対するトレースイベントトリガーを有効にします。 - -P、--priority o:prio|r:prio|f:prio|d:runtime:period
-
osnoiseトレーサースレッドにスケジューリングパラメーターを設定します。 - -h、--help
- ヘルプメニューを出力します。
第16章 ジャーナリングに起因するシステムの速度低下を最小限に抑えるか回避する リンクのコピーリンクがクリップボードにコピーされました!
ジャーナルの変更がディスクに書き込まれる順序は、到着する順序と異なる場合があります。カーネル I/O システムは、ジャーナルの変更の並べ替えを行い、利用可能なストレージ領域の使用を最適化できます。ジャーナルアクティビティーは、ジャーナルの変更を並べ替え、データおよびメタデータをコミットすることで、システムレイテンシーが発生する可能性があります。その結果、ファイルシステムのジャーナリングによってシステムの速度が低下する可能性があります。
XFS は、RHEL 8 で使用されるデフォルトのファイルシステムです。これはジャーナリングファイルシステムです。ext2 と呼ばれる古いファイルシステムは、ジャーナリングを使用しません。特にジャーナリングが必要な場合を除き、ext2 ファイルシステムを検討してください。Red Hat の最良なベンチマーク結果の多くでは、ext2 ファイルシステムが使用されています。これは、重要な初期チューニングの推奨項目の 1 つです。
XFS のようなジャーナリングファイルシステムは、ファイルが最後にアクセスされた時刻を記録します (atime 属性)。ジャーナリングファイルシステムを使用する必要がある場合は、atime を無効にすることを検討してください。
16.1. atime の無効化 リンクのコピーリンクがクリップボードにコピーされました!
atime 属性を無効にすると、ファイルシステムジャーナルへの書き込み回数が制限されるため、パフォーマンスが向上し、電力使用量が減少します。
手順
任意のテキストエディターを使用して
/etc/fstabファイルを開き、ルートマウントポイントのエントリーを見つけます。/dev/mapper/rhel-root / xfs defaults…オプションのセクションを編集して、
noatimeおよびnodiratimeという用語を追加します。noatimeオプションは、ファイルの読み取り時のアクセスタイムスタンプの更新を阻止し、nodiratimeオプションは、ディレクトリーの inode へのアクセス時刻の更新を停止します。/dev/mapper/rhel-root / xfs noatime,nodiratime…
一部のアプリケーションは、更新される atime に依存します。したがって、このオプションは、このようなアプリケーションが使用されていないシステムでのみ妥当です。
または、前のアクセス時刻が現在の変更時刻よりも古い場合にのみ、アクセス時刻が更新されるようにする relatime マウントオプションを使用することができます。
第17章 レイテンシーの影響を受けるワークロードのグラフィックコンソール出力の無効化 リンクのコピーリンクがクリップボードにコピーされました!
カーネルは、起動直後に printk() にメッセージを渡し始めます。カーネルはログファイルにメッセージを送信して、ヘッドレスサーバーに接続されているモニターがない場合でも、グラフィックコンソールにも表示します。
一部のシステムでは、グラフィックコンソールに送信された出力が原因でパイプラインが停滞する可能性があります。これにより、データ転送の待機中にタスクの実行が遅延する可能性があります。たとえば、teletype0 (/dev/tty0) に送信された出力が原因で、システムの停滞が発生する可能性があります。
予期しない停滞を防ぐため、グラフィックコンソールに送信される情報を以下で制限または無効にできます。
-
tty0定義を削除する。 - コンソール定義の順序を変更する。
-
ほとんどの
printk()関数をオフにし、必ずignore_loglevelカーネルパラメーターをnot configuredに設定する。
グラフィックコンソール出力のログオンを無効にし、グラフィックコンソールに出力されるメッセージを制御することにより、レイテンシーの影響を受けやすいワークロードでレイテンシーを改善できます。
17.1. グラフィックコンソールのグラフィックアダプターへのロギングの無効化 リンクのコピーリンクがクリップボードにコピーされました!
デフォルトのカーネルコンソールである teletype (tty) は、入力データをシステムに渡してグラフィックコンソールに出力情報を表示することで、システムとの対話を可能にします。
グラフィックコンソールを設定しないと、グラフィックアダプターにログの記録ができなくなります。これにより、tty0 はシステムで利用できず、グラフィックコンソールでのメッセージの出力を無効にするのに役立ちます。
グラフィックコンソールの出力を無効にしても、情報は削除されません。この情報はシステムログに出力され、journalctl ユーティリティーまたは dmesg ユーティリティーを使用して情報にアクセスできます。
手順
カーネル設定から
console=tty0オプションを削除します。# grubby --update-kernel=ALL --remove-args="console=tty0"
17.2. メッセージのグラフィックコンソールへの出力の無効化 リンクのコピーリンクがクリップボードにコピーされました!
必要なログレベルを /proc/sys/kernel/printk ファイルに設定すると、グラフィックコンソールに送信される出力メッセージの量を制御できます。
手順
現在のコンソールログレベルを表示します。
$ cat /proc/sys/kernel/printk 7 4 1 7このコマンドは、システムログレベルの現在の設定を出力します。数字は、システムロガーの current、default、minimum、および boot-default の値に対応します。
/proc/sys/kernel/printkファイルで希望のログレベルを設定します。$ echo “1” > /proc/sys/kernel/printkコマンドは、現在のコンソールログレベルを変更します。たとえば、ログレベル 1 を設定すると、警告メッセージのみが出力され、グラフィックコンソールに他のメッセージが表示されないようになります。
第18章 アプリケーションのニーズを満たすためのシステムクロックの管理 リンクのコピーリンクがクリップボードにコピーされました!
NUMA や SMP などのマルチプロセッサーシステムには、複数のハードウェアクロックインスタンスがあります。起動時に、カーネルは利用可能なクロックソースを検出し、使用するクロックソースを選択します。パフォーマンスを改善するために、リアルタイムシステムの最小要件を満たすために使用されるクロックソースを変更できます。
18.1. ハードウェアクロック リンクのコピーリンクがクリップボードにコピーされました!
Non-Uniform Memory Access (NUMA) や Symmetric multiprocessing (SMP) などのマルチプロセッサーシステムに見られるクロックソースの複数のインスタンスは、それらの間で相互作用し、CPU 周波数スケーリングまたはエネルギーエコノミーモードへの移行などのシステムイベントへの反応により、それらがリアルタイムカーネルに適したクロックソースであるかどうかを判断します。
推奨されるクロックソースは Time Stamp Counter (TSC) です。TSC が利用できない場合は、High Precision Event Timer (HPET) が 2 番目に最適なオプションとなります。ただし、すべてのシステムに HPET クロックがあるわけではなく、一部の HPET クロックは信頼できない可能性があります。
TSC および HPET がない場合のオプションとして、ACPI Power Management Timer (ACPI_PM)、Programmable Interval Timer (PIT)、Real Time Clock (RTC) などがあります。最後の 2 つのオプションは、読み取るのにコストがかかるか、分解能 (時間粒度) が低いかのどちらかであるため、リアルタイムカーネルでの使用は準最適となります。
18.2. システムで利用可能なクロックソースの表示 リンクのコピーリンクがクリップボードにコピーされました!
システムで利用可能なクロックソースのリストは、/sys/devices/system/clocksource/clocksource0/available_clocksource ファイルにあります。
手順
available_clocksourceファイルを表示します。# cat /sys/devices/system/clocksource/clocksource0/available_clocksource tsc hpet acpi_pmこの例では、システムで利用可能なクロックソースは TSC、HPET、および ACPI_PM です。
18.3. 現在使用中のクロックソースの表示 リンクのコピーリンクがクリップボードにコピーされました!
システムで現在使用されているクロックソースは、/sys/devices/system/clocksource/clocksource0/current_clocksource ファイルに保存されています。
手順
current_clocksourceファイルを表示します。# cat /sys/devices/system/clocksource/clocksource0/current_clocksource tscこの例では、システムの現在のクロックソースは TSC です。
18.4. 使用するクロックソースの一時的な変更 リンクのコピーリンクがクリップボードにコピーされました!
クロックの既知の問題により、システムのメインアプリケーションに最適なクロックが使用されないことがあります。問題のあるすべてのクロックを除外した後、システムに残ったハードウェアクロックが、リアルタイムシステムの最低要件を満たせないことがあります。
重要なアプリケーションの要件は、システムごとに異なります。そのため、各アプリケーション、したがって各システムに適したクロックも異なります。一部のアプリケーションはクロックの分解能に依存し、信頼できるナノ秒の読み取りを提供するクロックの方が適しています。また、クロックを読み取るアプリケーションは、読み取りコスト (読み取り要求と結果の間隔) の小さいクロックからメリットを得ることができます。
これらのケースでは、カーネルが選択したクロックをオーバーライドできます。ただし、このオーバーライドの副次的な影響を理解し、そのハードウェアクロックの既知の欠点をトリガーしない環境を作成できる場合に限ります。
カーネルは、利用可能な最適なクロックソースを自動的に選択します。選択したクロックソースのオーバーライドは、影響が明確に理解されない限り推奨されません。
前提条件
- システムの root 権限がある。
手順
利用可能なクロックソースを表示します。
# cat /sys/devices/system/clocksource/clocksource0/available_clocksource tsc hpet acpi_pm例として、システムで利用可能なクロックソースが TSC、HPET、および ACPI_PM であると考えてください。
使用するクロックソースの名前を
/sys/devices/system/clocksource/clocksource0/current_clocksourceファイルに書き込みます。# echo hpet > /sys/devices/system/clocksource/clocksource0/current_clocksource注記変更は現在使用中のクロックソースに適用されます。システムの再起動後、デフォルトのクロックが使用されます。変更を永続化させるには、カーネルチューニングパラメーターの変更の永続化 を参照してください。
検証
current_clocksourceファイルを表示して、現在のクロックソースが指定されたクロックソースであることを確認します。# cat /sys/devices/system/clocksource/clocksource0/current_clocksource hpetこの例では、システムの現在のクロックソースとして HPET を使用します。
18.5. ハードウェアクロックソースの読み込みコストの比較 リンクのコピーリンクがクリップボードにコピーされました!
システムのクロックの速度を比較できます。TSC からの読み取りは、プロセッサーからレジスターを読み取ることを意味します。HPET クロックからの読み取りには、メモリーエリアを読み取る必要があります。TSC からの読み取りが高速化され、毎秒大量のメッセージのタイムスタンプ処理を行う場合は、パフォーマンスが大幅に向上します。
前提条件
- システムの root 権限がある。
-
clock_timingプログラムがシステム上にある。詳細は、clock_timing プログラム を参照してください。
手順
clock_timingプログラムが保存されるディレクトリーに移動します。# cd clock_testシステムで利用可能なクロックソースを表示します。
# cat /sys/devices/system/clocksource/clocksource0/available_clocksource tsc hpet acpi_pmこの例では、システムで利用可能なクロックソースは
TSC、HPET、およびACPI_PMになります。現在使用中のクロックソースを表示します。
# cat /sys/devices/system/clocksource/clocksource0/current_clocksource tscこの例では、システムの現在のクロックソースは
TSCです。./
clock_timingプログラムと共にtimeユーティリティーを実行します。この出力は、クロックソースを 1,000 万回読み込むために必要な期間を表示します。# time ./clock_timing real 0m0.601s user 0m0.592s sys 0m0.002sこの例は、以下のパラメーターを示しています。
-
real: プログラムの呼び出しから始まり、プロセスが終了するまでに費やした合計時間。realには、ユーザーとカーネル時間が含まれており、通常は後者 2 つの合計値よりも大きくなります。このプロセスが、優先度の高いアプリケーションや、ハードウェア割り込み (IRQ) などのシステムイベントによって中断される場合、待機に費やされたこの時間もrealとして計算されます。 -
user: カーネルの介入を必要としないタスクを実行するプロセスがユーザー空間で費やした時間。 -
sys: ユーザープロセスで必要なタスクの実行中にカーネルが費やした時間。これらのタスクには、ファイルのオープン、ファイルまたは I/O ポートの読み取りおよび書き込み、メモリーの割り当て、スレッドの作成、およびネットワーク関連のアクティビティーが含まれます。
-
/sys/devices/system/clocksource/clocksource0/current_clocksourceファイルに、テストする次のクロックソースの名前を書き込みます。# echo hpet > /sys/devices/system/clocksource/clocksource0/current_clocksourceこの例では、現在のクロックソースが
HPETに変更されています。- 利用可能なすべてのクロックソースに対して、ステップ 4 と 5 を繰り返します。
- 利用可能なすべてのクロックソースについて、ステップ 4 の結果を比較します。
18.6. Opteron CPU での TSC タイマーの同期 リンクのコピーリンクがクリップボードにコピーされました!
AMD64 Opteron プロセッサーの現行世代は、大きな gettimeofday スキューの影響を受けやすい可能性があります。このスキューは、cpufreq および Time Stamp Counter (TSC) の両方が使用されている場合に発生します。RHEL for Real Time は、すべてのプロセッサーが同じ頻度に同時に変更することで、このスキューを防ぐ方法を提供します。そのため、1 つのプロセッサーの TSC は、別のプロセッサーの TSC とは異なる速度で増加することはありません。
前提条件
- システムの root 権限がある。
手順
clocksource=tscおよびpowernow-k8.tscsync=1カーネルオプションを有効にします。# grubby --update-kernel=ALL --args="clocksource=tsc powernow-k8.tscsync=1"これにより、TSC の使用が強制され、同時にコアプロセッサーの周波数遷移が有効になります。
- マシンを再起動します。
18.7. clock_timing プログラム リンクのコピーリンクがクリップボードにコピーされました!
clock_timing プログラムは、現在のクロックソースを 1,000 万回読み取ります。time ユーティリティーと共に、これを行うために必要な時間を測定します。
手順
clock_timing プログラムを作成するには、以下を実行します。
プログラムファイルのディレクトリーを作成します。
$ mkdir clock_test作成したディレクトリーに移動します。
$ cd clock_testソースファイルを作成してテキストエディターで開きます。
$ {EDITOR} clock_timing.cファイルに以下のコマンドを入力します。
#include <time.h> void main() { int rc; long i; struct timespec ts; for(i=0; i<10000000; i++) { rc = clock_gettime(CLOCK_MONOTONIC, &ts); } }- ファイルを保存して、エディターを終了します。
ファイルをコンパイルします。
$ gcc clock_timing.c -o clock_timing -lrtclock_timingプログラムの準備ができ、保存されているディレクトリーから実行できます。
第19章 電源管理移行の制御 リンクのコピーリンクがクリップボードにコピーされました!
電源管理の移行を制御すると、レイテンシーが改善されます。
前提条件
- システムの root 権限がある。
19.1. 省電力の状態 リンクのコピーリンクがクリップボードにコピーされました!
最新のプロセッサーは、低い省電力状態から高い省電力状態 (C-state) にアクティブに移行します。ただし、高い省電力状態から稼働状態に戻ると、リアルタイムアプリケーションの理想よりも多くの時間を消費してしまいます。アプリケーションは Power Management Quality of Service (PM QoS) インターフェイスを使用して、これらの移行を防ぐことができます。
PM QoS インターフェイスを使用すると、システムは idle=poll および processor.max_cstate=1 パラメーターの動作をエミュレートできますが、省電力の状態をより詳細に制御できます。idle=poll は、プロセッサーが idle 状態になることを防ぎます。processor.max_cstate=1 は、プロセッサーがより深い C-state (省電力モード) に入ることを阻止します。
アプリケーションが /dev/cpu_dma_latency ファイルを開いたままにすると、PM QoS インターフェイスはプロセッサーが深いスリープ状態に入ることを阻止します。これにより、終了する際に予期せぬレイテンシーが発生します。ファイルが閉じられると、システムは省電力状態に戻ります。
19.2. 電源管理状態の設定 リンクのコピーリンクがクリップボードにコピーされました!
次のいずれかの方法で電源管理の状態を設定することで、電源管理の移行を制御できます。
-
/dev/cpu_dma_latencyファイルに値を書き込んで、プロセスの最大応答時間をマイクロ秒単位で変更し、低レイテンシーが必要になるまでファイル記述子を開いたままにします。 -
アプリケーションまたはスクリプトで
/dev/cpu_dma_latencyファイルを参照します。
前提条件
- 管理者権限がある。
手順
/dev/cpu_dma_latencyに最大応答時間 (マイクロ秒単位) を表す 32 ビットの数値を書き込むことでレイテンシー許容度を指定し、低レイテンシー操作によってファイル記述子を開いたままにします。値0は C 状態を完全に無効にします。以下に例を示します。
import os import signal import sys if not os.path.exists('/dev/cpu_dma_latency'): print("no PM QOS interface on this system!") sys.exit(1) try: fd = os.open('/dev/cpu_dma_latency', os.O_WRONLY) os.write(fd, b'\0\0\0\0') print("Press ^C to close /dev/cpu_dma_latency and exit") signal.pause() except KeyboardInterrupt: print("closing /dev/cpu_dma_latency") os.close(fd) sys.exit(0)注記Power Management Quality of Service (
pm_qos) インターフェイスは、ファイル記述子が開いている間のみアクティブになります。したがって、/dev/cpu_dma_latencyへのアクセスに使用するスクリプトまたはプログラムは、電源状態の移行が許可されるまでファイルを開いたままにしておく必要があります。
第20章 割り込みとユーザープロセスを分離してシステムレイテンシーを最小限に抑える リンクのコピーリンクがクリップボードにコピーされました!
リアルタイム環境では、さまざまなイベントに応答する際にレイテンシーを最小限に抑える必要があります。これを行うには、割り込み (IRQ) とさまざまな専用 CPU 上のユーザープロセスを相互に分離します。
20.1. 割り込みおよびプロセスバインディング リンクのコピーリンクがクリップボードにコピーされました!
割り込み (IRQ) をさまざまな専用 CPU 上のユーザープロセスから分離することで、リアルタイム環境でのレイテンシーを最小限に抑えるか、なくすことができます。
通常、割り込みは CPU 間で均等に共有されます。これにより、CPU が新しいデータおよび命令キャッシュを書き込む必要があるときに、割り込み処理が遅延する場合があります。これらの割り込みの遅延は、同じ CPU で実行されている他の処理との競合を引き起こす可能性があります。
タイムクリティカルな割り込みおよびプロセスを特定の CPU (または CPU の範囲) に割り当てることができます。これにより、この割り込みを処理するコードおよびデータ構造がプロセッサーおよび命令キャッシュにある可能性が非常に高くなります。その結果、専用のプロセスはできるだけ迅速に実行でき、他のすべてのタイムクリティカルでないプロセスは他の CPU で実行されます。これは、関連する速度がメモリーおよび使用可能なペリフェラルバス帯域幅の限界に近いか限界に達している場合に、特に重要になる可能性があります。メモリーがプロセッサーキャッシュにフェッチされるのを待つと、全体的な処理時間と決定論は著しく影響を受けます。
実際には、最適なパフォーマンスはアプリケーションによってまったく異なります。たとえば、同様の機能を持つアプリケーションを異なる企業向けにチューニングする場合、全く異なる最適なパフォーマンスチューニングが必要になります。
- ある企業では、4 つの CPU のうち 2 つをオペレーティングシステムの機能と割り込み処理用に分離した時に、最適な結果が得られました。残りの 2 つの CPU は、純粋にアプリケーション処理専用でした。
- 別の会社では、ネットワーク関連のアプリケーションプロセスを、ネットワークデバイスドライバーの割り込みを処理する単一の CPU にバインドしたときに、最適な決定論が得られました。
プロセスを CPU にバインドするには、通常、特定の CPU または CPU の範囲の CPU マスクを把握する必要があります。CPU マスクは通常、使用するコマンドに応じて、32 ビットのビットマスク、10 進数、または 16 進数で表されます。
| CPU | ビットマスク | 10 進数 | 16 進数 |
| 0 | 00000000000000000000000000000001 | 1 | 0x00000001 |
| 0, 1 | 00000000000000000000000000000011 | 3 | 0x00000011 |
20.2. irqbalance デーモンの無効化 リンクのコピーリンクがクリップボードにコピーされました!
irqbalance デーモンはデフォルトで有効になっており、複数の CPU に対して定期的に割り込みの均等な処理を強制します。ただし、リアルタイムのデプロイメントでは、アプリケーションは通常特定の CPU にバインドされているため、irqbalance は必要ありません。
手順
irqbalanceのステータスを確認します。# systemctl status irqbalance irqbalance.service - irqbalance daemon Loaded: loaded (/usr/lib/systemd/system/irqbalance.service; enabled) Active: active (running) …irqbalanceが実行されている場合、これを無効にして停止します。# systemctl disable irqbalance # systemctl stop irqbalance
検証
irqbalanceステータスが非アクティブであることを確認します。# systemctl status irqbalance
20.3. IRQ バランスからの CPU の除外 リンクのコピーリンクがクリップボードにコピーされました!
IRQ バランシングサービスを使用して、割り込み (IRQ) バランシングを考慮する際に除外する CPU を指定できます。/etc/sysconfig/irqbalance 設定ファイルの IRQBALANCE_BANNED_CPUS パラメーターは、この設定を制御します。パラメーターの値は 64 ビットの 16 進数ビットマスクで、マスクの各ビットは CPU コアを表します。
手順
任意のテキストエディターで
/etc/sysconfig/irqbalanceを開き、IRQBALANCE_BANNED_CPUSというファイルのセクションを見つけます。# IRQBALANCE_BANNED_CPUS # 64 bit bitmask which allows you to indicate which cpu's should # be skipped when reblancing irqs. Cpu numbers which have their # corresponding bits set to one in this mask will not have any # irq's assigned to them on rebalance # #IRQBALANCE_BANNED_CPUS=-
IRQBALANCE_BANNED_CPUS変数のコメントを解除します。 - 適切なビットマスクを入力し、IRQ バランスメカニズムで無視される CPU を指定します。
- ファイルを保存してから閉じます。
irqbalanceサービスを再起動して、変更を有効にします。# systemctl restart irqbalance
最大 64 個の CPU コアを持つシステムを実行している場合は、それぞれ 8 桁の 16 進数のグループをコンマで区切ります。例: IRQBALANCE_BANNED_CPUS=00000001,0000ff00
| CPU | ビットマスク |
| 0 | 00000001 |
| 8 - 15 | 0000ff00 |
| 8 - 15, 33 | 00000002,0000ff00 |
IRQBALANCE_BANNED_CPUS が /etc/sysconfig/irqbalance に設定されていない場合、RHEL 7.2 以降では、irqbalance ユーティリティーは isolcpus カーネルパラメーターを介して分離した CPU コアの IRQ を自動的に回避します。
20.4. 個々の IRQ への CPU アフィニティーの手動割り当て リンクのコピーリンクがクリップボードにコピーされました!
CPU アフィニティーを割り当てると、指定した CPU または CPU の範囲にプロセスとスレッドをバインドおよびバインド解除できます。これにより、キャッシュの問題を減らすことができます。
手順
/proc/interruptsファイルを表示して、各デバイスで使用されている IRQ を確認します。# cat /proc/interrupts各行には、IRQ 番号、各 CPU で発生した割り込みの数、IRQ タイプ、および説明が表示されます。
CPU0 CPU1 0: 26575949 11 IO-APIC-edge timer 1: 14 7 IO-APIC-edge i8042特定の IRQ の
smp_affinityエントリーに CPU マスクを書き込みます。CPU マスクは、16 進数で表記する必要があります。たとえば、以下のコマンドは、IRQ 番号 142 が CPU 0 でのみ実行されるように指示します。
# echo 1 > /proc/irq/142/smp_affinityこの変更は、割り込みが発生した場合にのみ有効になります。
検証
- 指定の割り込みをトリガーするアクティビティーを実行します。
/proc/interruptsで変更を確認します。設定された IRQ の指定された CPU の割り込みの数は増加し、指定されたアフィニティー外の CPU で設定された IRQ の割り込みの数は増加しませんでした。
20.5. taskset ユーティリティーを使用したプロセスの CPU へのバインド リンクのコピーリンクがクリップボードにコピーされました!
taskset ユーティリティーは、タスクのプロセス ID (PID) を使用して、その CPU アフィニティーを表示または設定します。このユーティリティーを使用して、選択した CPU アフィニティーでコマンドを実行できます。
アフィニティーを設定するには、CPU マスクを 10 進数または 16 進数にする必要があります。mask 引数は、変更されるコマンドまたは PID に対して有効な CPU コアを指定する bitmask です。
taskset ユーティリティーは NUMA (Non-Uniform Memory Access) システムで動作しますが、ユーザーが CPU および最も近い NUMA メモリーノードにスレッドをバインドすることはできません。このようなシステムでは、taskset は推奨されるツールではなく、その高度な機能を使用するには、代わりに numactl ユーティリティーを使用する必要があります。
詳細は、システム上の numactl(8) man ページを参照してください。
手順
必要なオプションおよび引数を指定して
tasksetを実行します。CPU マスクの代わりに -c パラメーターを使用して CPU リストを指定できます。この例では、
my_embedded_processは、CPU 0、4、7 - 11 でのみ実行するように指示されています。# taskset -c 0,4,7-11 /usr/local/bin/my_embedded_processほとんどの場合、この呼び出しは便利です。
現在実行されていないプロセスのアフィニティーを設定するには、
tasksetを使用して、CPU マスクとプロセスを指定します。この例では、
my_embedded_processは、CPU 3 のみを使用するように指示されています (CPU マスクの 10 進数バージョンを使用)。# taskset 8 /usr/local/bin/my_embedded_processビットマスクで複数の CPU を指定できます。この例では、
my_embedded_processは、プロセッサー 4、5、6、および 7 で実行するように指示されています (CPU マスクの 16 進数バージョンを使用)。# taskset 0xF0 /usr/local/bin/my_embedded_process変更するプロセスの CPU マスクと PID を指定して、
-p(--pid) オプションを使用することにより、すでに実行されているプロセスの CPU アフィニティーを設定できます。この例では、PID が 7013 のプロセスは CPU 0 でのみ実行するように指示されています。# taskset -p 1 7013
リスト表示されているオプションを組み合わせることができます。
第21章 Out of Memory (OOM) 状態の管理 リンクのコピーリンクがクリップボードにコピーされました!
Out-of-memory (OOM) は、スワップ領域を含む利用可能なメモリーがすべて割り当てられているコンピューティング状態です。通常、これによりシステムがパニックになり、想定どおりに機能しなくなります。以下で説明する手順は、システムの OOM 状態を回避するのに役立ちます。
前提条件
- システムの root 権限がある。
21.1. Out of Memory 値の変更 リンクのコピーリンクがクリップボードにコピーされました!
/proc/sys/vm/panic_on_oom ファイルには、Out of Memory (OOM) の動作を制御するスイッチである値が含まれます。ファイルに 1 が含まれる場合、カーネルは OOM でパニックになり、期待どおりに機能しなくなります。
デフォルト値は 0 で、システムが OOM 状態の場合に oom_killer() 関数を呼び出すようカーネルに指示します。通常、oom_killer() は不要なプロセスを終了します。これにより、システムの存続が可能になります。
/proc/sys/vm/panic_on_oom の値を変更できます。
手順
/proc/sys/vm/panic_on_oomの現在の値を表示します。# cat /proc/sys/vm/panic_on_oom 0/proc/sys/vm/panic_on_oomの値を変更するには、次のコマンドを実行します。echo コマンドを使用して、新しい値を
/proc/sys/vm/panic_on_oomに代入します。# echo 1 > /proc/sys/vm/panic_on_oom
OOM 時に Real-Time カーネルをパニック状態にすることが推奨されます (1)。そうしないと、システムが OOM 状態になった場合、その状態は決定論的ではなくなります。
検証
/proc/sys/vm/panic_on_oomの値を表示します。# cat /proc/sys/vm/panic_on_oom 1- 表示される値が指定された値と一致していることを確認します。
21.2. Out of Memory 状態のときに強制終了するプロセスの優先順位付け リンクのコピーリンクがクリップボードにコピーされました!
oom_killer() 関数で終了するプロセスに優先順位を付けることができます。これにより、優先順位の高いプロセスが OOM 状態の間も実行され続けることが保証されます。各プロセスには /proc/PID ディレクトリーがあります。各ディレクトリーには、以下のファイルが含まれます。
-
oom_score_adj- oom_score_adj の有効なスコアは、-16 から +15 の範囲です。この値は、他の要因の中でも特に、プロセスの実行時間も考慮に入れるアルゴリズムを使用して、プロセスのパフォーマンスフットプリントを計算するために使用されます。 -
oom_score-oom_score_adjの値を使用して計算されたアルゴリズムの結果が含まれます。
メモリー不足の状態では、oom_killer() 関数は oom_score が最も高いプロセスを終了します。
プロセスの `oom_score_adj` ファイルを編集することで、終了するプロセスの優先度を設定できます。
前提条件
- 優先するプロセスのプロセス ID (PID) を把握している。
手順
プロセスの現在の
oom_scoreを表示します。# cat /proc/12465/oom_score 79872プロセスの
oom_score_adjの内容を表示します。# *cat /proc/12465/oom_score_adj * 13oom_score_adjの値を編集します。# *echo -5 > /proc/12465/oom_score_adj *
検証
プロセスの現在の
oom_scoreを表示します。# cat /proc/12465/oom_score 78- 表示される値が以前の値よりも小さいことを確認します。
21.3. プロセスの Out of Memory Killer の無効化 リンクのコピーリンクがクリップボードにコピーされました!
プロセスの oom_killer() 関数を無効にするには、oom_score_adj を予約値である -17 に設定します。これにより、OOM 状態でもプロセスが存続します。
手順
oom_score_adjの値を-17に設定します。# echo -17 > /proc/12465/oom_score_adj
検証
プロセスの現在の
oom_scoreを表示します。# cat /proc/12465/oom_score 0-
表示される値が
0であることを確認します。
第22章 tuna CLI を使用したレイテンシーの向上 リンクのコピーリンクがクリップボードにコピーされました!
tuna CLI を使用して、システムのレイテンシーを改善できます。RHEL 9 用の tuna CLI には、argparse 解析モジュールをベースとしたコマンドラインが搭載されています。このインターフェイスは次の機能を提供します。
- より標準化されたコマンドとオプションのメニュー
-
このインターフェイスでは、事前定義された入力を使用でき、
tunaによって入力が正しい型であることが確認されます。 - パラメーターの使用法に関するヘルプメッセージを自動的に生成し、無効な引数を含むエラーメッセージを表示します。
22.1. 前提条件 リンクのコピーリンクがクリップボードにコピーされました!
-
tunaおよびpython-linux-procfsパッケージがインストールされている。 - システムの root 権限がある。
22.2. tuna CLI リンクのコピーリンクがクリップボードにコピーされました!
tuna コマンドラインインターフェイス (CLI) は、システムのチューニング変更を行うためのツールです。
tuna ツールは実行中のシステムで使用するように設計されており、変更がすぐに反映されます。これにより、アプリケーション固有の測定ツールは、変更が加えられた直後にシステムパフォーマンスを確認および分析できます。
tuna CLI には、以前はアクションオプションであったコマンドのセットが追加されています。それらのコマンドを以下に示します。
- isolate
-
すべてのスレッドと IRQ を
CPU-LISTから分離します。 - include
-
すべてのスレッドが
CPU-LIST上で実行されるように設定します。 - move
-
特定のエンティティーを
CPU-LISTに移動します。 - spread
-
選択したエンティティーを
CPU-LISTに分散します。 - priority
-
POLICYやRTPRIOなどのスレッドスケジューラーの調整可能パラメーターを設定します。 - run
- 新しいプロセスをフォークしてコマンドを実行します。
- save
-
kthreadsschedtunablesをFILENAMEに保存します。 - apply
- プロファイルで定義された変更を適用します。
- show_threads
- スレッドリストを表示します。
- show_irqs
-
IRQリストを表示します。 - show_configs
- 既存のプロファイルのリストを表示します。
- what_is
- 選択したエンティティーに関するヘルプを表示します。
- gui
- グラフィカルユーザーインターフェイス (GUI) を起動します。
コマンドは、tuna -h コマンドで表示できます。各コマンドにはオプションの引数があり、tuna <command> -h コマンドで表示できます。たとえば、tuna isolate -h コマンドを使用すると、isolate のオプションを表示できます。
22.3. tuna CLI を使用した CPU の分離 リンクのコピーリンクがクリップボードにコピーされました!
tuna CLI を使用して、割り込み (IRQ) をさまざまな専用 CPU 上のユーザープロセスから分離し、リアルタイム環境でのレイテンシーを最小限に抑えることができます。CPU の分離に関する詳細は、割り込みおよびプロセスバインディング を参照してください。
前提条件
-
tunaおよびpython-linux-procfsパッケージがインストールされている。 - システムの root 権限がある。
手順
1 つ以上の CPU を分離します。
# tuna isolate --cpus=<cpu_list>cpu_listは、分離する CPU のコンマ区切りリストまたは範囲です。以下に例を示します。
# tuna isolate --cpus=0,1または
# tuna isolate --cpus=0-5
22.4. tuna CLI を使用した指定の CPU への割り込みの移動 リンクのコピーリンクがクリップボードにコピーされました!
tuna CLI を使用して、割り込み (IRQ) を専用の CPU に移動し、リアルタイム環境でのレイテンシーを最小限に抑えるか、なくすことができます。IRQ の移動に関する詳細は、割り込みおよびプロセスバインディング を参照してください。
前提条件
-
tunaおよびpython-linux-procfsパッケージがインストールされている。 - システムの root 権限がある。
手順
IRQ のリストが割り当てられている CPU をリスト表示します。
# tuna show_irqs --irqs=<irq_list>irq_listは、割り当てられている CPU を一覧表示する IRQ のコンマ区切りリストです。以下に例を示します。
# tuna show_irqs --irqs=128IRQ のリストを CPU のリストに割り当てます。
# tuna move --irqs=irq_list --cpus=<cpu_list>irq_listは割り当てる IRQ のコンマ区切りリストで、cpu_listはその割り当て先の CPU のコンマ区切りリストまたは範囲です。以下に例を示します。
# tuna move --irqs=128 --cpus=3
検証
IRQ を指定された CPU に移動する前後で、選択された IRQ の状態を比較します。
# tuna show_irqs --irqs=128
22.5. tuna CLI を使用したプロセススケジューリングポリシーおよび優先順位の変更 リンクのコピーリンクがクリップボードにコピーされました!
tuna CLI を使用して、プロセススケジューリングポリシーおよび優先順位を変更できます。
前提条件
-
tunaおよびpython-linux-procfsパッケージがインストールされている。 システムの root 権限がある。
注記OTHERおよびBATCHスケジューリングポリシーの割り当てには、root 権限は必要ありません。
手順
スレッドの情報を表示します。
# tuna show_threads --threads=<thread_list>thread_listは、表示するプロセスのコンマ区切りリストです。以下に例を示します。
# tuna show_threads --threads=42369,42416,43859プロセススケジューリングポリシーとスレッドの優先度を変更します。
# tuna priority scheduling_policy:priority_number --threads=<thread_list>-
thread_listは、スケジューリングポリシーおよび優先度を表示するプロセスのコンマ区切りリストです。 scheduling_policyは以下のいずれかになります。- OTHER
- BATCH
- FIFO: First In First Out (先入れ先出し)
- RR - Round Robin (ラウンドロビン)
priority_numberは 0 から 99 までの優先順位で、0は優先度がなく、99は優先度が最も高くなります。注記OTHERおよびBATCHスケジューリングポリシーでは、優先度を指定する必要はありません。さらに、唯一の有効な優先度 (指定する場合) は0です。FIFOおよびRRスケジューリングポリシーには、1以上の優先度が必要です。以下に例を示します。
-
# tuna priority FIFO:1 --threads=42369,42416,43859
検証
- スレッドの情報を表示して、情報が変更されることを確認します。
# tuna show_threads --threads=42369,42416,43859
第23章 スケジューラーの優先順位の設定 リンクのコピーリンクがクリップボードにコピーされました!
Red Hat Enterprise Linux for Real Time カーネルを使用すると、スケジューラーの優先度を詳細に制御できます。また、アプリケーションレベルのプログラムをカーネルスレッドよりも優先度の高い状態でスケジュールすることもできます。
スケジューラーの優先順位を設定すると、悪影響が出る可能性があり、重要なカーネルプロセスが想定どおりに実行されない場合、システムが応答しなくなることや、予期せぬ動作を示すことがあります。最終的には、正しい設定はワークロードによって異なります。
23.1. スレッドのスケジューリングの優先度の表示 リンクのコピーリンクがクリップボードにコピーされました!
スレッドの優先度は、0 (最低優先度) から 99 (最高優先度) まで、一連のレベルを使用して設定されます。systemd サービスマネージャーは、カーネルの起動後に、スレッドのデフォルトの優先度を変更するのに使用できます。
手順
実行中のスレッドのスケジューリング優先度を表示するには、tuna ユーティリティーを使用します。
# tuna --show_threads thread ctxt_switches pid SCHED_ rtpri affinity voluntary nonvoluntary cmd 2 OTHER 0 0xfff 451 3 kthreadd 3 FIFO 1 0 46395 2 ksoftirqd/0 5 OTHER 0 0 11 1 kworker/0:0H 7 FIFO 99 0 9 1 posixcputmr/0 ...[output truncated]...
23.2. 起動時のサービスの優先度の変更 リンクのコピーリンクがクリップボードにコピーされました!
systemd を使用すると、システムの起動時に起動するサービスのリアルタイムの優先度を設定できます。
ユニット設定ディレクティブを使用して、起動プロセス時のサービスの優先度を変更します。ブートプロセスの優先順位の変更は、/etc/systemd/system/service.service.d/priority.conf の service セクションにある以下のディレクティブを使用して行います。
CPUSchedulingPolicy=
実行されるプロセスの CPU スケジューリングポリシーを設定します。Linux で利用可能なスケジューリングクラスのいずれかを設定できます。
-
other -
batch -
idle -
fifo -
rr
CPUSchedulingPriority=
実行されるプロセスの CPU スケジューリングの優先度を設定します。設定可能な優先度の範囲は、選択した CPU スケジューリングポリシーにより異なります。リアルタイムスケジューリングポリシーでは、1 (最低優先度) から 99 (最高優先度) までの整数を使用できます。
前提条件
- 管理者権限がある。
- システムの起動時に実行するサービス。
手順
既存のサービスに対して以下を実行します。
サービスの補助サービス設定ディレクトリーファイルを作成します。
# cat <<-EOF > /etc/systemd/system/mcelog.service.d/priority.confファイルの
[Service]セクションに、スケジューリングポリシーと優先度を追加します。以下に例を示します。
[Service] CPUSchedulingPolicy=fifo CPUSchedulingPriority=20 EOFsystemdスクリプトの設定を再読み込みします。# systemctl daemon-reloadサービスを再起動します。
# systemctl restart mcelog
検証
サービスの優先度を表示します。
$ tuna -t mcelog -Pこの出力は、設定されているサービスの優先度を示します。
以下に例を示します。
thread ctxt_switches pid SCHED_ rtpri affinity voluntary nonvoluntary cmd 826 FIFO 20 0,1,2,3 13 0 mcelog
23.3. サービスの CPU 使用率の設定 リンクのコピーリンクがクリップボードにコピーされました!
systemd を使用して、サービスを実行できる CPU を指定できます。
前提条件
- 管理者権限がある。
手順
サービスの補助サービス設定ディレクトリーファイルを作成します。
# md sscd[Service]セクションのCPUAffinity属性を使用して、サービスに使用する CPU をファイルに追加します。以下に例を示します。
[Service] CPUAffinity=0,1 EOFsystemd スクリプトの設定を再読み込みします。
# systemctl daemon-reloadサービスを再起動します。
# systemctl restart service
検証
指定したサービスを実行可能な CPU を表示します。
$ tuna -t mcelog -Pserviceは、指定したサービスに置き換えます。以下の出力は、
mcelogが CPU 0 および 1 に制限されていることを示しています。thread ctxt_switches pid SCHED_ rtpri affinity voluntary nonvoluntary cmd 12954 FIFO 20 0,1 2 1 mcelog
23.4. 優先順位マップ リンクのコピーリンクがクリップボードにコピーされました!
スケジューラーの優先順位はグループで定義され、一部のグループは特定のカーネル機能の専用となります。
| 優先度 | Threads | 説明 |
|---|---|---|
| 1 | 優先度の低いカーネルスレッド |
通常、この優先度は |
| 2 - 49 | 利用可能 | 標準的なアプリケーションの優先度に使用される範囲。 |
| 50 | デフォルトの IRQ 値 | この優先度は、ハードウェアベースの割り込みのデフォルト値です。 |
| 51 - 98 | 優先度の高いスレッド |
この範囲は、定期的に実行され、応答時間が短くなければならないスレッドに使用されます。低いレベルの割り込みに対答できなっくなるので、CPU にバインドされたスレッドには、この範囲を使用 |
| 99 | ウォッチドッグおよび移行 | 最も高い優先順位で実行される必要があるシステムスレッド。 |
第24章 ネットワーク決定のヒント リンクのコピーリンクがクリップボードにコピーされました!
TCP はレイテンシーに大きな影響を及ぼす可能性があります。TCP は、効率を高め、輻輳を制御し、信頼できる配信を保証するためにレイテンシーを追加します。チューニング時には、以下の点を考慮してください。
- 順番どおりの配信が必要か。
パケットロスに対して保護する必要があるか。
複数回パケットを送信すると遅延が発生する可能性があります。
TCP を使用する必要があるか。
ソケットで
TCP_NODELAYを使用して Nagle バッファリングアルゴリズムを無効にすることを検討してください。Nagle アルゴリズムはすべてを一度に送信するために小さな送信パケットを収集するので、レイテンシーに悪影響を及ぼす可能性があります。
24.1. 遅延またはスループットの扱いに注意が必要なサービス向けに RHEL を最適化する リンクのコピーリンクがクリップボードにコピーされました!
結合チューニングの目標は、特定のワークロードに必要な割り込みの数を最小限に抑えることです。高スループットの状況では、高いデータレートを維持しながら、割り込みをできるだけ少なくすることが目標となります。待ち時間が短い状況では、より多くの割り込みを使用してトラフィックを迅速に処理できます。
ネットワークカードの設定を調整して、1 つの割り込みに結合されるパケットの数を増減できます。その結果、トラフィックのスループットまたは遅延を向上させることができます。
手順
ボトルネックが発生しているネットワークインターフェイスを特定します。
# ethtool -S enp1s0 NIC statistics: rx_packets: 1234 tx_packets: 5678 rx_bytes: 12345678 tx_bytes: 87654321 rx_errors: 0 tx_errors: 0 rx_missed: 0 tx_dropped: 0 coalesced_pkts: 0 coalesced_events: 0 coalesced_aborts: 0名前に
drop、discardまたはerrorを含むパケットカウンターを特定します。これらの特定の統計は、ネットワークインターフェイスカード (NIC) の結合によって発生する可能性がある、NIC のパケットバッファーでの実際のパケットロスを測定します。前の手順で特定したパケットカウンターの値を監視します。
これらをネットワークの予想値と比較して、特定のインターフェイスにボトルネックが発生しているかどうかを判断します。ネットワークのボトルネックの一般的な兆候には次のようなものがありますが、これらに限定されません。
- ネットワークインターフェイス上での多数のエラー
- 高いパケットロス
ネットワークインターフェイスの多用
注記ネットワークのボトルネックを特定する際のその他の重要な要素としては、CPU 使用率、メモリー使用率、ディスク I/O などがあります。
現在の割り込み結合設定を確認します。
# ethtool -c enp1s0 Coalesce parameters for enp1s0: Adaptive RX: off Adaptive TX: off RX usecs: 100 RX frames: 8 RX usecs irq: 100 RX frames irq: 8 TX usecs: 100 TX frames: 8 TX usecs irq: 100 TX frames irq: 8-
usecs値は、受信機または送信機が割り込みを生成する前に待機するマイクロ秒数を指します。 -
frames値は、受信機または送信機が割り込みを生成する前に待機するフレーム数を指します。 irq値は、ネットワークインターフェイスがすでに割り込みを処理している場合に、割り込み調整を設定するために使用されます。注記すべてのネットワークインターフェイスカードが、出力例のすべての値のレポートと変更をサポートしているわけではありません。
-
Adaptive RX/TX値は、割り込み結合設定を動的に調整する適応割り込み結合メカニズムを表します。Adaptive RX/TXが有効な場合、NIC ドライバーはパケット条件に基づいて、結合値を自動計算します (アルゴリズムは NIC ドライバーごとに異なります)。
-
必要に応じて結合設定を変更します。以下に例を示します。
ethtool.coalesce-adaptive-rxが無効になっている間に、RX パケットの割り込みを生成するまでの遅延を 100 マイクロ秒に設定するようにethtool.coalesce-rx-usecsを設定します。# nmcli connection modify enp1s0 ethtool.coalesce-rx-usecs 100ethtool.coalesce-rx-usecsがデフォルト値に設定されている間、ethtool.coalesce-adaptive-rxを有効にします。# nmcli connection modify enp1s0 ethtool.coalesce-adaptive-rx onAdaptive-RX 設定を次のように変更します。
-
低レイテンシー (50us 未満) が気になるユーザーは、
Adaptive-RXを有効にしないでください。 -
スループットを懸念するユーザーは、おそらく問題なく
Adaptive-RXを有効にすることができます。適応割り込み結合メカニズムを使用したくない場合は、ethtool.coalesce-rx-usecsに 100us や 250us などの大きな値を設定してみることができます。 - 自分のニーズがわからないユーザーは、問題が発生するまでこの設定を変更しないでください。
-
低レイテンシー (50us 未満) が気になるユーザーは、
接続を再度有効にします。
# nmcli connection up enp1s0
検証
ネットワークパフォーマンスを監視し、ドロップされたパケットを確認します。
# ethtool -S enp1s0 NIC statistics: rx_packets: 1234 tx_packets: 5678 rx_bytes: 12345678 tx_bytes: 87654321 rx_errors: 0 tx_errors: 0 rx_missed: 0 tx_dropped: 0 coalesced_pkts: 12 coalesced_events: 34 coalesced_aborts: 56 ...rx_errors、rx_dropped、tx_errors、およびtx_droppedフィールドの値は 0 またはそれに近い値 (ネットワークトラフィックとシステムリソースに応じて最大数百まで) である必要があります。これらのフィールドの値が高い場合は、ネットワークに問題があることを示します。カウンターには異なる名前を付けることができます。名前に "drop"、"discard"、または "error" を含むパケットカウンターを注意深く監視します。rx_packets、tx_packets、rx_bytes、およびtx_bytesの値は時間の経過とともに増加します。値が増加しない場合は、ネットワークに問題がある可能性があります。パケットカウンターは、NIC ドライバーに応じて異なる名前を持つことができます。重要ethtoolコマンドの出力は、使用している NIC とドライバーによって異なる場合があります。極めて低いレイテンシーを重視するユーザーは、監視目的でアプリケーションレベルのメトリクスまたはカーネルパケットタイムスタンプ API を使用できます。
24.2. イーサネットネットワークのフロー制御 リンクのコピーリンクがクリップボードにコピーされました!
イーサネットリンクで、ネットワークインターフェイスとスイッチポートの間で継続的にデータ送信が行われると、バッファー容量がいっぱいになる可能性があります。バッファー容量がいっぱいになると、ネットワークの輻輳が発生します。この場合、送信側が受信側の処理能力よりも高いレートでデータを送信すると、パケットロスが発生する可能性があります。リンクの反対側のネットワークインターフェイス (スイッチポート) のデータ処理能力が低いためです。
フロー制御メカニズムは、送信側と受信側の送受信能力がそれぞれ異なるイーサネットリンクを介したデータ送信を管理します。パケットロスを回避するために、イーサネットフロー制御メカニズムはパケット送信を一時的に停止し、スイッチポート側の高い伝送レートを制御します。なお、スイッチがスイッチポートを越えてポーズフレームを転送することはありません。
受信 (RX) バッファーがいっぱいになると、受信側は送信側にポーズフレームを送信します。その後、送信側は、1 秒未満の短い期間、データ送信を停止しますが、この一時停止期間中は受信データのバッファリングを続けます。この期間は、受信側がインターフェイスバッファーを空にして、バッファーオーバーフローを防ぐのに十分な時間を提供します。
イーサネットリンクのどちら側も、ポーズフレームを反対側に送信できます。ネットワークインターフェイスの受信バッファーがいっぱいになると、ネットワークインターフェイスはポーズフレームをスイッチポートに送信します。同様に、スイッチポートの受信バッファーがいっぱいになると、スイッチポートはネットワークインターフェイスにポーズフレームを送信します。
デフォルトでは、Red Hat Enterprise Linux のほとんどのネットワークドライバーではポーズフレームのサポートが有効になっています。ネットワークインターフェイスの現在の設定を表示するには、次のように入力します。
# ethtool --show-pause enp1s0
Pause parameters for enp1s0:
...
RX: on
TX: on
...
スイッチのベンダーに問い合わせて、スイッチがポーズフレームをサポートしているかどうかを確認してください。
第25章 trace-cmd を使用したレイテンシーのトレース リンクのコピーリンクがクリップボードにコピーされました!
trace-cmd ユーティリティーは、ftrace ユーティリティーのフロントエンドです。trace-cmd を使用すると、/sys/kernel/debug/tracing/ ディレクトリーに書き込む必要なく、ftrace アクションを有効にすることができます。trace-cmd は、そのインストールにオーバーヘッドを追加しません。
前提条件
- 管理者権限がある。
25.1. trace-cmd のインストール リンクのコピーリンクがクリップボードにコピーされました!
trace-cmd ユーティリティーは、ftrace ユーティリティーのフロントエンドを提供します。
前提条件
- 管理者権限がある。
手順
trace-cmdユーティリティーをインストールします。# dnf install trace-cmd
25.2. trace-cmd の実行 リンクのコピーリンクがクリップボードにコピーされました!
trace-cmd ユーティリティーを使用して、すべての ftrace 機能にアクセスできます。
前提条件
- 管理者権限がある。
手順
trace-cmd commandを入力します。ここで、
commandはftraceオプションに置き換えます。注記コマンドとオプションのリストは、
trace-cmd(1)の man ページを参照してください。各コマンドのほとんどにも、独自の man ページ (trace-cmd-command) があります。
25.3. trace-cmd の例 リンクのコピーリンクがクリップボードにコピーされました!
以下のコマンド例で、trace-cmd ユーティリティーを使用してカーネル機能をトレースする方法を示します。
例
myapp の実行中に、カーネル内で実行中の記録機能を有効にして開始します。
# trace-cmd record -p function myappこれにより、myapp に無関係なタスクであっても、すべての CPU およびすべてのタスクの関数が記録されます。
結果を表示します。
# trace-cmd reportmyapp の実行中に、sched で始まる関数のみを記録します。
# trace-cmd record -p function -l 'sched*' myappすべての IRQ イベントを有効にします。
# trace-cmd start -e irqwakeup_rtトレーサーを起動します。# trace-cmd start -p wakeup_rt関数トレースを無効にしながら、
preemptirqsoffトレーサーを起動します。# trace-cmd start -p preemptirqsoff -d注記RHEL 8 の
trace-cmdは、function-traceではなくftrace_enabledを無効にします。trace-cmd start -p機能を使用すると、ftraceを再度有効にできます。trace-cmdが変更を開始する前の状態にシステムを戻します。# trace-cmd start -p noptrace-cmdを使用した後にdebugfsファイルシステムを使用する場合は、システムを再起動したかどうかに関係なく、これが重要になります。1 つのトレースポイントをトレースします。
# trace-cmd record -e sched_wakeup ls /binトレースを停止します。
# trace-cmd record stop
第26章 tuned-profiles-real-time を使用した CPU の分離 リンクのコピーリンクがクリップボードにコピーされました!
アプリケーションスレッドの実行時間を最大化するために、CPU を分離できます。そのため、無関係なタスクを可能な限り多く CPU から削除します。通常、CPU の分離には、以下の操作が必要です。
- ユーザー空間のスレッドをすべて削除する。
- バインドされていないカーネルスレッドを削除します。カーネル関連のバインドされたスレッドは特定の CPU にリンクされており、移動できません)。
-
システム内の各 Interrupt Request (IRQ) 番号が
Nの/proc/irq/N/smp_affinityプロパティーを変更して割り込みを削除する。
tuned-profiles-realtime パッケージの isolated_cores=cpulist 設定オプションを使用することで、CPU を分離する操作を自動化できます。
前提条件
- 管理者権限がある。
26.1. 分離する CPU の選択 リンクのコピーリンクがクリップボードにコピーされました!
分離する CPU を選択する際は、システムの CPU トポロジーを慎重に考慮する必要があります。ユースケースごとに異なる設定が必要です。
- スレッドがキャッシュを共有することによって相互に通信する必要があるマルチスレッドアプリケーションがある場合は、それらを同じ NUMA ノードまたは物理ソケットに保持する必要があります。
- 複数の無関係なリアルタイムアプリケーションを実行する場合は、CPU を NUMA ノードまたはソケットで分離することが適切な場合があります。
hwloc パッケージは、lstopo-no-graphics および numactl などの CPU に関する情報を取得する際に便利なユーティリティーを提供します。
前提条件
-
hwlocパッケージがインストールされます。
手順
物理パッケージで利用可能な CPU のレイアウトを表示します。
# lstopo-no-graphics --no-io --no-legend --of txt図26.1 lstopo-no-graphics を使用した CPU のレイアウトの表示
このコマンドは、使用可能なコア数とソケット数、および NUMA ノードの論理距離を示すため、マルチスレッドアプリケーションに役立ちます。
また、
hwloc-guiパッケージには、グラフィカル出力を生成するlstopoユーティリティーが含まれます。ノード間の距離など、CPU の詳細を表示します。
# numactl --hardware available: 2 nodes (0-1) node 0 cpus: 0 1 2 3 node 0 size: 16159 MB node 0 free: 6323 MB node 1 cpus: 4 5 6 7 node 1 size: 16384 MB node 1 free: 10289 MB node distances: node 0 1 0: 10 21 1: 21 10
26.2. TuneD の isolated_cores オプションを使用した CPU の分離 リンクのコピーリンクがクリップボードにコピーされました!
CPU を分離する最初のメカニズムは、カーネルブートコマンドラインでブートパラメーターの isolcpus=cpulist を指定することです。RHEL for Real Time での推奨の方法は、TuneD デーモンとその tuned-profiles-realtime を使用することです。
tuned-profiles-realtime バージョン 2.19 以降では、組み込み関数 calc_isolated_cores が初期 CPU セットアップを自動的に適用します。/etc/tuned/realtime-variables.conf 設定ファイルには、デフォルトの変数コンテンツが isolated_cores=${f:calc_isolated_cores:2} として含まれています。
デフォルトでは、calc_isolated_cores はソケットごとに 1 つのコアをハウスキーピング用に予約し、残りを分離します。デフォルト設定を変更する必要がある場合は、/etc/tuned/realtime-variables.conf 設定ファイルの isolated_cores=${f:calc_isolated_cores:2} 行をコメントアウトし、TuneD の isolated_cores オプションを使用して CPU を分離する手順に従います。
前提条件
-
TuneDパッケージおよびtuned-profiles-realtimeパッケージがインストールされている。 - システムの root 権限がある。
手順
-
root ユーザーとして、テキストエディターで
/etc/tuned/realtime-variables.confを開きます。 isolated_cores=cpulistを設定して、分離する CPU を指定します。CPU 番号および範囲を使用できます。例:
isolated_cores=0-3,5,7コア 0、1、2、3、5、および 7 を分離します。
8 コアの 2 ソケットシステム (NUMA ノード 0 にはコア 0-3 があり、NUMA ノード 1 にはコア 4-8 がある) で、マルチスレッドアプリケーションに 2 つのコアを割り当てるには、以下を指定します。
isolated_cores=4,5これにより、ユーザー空間のスレッドが CPU 4 および 5 に割り当てられなくなります。
無関係なアプリケーション用に、異なる NUMA ノードから CPU を選択するには、以下のコマンドを実行します。
isolated_cores=0,4これにより、ユーザー空間のスレッドが CPU 0 および 4 に割り当てられなくなります。
tuned-admユーティリティーを使用して、リアルタイムのTuneDプロファイルを有効にします。# tuned-adm profile realtime- マシンを再起動して変更を有効にします。
検証
カーネルコマンドラインで
isolcpusパラメーターを検索します。$ cat /proc/cmdline | grep isolcpus BOOT_IMAGE=/vmlinuz-4.18.0-305.rt7.72.el8.x86_64 root=/dev/mapper/rhel_foo-root ro crashkernel=auto rd.lvm.lv=rhel_foo/root rd.lvm.lv=rhel_foo/swap console=ttyS0,115200n81 isolcpus=0,4
26.3. nohz パラメーターおよび nohz_full パラメーターを使用した CPU の分離 リンクのコピーリンクがクリップボードにコピーされました!
nohz パラメーターおよび nohz_full パラメーターは、指定された CPU の動作を変更します。このようなカーネルブートパラメーターを有効にするには、realtime-virtual-host、realtime-virtual-guest、または cpu-partitioning のいずれかの TuneD プロファイルをチューニングする必要があります。
nohz=on特定の CPU セットでのタイマーアクティビティーを減らします。
nohzパラメーターは、主にアイドル状態の CPU でタイマー割り込みを減らすために使用されます。これにより、アイドル状態の CPU を低消費電力モードで実行でき、バッテリーの寿命を長持ちさせます。リアルタイムの応答時間に対して直接的なメリットはありませんが、nohzパラメーターはリアルタイムの応答時間に直接的な悪影響を与えることはありません。ただし、リアルタイムパフォーマンスにプラスの影響を与えるnohz_fullパラメーターを有効にするには、nohzパラメーターが必要です。nohz_full=cpulist-
nohz_fullパラメーターで指定した CPU のリストでは、タイマーティックを処理する方法が異なります。CPU がnohz_fullCPU として指定され、CPU に実行可能なタスクが 1 つしかないと、カーネルはその CPU へのタイマーティックの送信を停止します。その結果、アプリケーション実行の時間が長くなり、割り込みの処理やコンテキストの切り替えに対する時間が短くなります。
第27章 SCHED_OTHER タスクの移行の制限 リンクのコピーリンクがクリップボードにコピーされました!
sched_nr_migrate を使用すると、SCHED_OTHER が他の CPU に移行するタスクを制限できます。
前提条件
- 管理者権限がある。
27.1. タスクの移行 リンクのコピーリンクがクリップボードにコピーされました!
SCHED_OTHER タスクが他の多数のタスクを生成する場合、それらはすべて同じ CPU 上で実行されます。migration タスクまたは softirq は、アイドル状態の CPU で実行できるように、これらのタスクのバランスをとろうとします。
sched_nr_migrate は、一度に移動するタスクの数を指定するように調整できます。リアルタイムタスクの移行方法は異なるため、この影響を直接受けることはありません。ただし、softirq がタスクを移動すると、実行キューのスピンロックが有効になり、割り込みが無効になります。
移行が必要なタスクが多数存在すると、そのタスクは割り込みが無効になっている間に発生するため、タイマーイベントやウェイクアップは同時には行われません。これにより、sched_nr_migrate を大きい値に設定した場合に、リアルタイムタスクで深刻なレイテンシーが発生する可能性があります。
27.2. sched_nr_migrate 変数を使用した SCHED_OTHER タスクの移行の制限 リンクのコピーリンクがクリップボードにコピーされました!
sched_nr_migrate 変数の値を大きくすると、リアルタイムレイテンシーを犠牲にして、多くのタスクを起動する SCHED_OTHER スレッドから高パフォーマンスが得られます。
SCHED_OTHER タスクのパフォーマンスを犠牲にしてリアルタイムのタスクレイテンシーを低くするには、値を小さくする必要があります。デフォルト値は 8 です。
手順
sched_nr_migrate変数の値を調整するには、echo コマンドで値を直接/proc/sys/kernel/sched_nr_migrateに出力します。# echo 2 > /proc/sys/kernel/sched_nr_migrate
検証
/proc/sys/kernel/sched_nr_migrateのコンテンツを表示します。# cat > /proc/sys/kernel/sched_nr_migrate 2
第28章 TCP パフォーマンスのスパイクの低減 リンクのコピーリンクがクリップボードにコピーされました!
TCP タイムスタンプを生成すると、TCP パフォーマンスのスパイクが発生する可能性があります。sysctl は、TCP 関連のエントリー値を制御し、/proc/sys/net/ipv4/tcp_timestamps で検出された timestamps カーネルパラメーターを設定します。
前提条件
- 管理者権限がある。
28.1. TCP タイムスタンプの無効化 リンクのコピーリンクがクリップボードにコピーされました!
TCP タイムスタンプを無効にすると、TCP パフォーマンスの急激な変化を低減できます。
手順
TCP タイムスタンプをオフにします。
# sysctl -w net.ipv4.tcp_timestamps=0 net.ipv4.tcp_timestamps = 0この出力は、
net.ip4.tcp_timestampsオプションの値が0であることを示しています。つまり、TCP タイムスタンプが無効です。
28.2. TCP タイムスタンプの有効化 リンクのコピーリンクがクリップボードにコピーされました!
タイムスタンプを生成すると、TCP パフォーマンスのスパイクが発生する可能性があります。TCP タイムスタンプを無効にすることで、TCP パフォーマンスのスパイクを低減できます。TCP タイムスタンプを生成しても TCP パフォーマンスのスパイクが発生しない場合は、タイムスタンプを有効にできます。
手順
TCP タイムスタンプを有効にします。
# sysctl -w net.ipv4.tcp_timestamps=1 net.ipv4.tcp_timestamps = 1この出力は、
net.ip4.tcp_timestampsの値が1であることを示しています。つまり、TCP タイムスタンプが有効です。
28.3. TCP のタイムスタンプステータスの表示 リンクのコピーリンクがクリップボードにコピーされました!
TCP タイムスタンプの生成ステータスを表示できます。
手順
TCP タイムスタンプの生成ステータスを表示します。
# sysctl net.ipv4.tcp_timestamps net.ipv4.tcp_timestamps = 01は、タイムスタンプが生成されていることを示します。0は、タイムスタンプが生成されていないことを示しています。
第29章 RCU コールバックを使用した CPU パフォーマンスの改善 リンクのコピーリンクがクリップボードにコピーされました!
Read-Copy-Update (RCU) は、カーネル内でスレッドを相互に排他的にするロックレスのメカニズムです。RCU 操作を実施することで、コールバックが CPU のキューに置かれ、今後メモリーを安全に削除できる状況になると実行されます。
RCU コールバックを使用して CPU のパフォーマンスを改善するには、以下の操作を行います。
- CPU を、CPU コールバックの実行の候補から除外する。
- すべての RCU コールバックを処理する CPU を割り当てる。この CPU は、ハウスキーピング CPU と呼ばれます。
- CPU を、RCU オフロードスレッド起動の処理から除外する。
この組み合わせにより、ユーザーのワークロードに特化した CPU への干渉が軽減されます。
前提条件
- 管理者権限がある。
-
tunaがインストールされている。
29.1. RCU コールバックのオフロード リンクのコピーリンクがクリップボードにコピーされました!
rcu_nocbs および rcu_nocb_poll カーネルパラメーターを使用して、RCU コールバックをオフロードできます。
手順
RCU コールバックを実行する候補から 1 つ以上の CPU を除外するには、
rcu_nocbsカーネルパラメーターで CPU のリストを指定します。以下に例を示します。rcu_nocbs=1,4-6または
rcu_nocbs=32 つ目の例では、CPU 3 が no-callback CPU であることをカーネルに指示します。つまり、RCU コールバックは、CPU 3 に固定された
rcuc/$CPUスレッドではなく、rcuo/$CPUスレッドで実行されます。このスレッドをハウスキーピング CPU に移動すると、CPU 3 に RCU コールバックジョブが割り当てられなくなります。
29.2. RCU コールバックの移動 リンクのコピーリンクがクリップボードにコピーされました!
ハウスキーピング CPU を割り当てて、すべての RCU コールバックスレッドを処理できます。これには、tuna コマンドを使用して、すべての RCU コールバックをハウスキーピング CPU に移動します。
手順
RCU コールバックスレッドをハウスキーピング CPU に移動します。
# tuna --threads=rcu --cpus=x --moveここで、
xは、ハウスキーピング CPU の CPU 番号に置き換えます。
このアクションにより、CPU X 以外のすべての CPU が RCU コールバックスレッドを処理しなくなります。
29.3. CPU の RCU オフロードスレッド起動からの除外 リンクのコピーリンクがクリップボードにコピーされました!
RCU オフロードスレッドは別の CPU の RCU コールバックを実行できますが、各 CPU は対応する RCU オフロードスレッド起動を処理する必要があります。この処理を CPU で行わないようにすることができます。
手順
rcu_nocb_pollカーネルパラメーターを設定します。このコマンドにより、タイマーが RCU オフロードスレッドを定期的に起動して、実行するコールバックがあるかどうかを確認します。
第30章 ftrace を使用したレイテンシーのトレース リンクのコピーリンクがクリップボードにコピーされました!
ftrace ユーティリティーは、RHEL for Real Time Kernel で提供される診断機能の 1 つです。ftrace は、開発者がユーザー空間外で発生するレイテンシーおよびパフォーマンスの問題を分析およびデバッグするのに使用できます。ftrace ユーティリティーには、さまざまな方法でユーティリティーを使用できるさまざまなオプションがあります。これは、コンテキストスイッチの追跡、優先順位の高いタスクでのウェイクアップにかかる時間の測定、割り込みが無効になっている期間の測定、特定の期間中に実行されたカーネル関数のリストの表示に使用できます。
ftrace トレーサーなどの一部のトレーサーは、大量のデータ量を生成し、トレースログ分析を時間の消費タスクに切り替えます。ただし、トレーサーに対し、アプリケーションが重要なコードパスに到達した場合にのみ開始および終了するように指示することが可能です。
前提条件
- 管理者権限がある。
30.1. ftrace ユーティリティーを使用したレイテンシーの追跡 リンクのコピーリンクがクリップボードにコピーされました!
ftrace ユーティリティーを使用して、レイテンシーを追跡できます。
手順
システムで利用可能なトレーサーを表示します。
# cat /sys/kernel/debug/tracing/available_tracers function_graph wakeup_rt wakeup preemptirqsoff preemptoff irqsoff function nopftraceのユーザーインターフェイスは、debugfs内の一連のファイルです。ftraceファイルは、/sys/kernel/debug/tracing/ディレクトリーにあります。/sys/kernel/debug/tracing/ディレクトリーに移動します。# cd /sys/kernel/debug/tracingトレースを有効にするとシステムのパフォーマンスに影響を及ぼす可能性があるため、このディレクトリーのファイルを変更することができるのは root ユーザーのみです。
トレースセッションを開始するには、以下を行います。
-
/sys/kernel/debug/tracing/available_tracersで利用可能なトレーサーのリストから、使用するトレーサーを選択します。 セレクターの名前を
/sys/kernel/debug/tracing/current_tracerに挿入します。# echo preemptoff > /sys/kernel/debug/tracing/current_tracer注記echo コマンドと '>' 1 つを合わせて使用する場合は、ファイル内の既存の値が上書きされます。ファイルに値を追記する場合は、代わりに '>>' を使用します。
-
function-traceオプションは、wakeup_rt、preemptirqsoffなどを使用してレイテンシーをトレースすると、関数のトレースが自動的に有効になり、オーバーヘッドが誇張される可能性があるため便利です。functionおよびfunction_graphのトレースが有効になっているかどうかを確認します。# cat /sys/kernel/debug/tracing/options/function-trace 1-
値を
1に設定すると、functionとfunction_graphのトレースが有効になります。 -
値が
0の場合は、functionおよびfunction_graphのトレースが無効になっていることを示します。
-
値を
デフォルトでは、
functionおよびfunction_graphトレースは有効になっています。functionおよびfunction_graphのトレースのオン/オフを切り替えるには、/sys/kernel/debug/tracing/options/function-traceに適切な値を echo で追加します。# echo 0 > /sys/kernel/debug/tracing/options/function-trace # echo 1 > /sys/kernel/debug/tracing/options/function-trace重要echoコマンドを使用する場合は、値と>文字の間に空白文字を配置するようにしてください。0>、1>、および2>(空白文字なし) を使用するシェルプロンプトでは、標準入力、標準出力、および標準エラーを参照します。誤ってそれらを使用すると、トレースが予期せぬ出力になる可能性があります。/debugfs/tracing/ディレクトリー内のさまざまなファイルの値を変更して、トレーサーの詳細とパラメーターを調整します。以下に例を示します。
irqsoff、preemptoff、preempirqsoff、およびwakeupトレーサーは、レイテンシーを継続的に監視します。tracing_max_latencyに記録されたレイテンシーよりも大きいレイテンシーを記録すると、そのレイテンシーのトレースが記録され、tracing_max_latencyが新しい最大時間に更新されます。これにより、tracing_max_latencyは、最後にリセットされてから記録された最大のレイテンシーを常に表示します。最大レイテンシーをリセットするには、
0をtracing_max_latencyファイルに echo で追加します。# echo 0 > /sys/kernel/debug/tracing/tracing_max_latency設定された量よりも大きいレイテンシーのみを表示するには、マイクロ秒単位で量を echo で出力します。
# echo 200 > /sys/kernel/debug/tracing/tracing_max_latencyトレースのしきい値を設定すると、最大レイテンシー設定が上書きされます。しきい値より大きいレイテンシーが記録されると、最大レイテンシーに関係なく記録されます。トレースファイルを確認すると、最後に記録されたレイテンシーのみが表示されます。
しきい値を設定するには、それを超えるとレイテンシーを記録する必要があるマイクロ秒数を echo で出力します。
# echo 200 > /sys/kernel/debug/tracing/tracing_thresh
トレースログを表示します。
# cat /sys/kernel/debug/tracing/traceトレースログを保存するには、別のファイルにコピーします。
# cat /sys/kernel/debug/tracing/trace > /tmp/lat_trace_logトレースされている関数を表示します。
# cat /sys/kernel/debug/tracing/set_ftrace_filter-
/sys/kernel/debug/tracing/set_ftrace_filterで設定を編集して、トレースしている関数をフィルターにかけます。ファイルにフィルターが指定されていない場合、すべての関数がトレースされます。 フィルター設定を変更するには、トレースする関数名を echo で追記します。このフィルターでは、検索用語の先頭または末尾に '*' ワイルドカードを使用できます。
例は ftrace の例 を参照してください。
30.2. ftrace ファイル リンクのコピーリンクがクリップボードにコピーされました!
/sys/kernel/debug/tracing/ ディレクトリーの主なファイルを以下に示します。
ftrace ファイル
- trace
-
ftraceトレースの出力を表示するファイル。これは、このファイルが読み込まれるとトレースが停止し、読み込まれたイベントを使用しないため、実際にはトレースのスナップショットです。つまり、ユーザーがトレースを無効にしてこのファイルを読み取ると、読み取り時に毎回同じ内容を報告します。 - trace_pipe
-
トレースをライブで読み込む際に、
ftraceトレースの出力を表示するファイル。これは、プロデューサー/コンシューマーのトレースです。つまり、読み取りごとに、読み取られたイベントが消費されます。これは、読み取り時にトレースを停止せずに、アクティブなトレースの読み取りで使用できます。 - available_tracers
- カーネルにコンパイルされた ftrace トレーサーのリスト。
- current_tracer
-
ftraceトレーサーを有効または無効にします。 - events
- トレースするイベントが含まれ、イベントを有効または無効にするのに使用できるディレクトリーと、イベントのフィルターの設定を行うことができます。
- tracing_on
-
ftraceバッファーへの録画を無効および有効にします。tracing_onファイル経由でトレースを無効にしても、カーネル内で行われている実際のトレースは無効になりません。バッファーへの書き込みのみを無効にします。トレースを実行する作業は継続されますが、データはどこにも移動しません。
30.3. ftrace トレーサー リンクのコピーリンクがクリップボードにコピーされました!
カーネルの設定方法によっては、指定のカーネルですべてのトレーサーが利用できるとは限りません。RHEL for Real Time カーネルの場合、トレースカーネルおよびデバッグカーネルには、実稼働カーネルとは異なるトレーサーがあります。これは、トレーサーの一部にトレーサーがカーネルに設定され、アクティブではない場合に大きなオーバーヘッドが発生するためです。このトレーサーは、trace および debug カーネルに対してのみ有効になります。
トレーサー
- function
- 最も広く適用されるトレーサーの 1 つ。カーネル内の関数呼び出しを追跡します。トレースされる関数の数によっては、目立ったオーバーヘッドが発生する場合があります。アクティブでない場合は、ほとんどオーバーヘッドが発生しません。
- function_graph
function_graphトレーサーは、より視覚に訴える形式で結果を表示するように設計されています。このトレーサーは、関数の終了を追跡し、カーネル内の関数呼び出しのフローを表示します。注記このトレーサーは、有効化されると
functionトレーサーよりもオーバーヘッドが高くなりますが、無効化されると同じオーバーヘッドが低くなります。- wakeup
- すべての CPU でアクティビティーが発生することを報告する完全な CPU トレーサー。リアルタイムタスクであるかに関わらず、システム内で最も優先度の高いタスクを起動するのにかかる時間を記録します。非リアルタイムタスクを起動するのにかかる最大時間の記録では、リアルタイムタスクを起動するのにかかる時間が非表示になります。
- wakeup_rt
- すべての CPU でアクティビティーが発生することを報告する完全な CPU トレーサー。現在の最も高い優先度タスクから、ウェイクアップ時間まで経過時間を記録します。このトレーサーは、リアルタイムタスクの時間のみを記録します。
- preemptirqsoff
- プリエンプションまたは割り込みを無効にするエリアを追跡し、プリエンプションまたは割り込みが無効となった最大時間を記録します。
- preemptoff
- preemptirqsoff トレーサーと似ていますが、プリエンプションが無効化された最大間隔のみをトレースします。
- irqsoff
- preemptirqsoff トレーサーと似ていますが、割り込みが無効化された最大間隔のみをトレースします。
- nop
-
デフォルトのトレーサー。トレース機能自体は提供しませんが、イベントがトレーサーにインターリーブする可能性があるため、
nopトレーサーは、イベントのトレースに特に関心がある場合に使用されます。
30.4. ftrace の例 リンクのコピーリンクがクリップボードにコピーされました!
以下では、トレースする関数のフィルター処理を変更する例を多数説明します。単語の先頭と末尾の両方に * ワイルドカードを使用できます。たとえば、*irq\* は、名前に irq を含むすべての関数を選択します。ただし、ワイルドカードは単語内で使用できません。
検索用語とワイルドカード文字を二重引用符で囲むと、シェルが検索を現在の作業ディレクトリーに拡張しないようにします。
フィルターの例
schedule関数のみをトレースします。# echo schedule > /sys/kernel/debug/tracing/set_ftrace_filterlockで終わるすべての関数をトレースします。# echo "*lock" > /sys/kernel/debug/tracing/set_ftrace_filterspin_で始まるすべての関数をトレースします。# echo "spin_*" > /sys/kernel/debug/tracing/set_ftrace_filter名前に
cpuのあるすべての関数をトレースします。# echo "cpu" > /sys/kernel/debug/tracing/set_ftrace_filter
第31章 アプリケーションのタイムスタンプ リンクのコピーリンクがクリップボードにコピーされました!
アプリケーションがタイムスタンプを頻繁に実行する場合には、CPU によるクロック読み取りが原因でパフォーマンスに影響があります。クロックの読み取りに使用するコストや時間がかさむと、アプリケーションのパフォーマンスに悪影響を及ぼす可能性があります。
読み出しメカニズムが備わっているハードウェアクロックを選択すると、デフォルトのクロックよりも速くなり、クロック読み取りのコストが軽減されます。
RHEL for Real Time では、POSIX クロックを clock_gettime() 関数とともに使用して、CPU のコストを可能な限り低く抑えて、クロックの読み取り値を生成し、パフォーマンスをさらに向上させることができます。
読み取りコストの高いハードウェアクロックを使用するシステムで、このような利点がより明確になります。
31.1. POSIX クロック リンクのコピーリンクがクリップボードにコピーされました!
POSIX は、タイムソースを実装して表すための標準です。システム内のその他のアプリケーションに影響を及ぼさずに、POSIX クロックをアプリケーションに割り当てることができます。これは、カーネルによって選択され、システム全体に実装されるハードウェアクロックとは対照的です。
指定の POSIX クロックを読み取るために使用される関数は <time.h> で定義される clock_gettime() です。clock_gettime() に相当するカーネルはシステムコールです。ユーザープロセスが clock_gettime() を呼び出すと、以下が行われます。
-
対応する C ライブラリー (
glibc) は、sys_clock_gettime()システムコールを呼び出します。 -
sys_clock_gettime()は、要求されたオペレーションを実行します。 -
sys_clock_gettime()は、結果をユーザープログラムプログラムに戻します。
ただし、このコンテキストはユーザーアプリケーションからカーネルへの切り替えには CPU コストがかかります。このコストは非常に低くなりますが、操作が数千回繰り返し行われると、累積されたコストはアプリケーション全体のパフォーマンスに影響を及ぼす可能性があります。カーネルへのコンテキストの切り替えを回避し、クロックの読み出しを速くするために、VDSO (Virtual Dynamic Shared Object) ライブラリー機能の形式で CLOCK_MONOTONIC_COARSE クロックおよび CLOCK_REALTIME_COARSE POSIX クロックのサポートが追加されました。
_COARSE クロックバリアントのいずれかを使用して clock_gettime() が実行する時間測定は、カーネルの介入を必要とせず、ユーザー空間全体で実行されます。これにより、パフォーマンスが大幅に向上します。_COARSE クロックの時間読み取りの分解能はミリ秒 (ms) です。つまり、1ms 未満の時間間隔は記録されません。POSIX クロックの _COARSE バリアントは、ミリ秒のクロック分解能に対応できるアプリケーションに適しています。
_COARSE 接頭辞の有無にかかわらず、POSIX クロックの読み出しコストと分解能を比較するには、RHEL for Real Time Reference ガイド を参照してください。
31.2. clock_gettime での _COARSE クロックバリアントの使用 リンクのコピーリンクがクリップボードにコピーされました!
コード出力例は、CLOCK_MONOTONIC_COARSE POSIX クロックを使用した clock_gettime 関数の使用を示しています。
#include <time.h>
main()
{
int rc;
long i;
struct timespec ts;
for(i=0; i<10000000; i++) {
rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
}
}
上記の例を改善するには、より多くの文字列を使用して clock_gettime() の戻りコードを確認したり、rc 変数の値を確認したり、ts 構造のコンテンツが信頼できるようにしたりします。
clock_gettime() の man ページでは、信頼できるアプリケーションを作成する方法が説明されています。
clock_gettime() 関数を使用するプログラムは、-lrt を gcc コマンドラインに追加して、-lrt ライブラリーにリンクする必要があります。
$ gcc clock_timing.c -o clock_timing -lrt
第32章 TCP_NODELAY を使用したネットワーク遅延の改善 リンクのコピーリンクがクリップボードにコピーされました!
デフォルトでは、TCP は Nagle のアルゴリズムを使用して、小さな送信パケットを集めて一度に送信します。これにより、レイテンシーの発生率が高くなる可能性があります。
前提条件
- 管理者権限がある。
32.1. TCP_NODELAY の使用による影響 リンクのコピーリンクがクリップボードにコピーされました!
送信されるすべてのパケットでレイテンシーを低く保つ必要のあるアプリケーションは、TCP_NODELAY オプションを有効化しているソケットで実行する必要があります。イベントが発生するとすぐに、カーネルにバッファー書き込みを送信します。
- 注記
-
TCP_NODELAYを効果的に使用するには、アプリケーションが小規模な論理的に関連するバッファー書き込みを行わないようにする必要があります。これを行わないと、このような小さい書き込みにより、TCPはこれらの複数のバッファーを個別のパケットとして送信するため、全体的なパフォーマンスが低下します。
論理に関連し、1 つのパケットとして送信する必要があるバッファーがアプリケーションに複数ある場合は、パフォーマンスの低下を回避するために、以下の回避策のいずれかを適用します。
-
メモリー内に連続したパケットを構築し、
TCP_NODELAYで設定したソケット上で論理パケットをTCPに送信する。 -
I/O ベクターを作成し、
TCP_NODELAYで設定したソケット上でwritevコマンドを使用してカーネルに渡す。 -
TCP_CORKオプションを使用する。TCP_CORKは、アプリケーションがコルクを削除するのを待ってからパケットを送信するようにTCPに指示します。このコマンドにより、受信するバッファーが既存のバッファーに追加されます。これにより、アプリケーションはカーネル領域にパケットを構築できます。これは、レイヤーの抽象化を提供する異なるライブラリーを使用する場合は必要です。
アプリケーションのさまざまなコンポーネントにより、論理パケットがカーネルに構築されている場合は、ソケットのコルクを解除する必要があります。これにより、TCP が、累積した論理パケットをすぐに送信できるようになります。
32.2. TCP_NODELAY の有効化 リンクのコピーリンクがクリップボードにコピーされました!
イベントが発生すると、TCP_NODELAY オプションは遅滞なくバッファー書き込みをカーネルに送信します。setsockopt() 関数を使用して TCP_NODELAY を有効にします。
手順
次の行を
TCPアプリケーションの.cファイルに追加します。int one = 1; setsockopt(descriptor, SOL_TCP, TCP_NODELAY, &one, sizeof(one));- ファイルを保存して、エディターを終了します。
パフォーマンスの低下を防ぐために、以下の回避策のいずれかを適用します。
-
メモリー内に連続したパケットを構築し、
TCP_NODELAYで設定したソケット上で論理パケットをTCPに送信する。 -
I/O ベクターを作成し、
TCP_NODELAYが設定されたソケット上でwritevを使用してカーネルに渡す。
-
メモリー内に連続したパケットを構築し、
32.3. TCP_CORK の有効化 リンクのコピーリンクがクリップボードにコピーされました!
TCP_CORK オプションは、ソケットが "uncorked" になるまで TCP がパケットを送信しないようにします。
手順
次の行を
TCPアプリケーションの.cファイルに追加します。int one = 1; setsockopt(descriptor, SOL_TCP, TCP_CORK, &one, sizeof(one));- ファイルを保存して、エディターを終了します。
アプリケーション内のさまざまなコンポーネントにより論理パケットがカーネルで構築されたら、
TCP_CORKを無効にします。int zero = 0; setsockopt(descriptor, SOL_TCP, TCP_CORK, &zero, sizeof(zero));TCPは、アプリケーションからのパケットを待たずに、直ちに累積した論理パケットを送信します。
第33章 ミューテックスの使用によるリソースの過剰使用の回避 リンクのコピーリンクがクリップボードにコピーされました!
相互排他 (ミューテックス) アルゴリズムは、共通リソースの過剰使用を防ぐために使用されます。
33.1. ミューテックスオプション リンクのコピーリンクがクリップボードにコピーされました!
相互除外 (ミューテックス) アルゴリズムは、プロセスが共通のリソースを同時に使用するのを防ぐために使用されます。高速ユーザー空間ミューテックス (futex) は、ミューテックスが別のスレッドによって保持されていない場合に、カーネル領域にコンテキストスイッチを要求せずにユーザー空間スレッドがミューテックスを要求することを可能にするツールです。
標準属性で pthread_mutex_t オブジェクトを初期化すると、プライベートで再帰的ではなく、堅牢ではない優先度継承対応ではないミューテックスが作成されます。このオブジェクトには、pthreads API および RHEL for Real Time カーネルで提供される利点はありません。
pthreads API および RHEL for Real Time カーネルの利点を活用するには、pthread_mutexattr_t オブジェクトを作成します。このオブジェクトは、futex に定義した属性を保存します。
futex および mutex という用語は、POSIX スレッド (pthread) のミューテックス構造を説明するために使用されます。
33.2. ミューテックス属性オブジェクトの作成 リンクのコピーリンクがクリップボードにコピーされました!
mutex に追加の機能を定義するには、pthread_mutexattr_t オブジェクトを作成します。このオブジェクトは、futex に定義した属性を保存します。これは基本的な安全手順で、常に実行する必要があります。
手順
以下のいずれかを使用して、ミューテックス属性オブジェクトを作成します。
-
pthread_mutex_t(my_mutex); -
pthread_mutexattr_t(&my_mutex_attr); -
pthread_mutexattr_init(&my_mutex_attr);
-
拡張ミューテックス属性の詳細は、拡張ミューテックス属性 を参照してください。
33.3. 標準属性のミューテックスの作成 リンクのコピーリンクがクリップボードにコピーされました!
標準属性で pthread_mutex_t オブジェクトを初期化すると、プライベートで再帰的ではなく、堅牢ではない優先度継承対応ではないミューテックスが作成されます。
手順
以下のいずれかを使用して、
pthreadsにミューテックスオブジェクトを作成します。-
pthread_mutex_t(my_mutex); pthread_mutex_init(&my_mutex, &my_mutex_attr);&my_mutex_attr;は、ミューテックス属性オブジェクトです。
-
33.4. 拡張ミューテックス属性 リンクのコピーリンクがクリップボードにコピーされました!
以下の拡張ミューテックス属性は、ミューテックス属性オブジェクトに格納できます。
ミューテックス属性
- 共有およびプライベートのミューテックス
共有ミューテックスはプロセス間で使用できますが、大きなオーバーヘッドが発生します。
pthread_mutexattr_setpshared(&my_mutex_attr, PTHREAD_PROCESS_SHARED);- リアルタイム優先度の継承
優先度の継承を使用して、優先度が反転する問題を回避できます。
pthread_mutexattr_setprotocol(&my_mutex_attr, PTHREAD_PRIO_INHERIT);- 強固なミューテックス
pthread が停止すると、pthread の下の強固なミューテックスが解放されます。ただし、これによりオーバーヘッドコストが高くなります。この文字列の _NP は、このオプションが非 POSIX であるか、移植性がないことを示します。
pthread_mutexattr_setrobust_np(&my_mutex_attr, PTHREAD_MUTEX_ROBUST_NP);- ミューテックスの初期化
共有ミューテックスはプロセス間で使用できますが、大きなオーバーヘッドが発生します。
pthread_mutex_init(&my_mutex_attr, &my_mutex);
33.5. ミューテックス属性オブジェクトの削除 リンクのコピーリンクがクリップボードにコピーされました!
ミューテックス属性オブジェクトを使用してミューテックスを作成した後に、属性オブジェクトを保持して同じタイプのミューテックスをさらに初期化することや、削除することができます。ミューテックスはいずれの場合も影響を受けません。
手順
pthread_mutexattr_destroy()関数を使用して、属性オブジェクトをクリーンアップします。pthread_mutexattr_destroy(&my_mutex_attr);mutex は通常の pthread_mutex として動作するようになり、通常どおりにロック、ロック解除、破棄できます。
第34章 アプリケーションのパフォーマンスの分析 リンクのコピーリンクがクリップボードにコピーされました!
perf はパフォーマンス分析ツールです。シンプルなコマンドラインインターフェイスを備え、Linux パフォーマンス測定における CPU ハードウェアの相違点を抽出します。Perf は、カーネルがエクスポートした perf_events インターフェイスに基づいています。
perf の利点の 1 つは、カーネルとアーキテクチャーの両方に依存しないことです。分析データは、特定のシステム設定なしに確認できます。
前提条件
-
perfパッケージがシステムにインストールされている。 - 管理者権限がある。
34.1. システム全体の統計の収集 リンクのコピーリンクがクリップボードにコピーされました!
perf record コマンドは、システム全体の統計を収集するために使用されます。すべてのプロセッサーで使用できます。
手順
システム全体のパフォーマンス統計を収集します。
# perf record -a ^C[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.725 MB perf.data (~31655 samples) ]この例では、オプション
-aによりすべての CPU が表示され、数秒後にプロセスが終了しています。結果には、収集したデータは 0.725 MB で、新しく作成したperf.dataファイルに保存されたことが示されています。
検証
結果のファイルが作成されたことを確認します。
# ls perf.data
34.2. パフォーマンス分析結果のアーカイブ リンクのコピーリンクがクリップボードにコピーされました!
perf archive を使用すると、他のシステムでの perf の結果を分析できます。以下の場合は必要ありません。
-
バイナリーやライブラリーなどの動的共有オブジェクト (DSO) は、
~/.debug/キャッシュなどの分析システムにすでに存在している。 - 両方のシステムでバイナリーのセットが同じである。
手順
perfコマンドによる結果のアーカイブを作成します。# perf archiveアーカイブから tarball を作成します。
# tar cvf perf.data.tar.bz2 -C ~/.debug
34.3. パフォーマンス解析結果の分析 リンクのコピーリンクがクリップボードにコピーされました!
perf record 機能によるデータを、perf report コマンドを使用して直接調査できるようになりました。
手順
perf.dataファイルまたはアーカイブした tarball から直接結果を分析します。# perf reportレポートの出力は、アプリケーションの最大 CPU 使用率順に並べ替えられます。これは、サンプルがカーネルまたはプロセスのユーザー空間で発生したかどうかを示します。
レポートには、サンプルを取得したモジュールの情報が表示されます。
-
カーネルモジュールで実行されていないカーネルサンプルには、
[kernel.kallsyms]という表記が使用されます。 -
カーネルモジュールで発生したカーネルサンプルには、
[module]、[ext4]のマークが付けられます。 ユーザー空間のプロセスでは、プロセスにリンクされた共有ライブラリーが結果に表示される可能性があります。
レポートは、プロセスがカーネルまたはユーザースペースでも発生するかどうかを示します。
-
結果の
[.]は、ユーザー空間を示しています。 -
結果の
[k]は、カーネル領域を示しています。
経験豊富な
perf開発者に適したデータなど、詳細を確認することができます。-
カーネルモジュールで実行されていないカーネルサンプルには、
34.4. 定義済みイベントのリスト表示 リンクのコピーリンクがクリップボードにコピーされました!
ハードウェアトレースポイントアクティビティーを取得するために利用可能なオプションは複数あります。
手順
定義済みのハードウェアイベントおよびソフトウェアイベントのリストを表示します。
# perf list List of pre-defined events (to be used in -e): cpu-cycles OR cycles [Hardware event] stalled-cycles-frontend OR idle-cycles-frontend [Hardware event] stalled-cycles-backend OR idle-cycles-backend [Hardware event] instructions [Hardware event] cache-references [Hardware event] cache-misses [Hardware event] branch-instructions OR branches [Hardware event] branch-misses [Hardware event] bus-cycles [Hardware event] cpu-clock [Software event] task-clock [Software event] page-faults OR faults [Software event] minor-faults [Software event] major-faults [Software event] context-switches OR cs [Software event] cpu-migrations OR migrations [Software event] alignment-faults [Software event] emulation-faults [Software event] ...[output truncated]...
34.5. 指定したイベント統計の取得 リンクのコピーリンクがクリップボードにコピーされました!
perf stat を使用すると、特定のイベントを表示できます。
手順
perf stat機能を使用して、コンテキストスイッチの数を表示します。# perf stat -e context-switches -a sleep 5 Performance counter stats for 'sleep 5': 15,619 context-switches 5.002060064 seconds time elapsed結果には、5 秒間に 15619 のコンテキストスイッチが発生したことが示されています。
スクリプトを実行してファイルシステムのアクティビティーを表示します。以下はスクリプトの例になります。
# for i in {1..100}; do touch /tmp/$i; sleep 1; done別の端末で、
perf statコマンドを実行します。# perf stat -e ext4:ext4_request_inode -a sleep 5 Performance counter stats for 'sleep 5': 5 ext4:ext4_request_inode 5.002253620 seconds time elapsed結果には、スクリプトが 5 秒間に 5 つのファイルの作成を要求したことが示され、
inode要求が 5 つあることが分かります。
第35章 stress-ng を使用したリアルタイムのシステムのストレステスト リンクのコピーリンクがクリップボードにコピーされました!
stress-ng ツールは、望ましくない条件下で良好なレベルの効率を維持するシステムの機能を測定します。stress-ng ツールは、すべてのカーネルインターフェイスに負荷およびストレスをかけるためのストレスワークロードジェネレーターです。これには、ストレッサーと呼ばれるさまざまなストレスメカニズムが含まれています。ストレステストにより、マシンに負荷がかかり、システムが過負荷になっているときに発生するサーマルオーバーランやオペレーティングシステムのバグなどのハードウェアの問題が発生します。
270 以上の異なるテストがあります。これらには、浮動小数点、整数、ビット操作、制御フロー、および仮想メモリーテストを実行する CPU 固有のテストが含まれます。
一部のテストは、設計が不十分なハードウェア上のシステムのサーマルゾーントリップポイントに影響を与える可能性があるため、stress-ng ツールの使用には注意が必要です。これは、システムパフォーマンスに影響を与え、過度のシステムスラッシングを引き起こし、停止が困難になる可能性があります。
35.1. CPU 浮動小数点ユニットとプロセッサーデータキャッシュのテスト リンクのコピーリンクがクリップボードにコピーされました!
浮動小数点ユニットは、浮動小数点算術演算を実行するプロセッサーの機能部分です。浮動小数点ユニットは算術演算を処理し、浮動小数点数または小数の計算を簡単にします。
--matrix-method オプションを使用すると、CPU 浮動小数点演算とプロセッサーデータキャッシュのストレステストを行うことができます。
前提条件
- システムの root 権限がある。
手順
1 つの CPU で浮動小数点を 60 秒間テストするには、
--matrixオプションを使用します。# stress-ng --matrix 1 -t 1m複数のストレッサーを複数の CPU で 60 秒間実行するには、
--timesまたは-tオプションを使用します。# stress-ng --matrix 0 -t 1m stress-ng --matrix 0 -t 1m --times stress-ng: info: [16783] dispatching hogs: 4 matrix stress-ng: info: [16783] successful run completed in 60.00s (1 min, 0.00 secs) stress-ng: info: [16783] for a 60.00s run time: stress-ng: info: [16783] 240.00s available CPU time stress-ng: info: [16783] 205.21s user time ( 85.50%) stress-ng: info: [16783] 0.32s system time ( 0.13%) stress-ng: info: [16783] 205.53s total time ( 85.64%) stress-ng: info: [16783] load average: 3.20 1.25 1.40ストレッサーが 0 の特別なモードでは、実行可能な CPU をクエリするため、CPU 番号を指定する必要はなくなります。
必要な合計 CPU 時間は 4 x 60 秒 (240 秒) で、そのうち 0.13% がカーネル、85.50% がユーザー時間、
stress-ngがすべての CPU の 85.64% を実行します。POSIX メッセージキューを使用してプロセス間でメッセージが渡されることをテストするには、
-mqオプションを使用します。# stress-ng --mq 0 -t 30s --times --perfmqオプションは、POSIX メッセージキューを使用してコンテキストスイッチを強制する特定の数のプロセスを設定します。このストレステストは、データキャッシュミスを少なくすることを目的としています。
35.2. 複数のストレスメカニズムを使用した CPU のテスト リンクのコピーリンクがクリップボードにコピーされました!
stress-ng ツールは、複数のストレステストを実行します。デフォルトモードでは、指定されたストレッサーメカニズムを並行して実行します。
前提条件
- システムの root 権限がある。
手順
次のように、CPU ストレッサーの複数のインスタンスを実行します。
# stress-ng --cpu 2 --matrix 1 --mq 3 -t 5mこの例では、
stress-ngは CPU ストレッサーの 2 つのインスタンス、マトリックスストレッサーの 1 つのインスタンス、およびメッセージキューストレッサーの 3 つのインスタンスを実行し、5 分間テストを行います。すべてのストレステストを並行して実行するには、the
-allオプションを使用します。# stress-ng --all 2この例では、
stress-ngはすべてのストレステストの 2 つのインスタンスを並行して実行します。異なるストレッサーをそれぞれ特定の順序で実行するには、
--seqオプションを使用します。# stress-ng --seq 4 -t 20この例では、
stress-ngはすべてのストレッサーを 1 つずつ 20 分間実行し、各ストレッサーのインスタンスの数はオンライン CPU の数と一致します。テスト実行から特定のストレッサーを除外するには、
-xオプションを使用します。# stress-ng --seq 1 -x numa,matrix,hddこの例では、
stress-ngは、numa、hdd、およびkeyストレッサーメカニズムを除いて、すべてのストレッサーを実行します。
35.3. CPU 発熱量の測定 リンクのコピーリンクがクリップボードにコピーされました!
CPU の発熱量を測定するために、指定されたストレッサーが短時間高温を発生させ、最大発熱量でのシステムの冷却の信頼性と安定性をテストします。--matrix-size オプションを使用すると、短時間で CPU 温度を摂氏単位で測定できます。
前提条件
- システムの root 権限がある。
手順
指定された期間、高温で CPU の動作をテストするには、次のコマンドを実行します。
# stress-ng --matrix 0 --matrix-size 64 --tz -t 60 stress-ng: info: [18351] dispatching hogs: 4 matrix stress-ng: info: [18351] successful run completed in 60.00s (1 min, 0.00 secs) stress-ng: info: [18351] matrix: stress-ng: info: [18351] x86_pkg_temp 88.00 °C stress-ng: info: [18351] acpitz 87.00 °Cこの例では、
stress-ngは、60 秒間摂氏 88 度になるようにプロセッサーパッケージのサーマルゾーンを設定します。オプション: 実行の最後にレポートを出力するには、
--tzオプションを使用します。# stress-ng --cpu 0 --tz -t 60 stress-ng: info: [18065] dispatching hogs: 4 cpu stress-ng: info: [18065] successful run completed in 60.07s (1 min, 0.07 secs) stress-ng: info: [18065] cpu: stress-ng: info: [18065] x86_pkg_temp 88.75 °C stress-ng: info: [18065] acpitz 88.38 °C
35.4. bogo 操作によるテスト結果の測定 リンクのコピーリンクがクリップボードにコピーされました!
stress-ng ツールは、1 秒あたりの bogo 操作を測定することにより、ストレステストのスループットを測定できます。bogo 操作のサイズは、実行されているストレッサーによって異なります。テスト結果は正確ではありませんが、概略のパフォーマンスを提供します。
この測定値を正確なベンチマークメトリックとして使用しないでください。これらの見積もりは、stress-ng のビルドに使用されるさまざまなカーネルバージョンまたはさまざまなコンパイラーバージョンでのシステムパフォーマンスの変化を理解するのに役立ちます。--metrics-brief オプションを使用して、マシンで利用可能な bogo 操作の合計とマトリックスストレッサーのパフォーマンスを表示します。
前提条件
- システムの root 権限がある。
手順
bogo 操作でテスト結果を測定するには、
--metrics-briefオプションを使用します。# stress-ng --matrix 0 -t 60s --metrics-brief stress-ng: info: [17579] dispatching hogs: 4 matrix stress-ng: info: [17579] successful run completed in 60.01s (1 min, 0.01 secs) stress-ng: info: [17579] stressor bogo ops real time usr time sys time bogo ops/s bogo ops/s stress-ng: info: [17579] (secs) (secs) (secs) (real time) (usr+sys time) stress-ng: info: [17579] matrix 349322 60.00 203.23 0.19 5822.03 1717.25--metrics-briefオプションは、テスト結果とmatrixストレッサーによって 60 秒間実行されたリアルタイムの bogo 操作の合計を表示します。
35.5. 仮想メモリーの逼迫の生成 リンクのコピーリンクがクリップボードにコピーされました!
メモリーが不足すると、カーネルはページをスワップに書き込み始めます。--page-in オプションを使用して、非常駐ページを強制的に仮想メモリーにスワップバックすることにより、仮想メモリーに負荷をかけることができます。これにより、仮想マシンが高負荷で実行されます。--page-in オプションを使用すると、bigheap、mmap、および仮想マシン (vm) ストレッサーに対してこのモードを有効にできます。--page-in オプションは、コアにない割り当てられたページをタッチして、強制的にページインさせます。
前提条件
- システムの root 権限がある。
手順
仮想メモリーのストレステストを行うには、
--page-inオプションを使用します。# stress-ng --vm 2 --vm-bytes 2G --mmap 2 --mmap-bytes 2G --page-inこの例では、
stress-ngは、4 GB のメモリー (割り当てられたバッファーサイズ (--page-inが有効な 2 x 2 GB のvmストレッサーおよび 2 x 2 GB のmmapストレッサー) よりも小さい) を備えたシステムでメモリー逼迫のテストを行います。
35.6. デバイスでの大きな割り込み負荷のテスト リンクのコピーリンクがクリップボードにコピーされました!
タイマーを高頻度で実行すると、大きな割り込み負荷が発生する可能性があります。適切に選択されたタイマーストレッサーを持つ -timer ストレッサーは、1 秒あたりに多くの割り込みを強制する可能性があります。
前提条件
- システムの root 権限がある。
手順
割り込み負荷を生成するには、
--timerオプションを使用します。# stress-ng --timer 32 --timer-freq 1000000この例では、
stress-ngは 1 MHz で 32 個のインスタンスをテストします。
35.7. プログラムでの深刻なページ障害の生成 リンクのコピーリンクがクリップボードにコピーされました!
stress-ng を使用すると、メモリーに読み込まれていないページで深刻なページ障害を生成することにより、ページ障害率をテストおよび分析できます。新しいカーネルバージョンでは、userfaultfd メカニズムは、プロセスの仮想メモリーレイアウトのページ障害について、障害検出スレッドに通知します。
前提条件
- システムの root 権限がある。
手順
初期のカーネルバージョンで深刻なページ障害を生成するには、以下のコマンドを使用します。
# stress-ng --fault 0 --perf -t 1m新しいカーネルバージョンで深刻なページ障害を生成するには、以下のコマンドを使用します。
# stress-ng --userfaultfd 0 --perf -t 1m
35.8. CPU ストレステストメカニズムの表示 リンクのコピーリンクがクリップボードにコピーされました!
CPU ストレステストには、CPU を使用するメソッドが含まれています。which オプションを使用して出力を印刷し、すべてのメソッドを表示できます。
テスト方法を指定しない場合、デフォルトでは、ストレッサーはすべてのストレッサーをラウンドロビン方式でチェックして、各ストレッサーで CPU をテストします。
前提条件
- システムの root 権限がある。
手順
利用可能なすべてのストレッサーメカニズムを印刷するには、
whichオプションを使用します。# stress-ng --cpu-method which cpu-method must be one of: all ackermann bitops callfunc cdouble cfloat clongdouble correlate crc16 decimal32 decimal64 decimal128 dither djb2a double euler explog fft fibonacci float fnv1a gamma gcd gray hamming hanoi hyperbolic idct int128 int64 int32--cpu-methodオプションを使用して、特定の CPU ストレス方式を指定します。# stress-ng --cpu 1 --cpu-method fft -t 1m
35.9. 検証モードの使用 リンクのコピーリンクがクリップボードにコピーされました!
verify モードは、テストがアクティブなときに結果を検証します。テスト実行からメモリーの内容の健全性チェックを行い、予期しない障害があれば報告します。
すべてのストレッサーには verify モードがなく、このモードを有効にすると、このモードで実行される追加の検証ステップのために、bogo 操作の統計が減少します。
前提条件
- システムの root 権限がある。
手順
ストレステストの結果を検証するには、
--verifyオプションを使用します。# stress-ng --vm 1 --vm-bytes 2G --verify -vこの例では、
stress-ngは、--verifyモードが設定されたvmストレッサーを使用して、仮想的にマッピングされたメモリーでの完全なメモリーチェックの出力を表示します。メモリーの読み取りと書き込み結果の健全性をチェックします。
第36章 コンテナーの作成と実行 リンクのコピーリンクがクリップボードにコピーされました!
このセクションでは、リアルタイムカーネルを使用してコンテナーを作成および実行する方法を説明します。
前提条件
-
podmanおよびその他のコンテナー関連のユーティリティーをインストールしている。 - RHEL での Linux コンテナーの管理に精通している。
-
kernel-rtパッケージおよびリアルタイム関連のパッケージをインストールしている。
36.1. コンテナーの作成 リンクのコピーリンクがクリップボードにコピーされました!
以下のオプションはすべて、リアルタイムカーネルとメインの RHEL カーネルの両方で使用できます。kernel-rt パッケージにより潜在的な決定論が改善され、通常のトラブルシューティングが可能となります。
前提条件
- 管理者権限がある。
手順
以下の手順では、リアルタイムカーネルに関して、Linux コンテナーを設定する方法を説明します。
コンテナーに使用するディレクトリーを作成します。以下に例を示します。
# mkdir cyclictest対象のディレクトリーに移動します。
# cd cyclictestコンテナーレジストリーサービスを提供するホストにログインします。
# podman login registry.redhat.io Username: my_customer_portal_login Password: *** Login Succeeded!Containerfileを作成します。# vim Containerfileカスタム Containerfile からビルドする場合は、Containerfile を変更してビルドします。以下は cyclisttest の例です。独自のイメージを作成していない場合は、realtime-tests-container イメージをプルして cyclictest を実行することもできます。
# podman build -t cyclictest .
36.2. コンテナーの実行 リンクのコピーリンクがクリップボードにコピーされました!
Containerfile を使用して構築されたコンテナーを実行できます。
手順
podman runコマンドを使用して、コンテナーを実行します。# podman run --device=/dev/cpu_dma_latency --cap-add ipc_lock --cap-add sys_nice --cap-add sys_rawio --rm -ti cyclictest /dev/cpu_dma_latency set to 0us policy: fifo: loadavg: 0.08 0.10 0.09 2/947 15 T: 0 ( 8) P:95 I:1000 C: 3209 Min: 1 Act: 1 Avg: 1 Max: 14 T: 1 ( 9) P:95 I:1500 C: 2137 Min: 1 Act: 2 Avg: 1 Max: 23 T: 2 (10) P:95 I:2000 C: 1601 Min: 1 Act: 2 Avg: 2 Max: 7 T: 3 (11) P:95 I:2500 C: 1280 Min: 1 Act: 2 Avg: 2 Max: 72 T: 4 (12) P:95 I:3000 C: 1066 Min: 1 Act: 1 Avg: 1 Max: 7 T: 5 (13) P:95 I:3500 C: 913 Min: 1 Act: 2 Avg: 2 Max: 87 T: 6 (14) P:95 I:4000 C: 798 Min: 1 Act: 1 Avg: 2 Max: 7 T: 7 (15) P:95 I:4500 C: 709 Min: 1 Act: 2 Avg: 2 Max: 29
この例は、必須のリアルタイム固有のオプションを指定した podman run コマンドを示しています。以下に例を示します。
-
先入れ先出し (FIFO) スケジューラーポリシーは、
--cap-add=sys_niceオプションを介してコンテナー内で実行されているワークロードで使用できます。このオプションでは、スレッドの CPU アフィニティーを設定することもできます。これは、リアルタイムのワークロードをチューニングする際のもう 1 つの重要な設定ディメンジョンです。 --device=/dev/cpu_dma_latencyオプションは、コンテナー内でホストデバイスを利用できるようにします (その後、CPU アイドル時間管理を設定するために cyclictest の負荷によって使用されます)。指定したデバイスを利用できない場合は、以下のようなエラーメッセージが表示されます。WARN: stat /dev/cpu_dma_latency failed: No such file or directoryこのようなエラーメッセージが表示された場合は、podman-run(1) の man ページを参照してください。コンテナーで特定のワークロードを実行するには、別の
podman-runオプションが役に立ちます。場合によっては、
--device=/dev/cpuオプションを追加してそのディレクトリー階層を追加して、/dev/cpu/*/msrなどの CPU ごとのデバイスファイルをマッピングする必要があります。
第37章 プロセスの優先度の表示 リンクのコピーリンクがクリップボードにコピーされました!
sched_getattr 属性を使用して、プロセスの優先度に関する情報およびプロセスのスケジューリングポリシーに関する情報を表示できます。
前提条件
- 管理者権限がある。
37.1. chrt ユーティリティー リンクのコピーリンクがクリップボードにコピーされました!
chrt ユーティリティーは、スケジューラーポリシーおよび優先度を確認して調整します。希望するプロパティーで新しいプロセスを開始するか、実行中のプロセスのプロパティーを変更できます。
37.2. chrt ユーティリティーを使用したプロセス優先度の表示 リンクのコピーリンクがクリップボードにコピーされました!
指定したプロセスの現在のスケジューリングポリシーおよびスケジューリング優先度を表示できます。
手順
実行中のプロセスを指定して、
-pオプションを指定してchrtユーティリティーを実行します。# chrt -p 468 pid 468's current scheduling policy: SCHED_FIFO pid 468's current scheduling priority: 85 # chrt -p 476 pid 476's current scheduling policy: SCHED_OTHER pid 476's current scheduling priority: 0
37.3. sched_getscheduler() を使用してプロセスの優先度を表示する リンクのコピーリンクがクリップボードにコピーされました!
リアルタイムプロセスでは、一連の関数を使用してポリシーと優先順位を制御します。sched_getscheduler() 関数を使用して、指定したプロセスのスケジューラーポリシーを表示できます。
手順
get_sched.cソースファイルを作成し、テキストエディターで開きます。$ {EDITOR} get_sched.cファイルに以下の行を追加します。
#include <sched.h> #include <unistd.h> #include <stdio.h> int main() { int policy; pid_t pid = getpid(); policy = sched_getscheduler(pid); printf("Policy for pid %ld is %i.\n", (long) pid, policy); return 0; }policy変数は、指定されたプロセスのスケジューラーポリシーを保持します。プログラムをコンパイルします。
$ gcc get_sched.c -o get_schedさまざまなポリシーでプログラムを実行します。
$ chrt -o 0 ./get_sched Policy for pid 27240 is 0. $ chrt -r 10 ./get_sched Policy for pid 27243 is 2. $ chrt -f 10 ./get_sched Policy for pid 27245 is 1.
37.4. スケジューラーポリシーの有効範囲の表示 リンクのコピーリンクがクリップボードにコピーされました!
sched_get_priority_min() 関数および sched_get_priority_max() 関数を使用して、特定のスケジューラーポリシーの有効な優先順位の範囲を確認できます。
手順
sched_get.cソースファイルを作成し、テキストエディターで開きます。$ {EDITOR} sched_get.cファイルに以下のコマンドを入力します。
#include <stdio.h> #include <unistd.h> #include <sched.h> int main() { printf("Valid priority range for SCHED_OTHER: %d - %d\n", sched_get_priority_min(SCHED_OTHER), sched_get_priority_max(SCHED_OTHER)); printf("Valid priority range for SCHED_FIFO: %d - %d\n", sched_get_priority_min(SCHED_FIFO), sched_get_priority_max(SCHED_FIFO)); printf("Valid priority range for SCHED_RR: %d - %d\n", sched_get_priority_min(SCHED_RR), sched_get_priority_max(SCHED_RR)); return 0; }注記指定されたスケジューラーポリシーがシステムに認識されていない場合、関数は
-1を返し、errnoはEINVALに設定されます。注記SCHED_FIFOおよびSCHED_RRはどちらも1~99の範囲内の任意の数値にすることができます。POSIX がこの範囲に従う保証はありませんが、移植可能なプログラムはこれらの関数を使用する必要があります。- ファイルを保存して、エディターを終了します。
プログラムをコンパイルします。
$ gcc sched_get.c -o msched_get
これで sched_get プログラムの準備が整い、保存先のディレクトリーから実行できるようになりました。
37.5. プロセスのタイムスライスの表示 リンクのコピーリンクがクリップボードにコピーされました!
SCHED_RR (ラウンドロビン) ポリシーは、SCHED_FIFO (先入れ先出し) ポリシーとは少し異なります。SCHED_RR は、ラウンドロビンローテーションで同じ優先度を持つ並行プロセスを割り当てます。このようにして、各プロセスにタイムスライスが割り当てられます。sched_rr_get_interval() 関数は、各プロセスに割り当てられたタイムスライスを報告します。
POSIX では、この関数が SCHED_RR スケジューラーポリシーで実行するように設定されたプロセスでのみ機能する 必要があります が、sched_rr_get_interval() 関数は Linux 上の任意のプロセスのタイムスライス長を取得できます。
タイムスライス情報は timespec として返されます。これは、1970 年 1 月 1 日のグリニッジ標準時 00:00:00 の基準時間からの秒数およびナノ秒数です。
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
}
手順
sched_timeslice.cソースファイルを作成し、テキストエディターで開きます。$ {EDITOR} sched_timeslice.c次の行を
sched_timeslice.cファイルに追加します。#include <stdio.h> #include <sched.h> int main() { struct timespec ts; int ret; /* real apps must check return values */ ret = sched_rr_get_interval(0, &ts); printf("Timeslice: %lu.%lu\n", ts.tv_sec, ts.tv_nsec); return 0; }- ファイルを保存して、エディターを終了します。
プログラムをコンパイルします。
$ gcc sched_timeslice.c -o sched_timesliceさまざまなポリシーと優先順位でプログラムを実行します。
$ chrt -o 0 ./sched_timeslice Timeslice: 0.38994072 $ chrt -r 10 ./sched_timeslice Timeslice: 0.99984800 $ chrt -f 10 ./sched_timeslice Timeslice: 0.0
37.6. プロセスのスケジューリングポリシーおよび関連する属性の表示 リンクのコピーリンクがクリップボードにコピーされました!
sched_getattr() 関数は、PID で識別される、指定されたプロセスに現在適用されているスケジューリングポリシーを照会します。PID がゼロに等しい場合は、呼び出しプロセスのポリシーが取得されます。
size 引数は、ユーザースペースに認識されている sched_attr 構造体のサイズを反映する必要があります。カーネルは、sched_attr::size をその sched_attr 構造体のサイズに入力します。
入力構造体が小さい場合、カーネルは指定されたスペースの外側の値を返します。その結果、システムコールが E2BIG エラーで失敗します。他の sched_attr フィールドは、The sched_attr structure で説明されているように入力されます。
手順
sched_timeslice.cソースファイルを作成し、テキストエディターで開きます。$ {EDITOR} sched_timeslice.c次の行を
sched_timeslice.cファイルに追加します。#define _GNU_SOURCE #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <linux/unistd.h> #include <linux/kernel.h> #include <linux/types.h> #include <sys/syscall.h> #include <pthread.h> #define gettid() syscall(__NR_gettid) #define SCHED_DEADLINE 6 /* XXX use the proper syscall numbers */ #ifdef __x86_64__ #define __NR_sched_setattr 314 #define __NR_sched_getattr 315 #endif struct sched_attr { __u32 size; __u32 sched_policy; __u64 sched_flags; /* SCHED_NORMAL, SCHED_BATCH */ __s32 sched_nice; /* SCHED_FIFO, SCHED_RR */ __u32 sched_priority; /* SCHED_DEADLINE (nsec) */ __u64 sched_runtime; __u64 sched_deadline; __u64 sched_period; }; int sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags) { return syscall(__NR_sched_getattr, pid, attr, size, flags); } int main (int argc, char **argv) { struct sched_attr attr; unsigned int flags = 0; int ret; ret = sched_getattr(0, &attr, sizeof(attr), flags); if (ret < 0) { perror("sched_getattr"); exit(-1); } printf("main thread pid=%ld\n", gettid()); printf("main thread policy=%ld\n", attr.sched_policy); printf("main thread nice=%ld\n", attr.sched_nice); printf("main thread priority=%ld\n", attr.sched_priority); printf("main thread runtime=%ld\n", attr.sched_runtime); printf("main thread deadline=%ld\n", attr.sched_deadline); printf("main thread period=%ld\n", attr.sched_period); return 0; }sched_timeslice.cファイルをコンパイルします。$ gcc sched_timeslice.c -o sched_timeslicesched_timesliceプログラムの出力を確認します。$ ./sched_timeslice main thread pid=321716 main thread policy=6 main thread nice=0 main thread priority=0 main thread runtime=1000000 main thread deadline=9000000 main thread period=10000000
37.7. sched_attr 構造体 リンクのコピーリンクがクリップボードにコピーされました!
sched_attr 構造体には、指定されたスレッドのスケジューリングポリシーとそれに関連する属性が含まれるか、それらを定義します。sched_attr 構造体の形式は次のとおりです。
struct sched_attr {
u32 size;
u32 sched_policy;
u64 sched_flags;
s32 sched_nice;
u32 sched_priority;
/* SCHED_DEADLINE fields */
u64 sched_runtime;
u64 sched_deadline;
u64 sched_period;
};
sched_attr データ構造体
- size
バイト単位のスレッドサイズ。構造体のサイズがカーネル構造体よりも小さい場合、追加のフィールドは
0と見なされます。サイズがカーネル構造体よりも大きい場合、カーネルはすべての追加フィールドを0として検証します。注記sched_attr構造体がカーネル構造体よりも大きく、カーネル構造のサイズを含むようにサイズを更新すると、sched_setattr()関数はE2BIGエラーで失敗します。- sched_policy
- スケジューリングポリシー
- sched_flags
プロセスが
fork()関数を使用してフォークする場合のスケジューリング動作を制御するのに役立ちます。呼び出し元のプロセスは親プロセスと呼ばれ、新しいプロセスは子プロセスと呼ばれます。有効な値は以下のとおりです。-
0: 子プロセスは親プロセスからスケジューリングポリシーを継承します。 -
SCHED_FLAG_RESET_ON_FORK: fork(): 子プロセスは親プロセスからスケジューリングポリシーを継承しません。代わりに、デフォルトのスケジューリングポリシー(struct sched_attr){ .sched_policy = SCHED_OTHER, }に設定されます。
-
- sched_nice
-
SCHED_OTHERまたはSCHED_BATCHスケジューリングポリシーを使用する際に設定するnice値を指定します。nice値は、-20(優先度が高い) から+19(優先度が低い) の範囲の数値です。 - sched_priority
-
SCHED_FIFOまたはSCHED_RRをスケジュールするときに設定する静的優先度を指定します。その他のポリシーの場合は、優先度を0として指定します。
SCHED_DEADLINE フィールドは、期限スケジューリングの場合にのみ指定する必要があります。
-
sched_runtime: 期限スケジューリングの
runtimeパラメーターを指定します。値はナノ秒で表されます。 -
sched_deadline: 期限スケジューリングの
deadlineパラメーターを指定します。値はナノ秒で表されます。 -
sched_period: 期限スケジューリングの
periodパラメーターを指定します。値はナノ秒で表されます。
第38章 プリエンプション状態の表示 リンクのコピーリンクがクリップボードにコピーされました!
CPU を使用するプロセスは、自発的または非自発的に、使用している CPU を放棄する可能性があります。
38.1. プリエンプション リンクのコピーリンクがクリップボードにコピーされました!
プロセスは、完了したか、イベント (ディスクからのデータ、キー操作、またはネットワークパケットなど) を待機しているため、CPU に自主的に優先度を譲ることがあります。
また、プロセスは不本意に CPU に優先度を譲ることもあります。これはプリエンプションと呼ばれ、優先度の高いプロセスが CPU を使用する場合に発生します。
プリエンプションはシステムパフォーマンスに重大な影響を及ぼす可能性があります。また、継続的なプリエンプションにより、スロットリングと呼ばれる状態が発生する可能性があります。この問題は、プロセスが常にプリエンプションされ、プロセスの実行が完了しない場合に発生します。
タスクの優先度を変更すると、自発的なプリエンプションを減らすことができます。
38.2. プロセスのプリエンプション状態の確認 リンクのコピーリンクがクリップボードにコピーされました!
指定されたプロセスの自発的および非自発的なプリエンプションステータスを確認できます。ステータスは /proc/PID/status に保存されます。
前提条件
- 管理者権限がある。
手順
/proc/PID/statusの内容を表示します。ここで、PIDはプロセスの ID です。以下に、PID 1000 のプロセスのプリエンプションステータスを示します。# grep voluntary /proc/1000/status voluntary_ctxt_switches: 194529 nonvoluntary_ctxt_switches: 195338
第39章 chrt ユーティリティーを使用したプロセス優先度の設定 リンクのコピーリンクがクリップボードにコピーされました!
chrt ユーティリティーを使用してプロセスの優先度を設定できます。
前提条件
- 管理者権限がある。
39.1. chrt ユーティリティーを使用したプロセス優先度の設定 リンクのコピーリンクがクリップボードにコピーされました!
chrt ユーティリティーは、スケジューラーポリシーおよび優先度を確認して調整します。希望するプロパティーで新しいプロセスを開始するか、実行中のプロセスのプロパティーを変更できます。
手順
プロセスのスケジューリングポリシーを設定するには、適切なコマンドオプションおよびパラメーターを指定して
chrtコマンドを実行します。次の例では、コマンドの影響を受けるプロセス ID は1000であり、優先度 (-p) は50です。# chrt -f -p 50 1000指定されたスケジューリングポリシーと優先度でアプリケーションを起動するには、アプリケーションの名前と、必要に応じてアプリケーションへのパスを属性と共に追加します。
# chrt -r -p 50 /bin/my-appchrtユーティリティーオプションの詳細は、chrt ユーティリティーのオプション を参照してください。
39.2. chrt ユーティリティーのオプション リンクのコピーリンクがクリップボードにコピーされました!
chrt ユーティリティーのオプションには、コマンドオプションと、コマンドのプロセスと優先度を指定するパラメーターが含まれます。
ポリシーオプション
- -f
-
スケジューラーポリシーを
SCHED_FIFOに設定します。 - -o
-
スケジューラーポリシーを
SCHED_OTHERに設定します。 - -r
-
スケジューラーポリシーを
SCHED_RR(ラウンドロビン) に設定します。 - -d
-
スケジューラーポリシーを
SCHED_DEADLINEに設定します。 - -p n
プロセスの優先度を n に設定します。
プロセスを SCHED_DEADLINE に設定するときは、
runtime、deadline、およびperiodパラメーターを指定する必要があります。以下に例を示します。
# chrt -d --sched-runtime 5000000 --sched-deadline 10000000 --sched-period 16666666 0 video_processing_tool以下は、
-
--sched-runtime 5000000は、ナノ秒単位の実行時間です。 -
--sched-deadline 10000000は、ナノ秒単位の相対的な期限です。 -
--sched-period 16666666は、ナノ秒単位の期間です。 -
0は、chrtコマンドに必要な未使用の優先度のプレースホルダーです。
-
第40章 ライブラリー呼び出しを使用したプロセスの優先度の設定 リンクのコピーリンクがクリップボードにコピーされました!
chrt ユーティリティーを使用してプロセスの優先度を設定できます。
前提条件
- 管理者権限がある。
40.1. 優先度を設定するためのライブラリー呼び出し リンクのコピーリンクがクリップボードにコピーされました!
リアルタイムプロセスは、異なる一連のライブラリー呼び出しを使用して、ポリシーおよび優先度を制御します。次のライブラリー呼び出しは、非リアルタイムプロセスの優先度を設定するのに使用されます。
-
nice -
setpriority
これらの関数は、非リアルタイムプロセスの nice 値を調整します。nice 値は、プロセッサー上で実行可能な非リアルタイムプロセスのリストにどのように優先度を設定するかをスケジューラーに提案します。リストの上位にあるプロセスは、リスト上で下位のプロセスより先に実行されます。
関数には、sched.h ヘッダーファイルをインクルードする必要があります。関数からの戻りコードを必ず確認するようにしてください。
40.2. ライブラリー呼び出しを使用したプロセス優先度の設定 リンクのコピーリンクがクリップボードにコピーされました!
スケジューラーポリシーおよびその他のパラメーターは、sched_setscheduler() 関数を使用して設定できます。現在、リアルタイムポリシーには、sched_priority というパラメーターがあります。このパラメーターは、プロセスの優先度を調整するために使用されます。
sched_setscheduler() 関数には、sched_setscheduler(pid_t pid, int policy, const struct sched_param *sp); 形式の 3 つのパラメーターが必要です。
sched_setscheduler(2) の man ページには、エラーコードを含む sched_setscheduler() の可能な戻り値がすべて記載されています。
プロセス ID がゼロの場合、sched_setscheduler() 関数は呼び出し元のプロセスに作用します。
次のコードの抜粋は、現在のプロセスのスケジューラーポリシーを SCHED_FIFO スケジューラーポリシーに設定し、優先度を 50 に設定します。
struct sched_param sp = { .sched_priority = 50 };
int ret;
ret = sched_setscheduler(0, SCHED_FIFO, &sp);
if (ret == -1) {
perror("sched_setscheduler");
return 1;
}
40.3. ライブラリー呼び出しを使用したプロセス優先度パラメーターの設定 リンクのコピーリンクがクリップボードにコピーされました!
sched_setparam() 関数は、特定プロセスのスケジューリングパラメーターを設定するために使用されます。その後、sched_getparam() 関数を使用して確認できます。
スケジューリングポリシーのみを返す sched_getscheduler() 関数とは異なり、sched_getparam() 関数は指定のプロセスのすべてのスケジューリングパラメーターを返します。
手順
指定したリアルタイムプロセスの優先度を読み取り、それを 2 増加させる以下のコードの抜粋を使用します。
struct sched_param sp;
int ret;
ret = sched_getparam(0, &sp);
sp.sched_priority += 2;
ret = sched_setparam(0, &sp);
このコードを実際のアプリケーションで使用する場合は、関数からの戻り値を確認し、エラーを適切に処理する必要があります。
優先度の増加に注意してください。この例のように、スケジューラーの優先度を 2 増加させ続けると、最終的に無効な優先度になる可能性があります。
40.4. プロセスのスケジューリングポリシーおよび関連する属性の設定 リンクのコピーリンクがクリップボードにコピーされました!
sched_setattr() 関数は、PID で指定されたインスタンス ID のスケジューリングポリシーとそれに関連する属性を設定します。pid=0 の場合、sched_setattr() は呼び出し元のスレッドのプロセスおよび属性に作用します。
手順
-
sched_setattr()を呼び出して、呼び出しが作用するプロセス ID と、以下のリアルタイムスケジューリングポリシーのいずれかを指定します。
リアルタイムスケジューリングポリシー
SCHED_FIFO- 先入れ先出し方式をスケジュールします。
SCHED_RR- ラウンドロビンポリシーをスケジュールします。
SCHED_DEADLINE- 期限スケジューリングポリシーをスケジュールします。
Linux は、以下の非リアルタイムスケジューリングポリシーもサポートしています。
非リアルタイムスケジューリングポリシー
SCHED_OTHER- 標準のラウンドロビンタイムシェアリングポリシーをスケジュールします。
SCHED_BATCH- プロセスの “バッチ" スタイルの実行をスケジュールします。
SCHED_IDLE非常に優先度の低いバックグラウンドジョブをスケジュールします。
SCHED_IDLEは静的優先度0でのみ使用でき、nice 値はこのポリシーに影響を与えません。このポリシーは、非常に低い優先度 (
SCHED_OTHERまたはSCHED_BATCHポリシーを使用した +19 nice 値よりも低い) でジョブを実行することを目的としています。
第41章 リアルタイムカーネルの問題と解決策のスケジューリング リンクのコピーリンクがクリップボードにコピーされました!
場合によっては、リアルタイムカーネルでのスケジューリングによって影響が発生することがあります。提供される情報を使用すると、リアルタイムカーネル上のスケジューリングポリシー、スケジューラーのスロットリング、およびスレッドの枯渇状態に関する問題と、考えられる解決策を理解できます。
41.1. リアルタイムカーネルのスケジューリングポリシー リンクのコピーリンクがクリップボードにコピーされました!
リアルタイムスケジューリングポリシーには、共通した大きな特徴が 1 つあります。それは、より優先度の高いスレッドがスレッドに割り込むか、スレッドがスリープまたは I/O の実行によって待機状態になるまで、リアルタイムスケジューリングポリシーは実行を続けるという点です。
SCHED_RR の場合、オペレーティングシステムは、実行中のスレッドに割り込み、同じ SCHED_RR 優先度を持つ別のスレッドを実行可能にします。このようないずれの場合も、優先度の低いスレッドが CPU 時間を取得できるようにするポリシーを定義する POSIX 仕様によりプロビジョニングが行われることはありません。リアルタイムスレッドのこの特性は、特定の CPU の 100% を独占するアプリケーションの作成が非常に簡単であることを意味します。ただし、これにより、オペレーティングシステムに問題が発生します。たとえば、オペレーティングシステムは、システム全体のリソースと CPU ごとのリソースの両方を管理し、これらのリソースを記述するデータ構造を定期的に調べて、それらのハウスキーピングアクティビティーを実行する必要があります。しかし、コアが SCHED_FIFO スレッドによって独占されていると、そのコアはハウスキーピングタスクを実行できません。最終的にシステム全体が不安定になり、クラッシュする可能性があります。
RHEL for Real Time カーネルでは、割り込みハンドラーは優先度が SCHED_FIFO のスレッドとして実行されます。デフォルトの優先度は 50 です。割り込みハンドラースレッドよりも高い SCHED_FIFO ポリシーまたは SCHED_RR ポリシーが割り当てられた cpu-hog スレッドでは、割り込みハンドラーの実行を防ぐことができます。これにより、これらの割り込みによるシグナルのデータを待機しているプログラムが枯渇し、エラーが発生します。
41.2. リアルタイムカーネルでのスケジューラーのスロットリング リンクのコピーリンクがクリップボードにコピーされました!
リアルタイムカーネルには、リアルタイムタスクで使用する帯域幅の割り当てを可能にする保護メカニズムが搭載されています。この保護メカニズムは、リアルタイムスケジューラーのスロットルと呼ばれています。
リアルタイムスロットリングメカニズムのデフォルト値は、リアルタイムタスクで CPU 時間の 95% を使用できるように定義します。残りの 5% はリアルタイム以外のタスク (SCHED_OTHER および同様のスケジューリングポリシーで実行されるタスク) に割り当てられます。1 つのリアルタイムタスクが CPU タイムスロットの 95% を占有している場合、その CPU 上の残りのリアルタイムタスクは実行されないことに注意してください。残りの 5% の CPU 時間は、リアルタイム以外のタスクでのみ使用されます。デフォルト値は、次のようなパフォーマンスの影響を与える可能性があります。
- リアルタイムタスクで使用できる CPU 時間は最大 95% です。これはリアルタイムタスクのパフォーマンスに影響を与える可能性があります。
- リアルタイムタスクは、リアルタイム以外のタスクの実行を許可せず、システムをロックアップしません。
リアルタイムスケジューラーのスロットリングは、/proc ファイルシステム内の次のパラメーターによって制御されます。
/proc/sys/kernel/sched_rt_period_usパラメーター-
100% の CPU 帯域幅である期間を
μs(マイクロ秒) 単位で定義します。デフォルト値は 1,000,000 μs、つまり 1 秒です。期間の値が非常に高いか低いと問題が発生する可能性があるため、期間の値の変更は慎重に検討する必要があります。 /proc/sys/kernel/sched_rt_runtime_usパラメーター-
すべてのリアルタイムタスクに使用できる合計帯域幅を定義します。デフォルト値は 950,000 μs (0.95 秒) です。これは CPU 帯域幅の 95% です。値を
-1に設定すると、リアルタイムタスクが CPU 時間を最大 100% 使用するように設定されます。これは、リアルタイムタスクが適切に設定され、無制限のポーリングループなどの明らかな注意点がない場合にのみ適切です。
41.3. リアルタイムカーネルでのスレッド枯渇 リンクのコピーリンクがクリップボードにコピーされました!
スレッドスタベーションは、スレッドがスタベーションしきい値よりも長く CPU 実行キューにあり、進行しない場合に発生します。スレッドスターベーションの一般的な原因は、CPU にバインドされた SCHED_FIFO や SCHED_RR など、固定優先度のポーリングアプリケーションを実行することです。ポーリングアプリケーションは I/O をブロックしないため、kworkers などの他のスレッドがその CPU で実行されなくなる可能性があります。
スレッドスタベーションを減らすための初期の試みは、リアルタイムスロットリングと呼ばれます。リアルタイムスロットリングでは、各 CPU に非リアルタイムタスク専用の実行時間の一部があります。スロットリングのデフォルト設定はオンであり、CPU の 95% がリアルタイムタスク用に割り当てられ、5% がリアルタイム以外のタスク用に予約されます。これは、1 つのリアルタイムタスクが原因でスタベーションが発生している場合には機能しますが、CPU に複数のリアルタイムタスクが割り当てられている場合には機能しません。以下を使用して問題を回避できます。
stalld機能stalld機能は、リアルタイムスロットリングの代替手段であり、スロットリングの欠点の一部を回避します。stalldは、システム内の各スレッドの状態を定期的に監視するデーモンであり、指定された時間、実行されずに、実行キューにあるスレッドを探します。stalldは、SCHED_DEADLINEポリシーを使用するようにそのスレッドを一時的に変更し、指定された CPU でスレッドにわずかな時間を割り当てます。次にスレッドが実行され、タイムスライスが使用されると、スレッドは元のスケジューリングポリシーに戻り、stalldはスレッドの状態を監視し続けます。ハウスキーピング CPU は、すべてのデーモン、シェルプロセス、カーネルスレッド、割り込みハンドラー、および分離された CPU からディスパッチできるすべての作業を実行する CPU です。リアルタイムスロットリングが無効になっているハウスキーピング CPU の場合、
stalldはメインワークロードを実行する CPU を監視し、その CPU にSCHED_FIFOビジーループを割り当てます。これは、停止したスレッドを検出し、事前に定義された許容可能な追加ノイズを使用して、必要に応じてスレッドの優先度を向上させるのに役立ちます。リアルタイムのスロットリング機能によってメインワークロードに不当なノイズが発生する場合は、stalldが優先される可能性があります。stalldを使用すると、不足しているスレッドをブーストすることによって導入されるノイズをより正確に制御できます。シェルスクリプト/usr/bin/throttlectlは、stalldの実行時にリアルタイムスロットリングを自動的に無効にします。/usr/bin/throttlectl showスクリプトを使用して、現在のスロットル値を一覧表示できます。- リアルタイムスロットリングの無効化
/procファイルシステムの次のパラメーターは、リアルタイムスロットリングを制御します。-
/proc/sys/kernel/sched_rt_period_usパラメーターは、期間のマイクロ秒数を指定します。デフォルトは 100 万、つまり 1 秒です。 -
/proc/sys/kernel/sched_rt_runtime_usパラメーターは、スロットリングが発生する前にリアルタイムタスクで使用できるマイクロ秒数を指定します。デフォルトは 950,000、つまり使用可能な CPU サイクルの 95% です。echo -1 > /proc/sys/kernel/sched_rt_runtime_usコマンドを使用して、値-1をsched_rt_runtime_usファイルに渡すことで、スロットルを無効にできます。
-