低レイテンシー操作のための RHEL 8 for Real Time の最適化

Red Hat Enterprise Linux for Real Time 8

Red Hat Enterprise Linux 8 での Linux リアルタイムカーネルの設定

概要

管理者は、Real-Time RHEL カーネルでワークステーションを設定できます。このような調整により、パフォーマンスが強化され、トラブルシューティングが容易になり、システムが最適化されます。

Red Hat ドキュメントへのフィードバック (英語のみ)

ご意見ご要望をお聞かせください。ドキュメントの改善点はございませんか。改善点を報告する場合は、以下のように行います。

  • 特定の文章に簡単なコメントを記入する場合は、以下の手順を行います。

    1. ドキュメントの表示が Multi-page HTML 形式になっていて、ドキュメントの右上端に Feedback ボタンがあることを確認してください。
    2. マウスカーソルで、コメントを追加する部分を強調表示します。
    3. そのテキストの下に表示される Add Feedback ポップアップをクリックします。
    4. 表示される手順に従ってください。
  • より詳細なフィードバックを行う場合は、Bugzilla のチケットを作成します。

    1. Bugzilla の Web サイトにアクセスします。
    2. Component で Documentation を選択します。
    3. Description フィールドに、ドキュメントの改善に関するご意見を記入してください。ドキュメントの該当部分へのリンクも記入してください。
    4. Submit Bug をクリックします。

第1章 RHEL 8 におけるリアルタイムカーネルチューニング

レイテンシー (応答時間) は、イベントとシステム応答間の時間として定義され、通常マイクロ秒(μ)で測定されます。

Linux 環境で実行されているほとんどのアプリケーションでは、基本的なパフォーマンスチューニングにより、レイテンシーを十分に改善できます。レイテンシーが低く、説明責任があり、予測可能でなければならない業界向けに、Red Hat には、レイテンシーがそれらのニーズを満たすように調整できるカーネルの代替品があります。RHEL for Real Time 8 は、RHEL 8 とのシームレスな統合を提供し、クライアントが組織内のレイテンシーを測定、設定、および記録する機会を提供します。

RHEL for Real Time 8 は、非常に高い決定論要件を持つアプリケーション向けに、適切にチューニングされたシステムでの使用を目的としています。カーネルシステムのチューニングにより、決定論の改善が大きくなります。

RHEL for Real Time 8 を使用する前に、標準の RHEL 8 システムの一般的なシステムチューニングを実行してから開始します。RHEL 8 システムの一般的なチューニングの実行に関する詳細は、『RHEL 8 Tuning Guide』を参照してください。

警告

これらのタスクの実行に失敗すると、RHEL 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 スレッドよりも優先度が高くなります (たとえば、優先度が 1SCHED_FIFO スレッドは どの SCHED_OTHER スレッドよりも優先度が高くなります)。SCHED_FIFO スレッドとして作成されたスレッドの優先度はどれも固定され、優先度の高いスレッドによってブロックまたはプリエンプションされるまで実行されます。

  • SCHED_RR (ラウンドロビン)

    SCHED_RR は、SCHED_FIFO を変更したものです。同じ優先度のスレッドにはクォンタムがあり、同じ優先度のすべての SCHED_RR スレッド間でラウンドロビン方式でスケジュールされます。このポリシーはほとんど使用されません。

第2章 実行する RHEL カーネルの指定

インストール済みの任意のカーネル、標準、または Real Time を起動できます。起動中に GRUB メニューで必要なカーネルを手動で選択できます。どのカーネルをデフォルトで起動するかを設定することもできます。

RHEL for Real Time カーネルがインストールされると、自動的にデフォルトのカーネルに設定され、次回の起動時に使用されます。

2.1. デフォルトのカーネルの表示

デフォルトで起動するように設定されたカーネルを表示できます。

手順

  • デフォルトのカーネルを表示するには、以下のコマンドを実行します。

    ~]# grubby --default-kernel
    /boot/vmlinuz-4.18.0-80.rt9.138.el8.x86_64

    コマンドの出力の rt は、デフォルトのカーネルがリアルタイムカーネルであることを示しています。

2.2. 実行中のカーネルの表示

現在実行中のカーネルを表示できます。

手順

  • 現在システムが実行中のカーネルを表示します。

    ~]# uname -a
    Linux rt-server.example.com 4.18.0-80.rt9.138.el8.x86_64 …
    注記

    システムが、8.3 から 8.4 などのマイナーアップデートを受け取ると、デフォルトのカーネルが Real Time カーネルから標準カーネルに自動的に戻る場合があります。

2.3. デフォルトのカーネルの設定

デフォルトのブートカーネルを設定できます。

手順

  1. インストールされた Real Time カーネルを一覧表示します。

    ~]# ls /boot/vmlinuz*rt*
    /boot/vmlinuz-4.18.0-80.rt9.138.el8.x86_64
  2. デフォルトのカーネルを一覧表示されている Real Time カーネルに設定します。

    ~]# grubby --set-default real-time-kernel

    real-time-kernel を Real Time カーネルバージョンに置き換えます。例:

    ~]# grubby --set-default /boot/vmlinuz-4.18.0-80.rt9.138.el8.x86_64

検証手順

  • デフォルトのカーネルを表示します。

    ~]# grubby --default-kernel
    /boot/vmlinuz-4.18.0-80.rt9.138.el8.x86_64

第3章 ハードウェアおよびファームウェアのレイテンシーテストの実行および解釈

RHEL Real Time カーネルで hwlatdetect プログラムを実行することで、潜在的なハードウェアプラットフォームがリアルタイム操作に適したものであることをテストし、検証することができます。

前提条件

  • RHEL-RT (RHEL for Real Time) パッケージおよび rt-tests パッケージがインストールされていることを確認します。
  • 低レイテンシー操作に必要なチューニング手順については、ベンダーのドキュメントを参照してください。

    ベンダーのドキュメントは、システムを System Management Mode (SMM) に変換する System Management Interrupts (SMI) を減らしたり、削除したりする手順を提供できます。システムは SMM ですが、ファームウェアを実行し、オペレーティングシステムのコードは実行しません。これは、SMM の実行中に期限切れになるタイマーはすべて、システムが通常の操作に戻るまで待機することを意味します。Linux では SMI をブロックできないため、これにより原因不明のレイテンシーが発生する可能性があります。実際に SMI を取得したことを示す唯一の兆候は、ベンダー固有のパフォーマンスカウンターレジスターにあります。

    警告

    ハードウェア障害が発生する可能性があるため、Red Hat は SMI を完全に無効にしないことを強く推奨します。

3.1. ハードウェアおよびファームウェアのレイテンシーテストの実行

テストは、ハードウェアアーキテクチャーまたは BIOS/EFI ファームウェアによって導入されるレイテンシーを見つけるため、hwlatdetect プログラムの実行中に、システムに不可をかける必要はありません。hwlatdetect のデフォルト値は、毎秒 0.5 秒間をポーリングし、時間をフェッチするために連続した呼び出しの間に 10 マイクロ秒を超えるギャップを報告することです。hwlatdetect は、システムで可能な限り 最適な 最大レイテンシーを返します。

したがって、最大レイテンシー値が 10us 未満で、hwlatdetect が gaps の 1 つを 20us として報告するアプリケーションがある場合、システムは 20us のレイテンシーのみを保証できます。

注記

hwlatdetect が、システムがアプリケーションのレイテンシー要件を満たせないことを示した場合は、BIOS 設定を変更するか、システムベンダーと協力して、アプリケーションのレイテンシー要件を満たす新しいファームウェアを入手してみてください。

前提条件

  • RHEL-RT パッケージおよび rt-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

関連情報

3.2. ハードウェアおよびファームウェアのレイテンシーテストの解釈

これにより、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
  • 以下の結果は、ファームウェアによるシステムの中断を最小限に抑えるように調整できなかったシステムを表しています。このような場合、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----

    この結果は、システムクロックソースの連続読み取りを実行しているときに、15-18 us の範囲で 10 個のレイテンシーが発生したことを示しています。

    hwlatdetect はトレーサーメカニズムを使用して、予期せぬレイテンシーを検出しました。

    注記

    以前のバージョンでは、ftrace トレーサーではなくカーネルモジュールを使用していました。

結果について

出力には、テスト方法、パラメーター、および結果が表示されます。

表3.1 テスト方法、パラメーター、および結果

パラメーター説明

test duration

10 秒

テストの期間 (秒単位)

detector

tracer

detector スレッドを実行するユーティリティー

parameters

  

Latency threshold

10us

許容可能な最大レイテンシー

Sample window

1000000us

1 秒

Sample width

500000us

1/2 秒

Non-sampling period

500000us

1/2 秒

Output File

なし

出力が保存されるファイル。

Results

  

最大レイテンシー

18us

Latency threshold を超えたテスト中の最大レイテンシー。Latency threshold を超えたサンプルがない場合、レポートは Below threshold を表示します。

Samples recorded

10

テストによって記録されるサンプルの数。

Samples exceeding threshold

10

レイテンシーが Latency threshold を超過したテストによって記録されるサンプル数。

SMIs during run

0

テストの実行中に発生した System Management Interrupts (SMI)の 数。

検出スレッドは、以下の擬似コードを実行するループを実行します。

t1 = timestamp()
	loop:
		t0 = timestamp()
		if (t0 - t1) > threshold
		   outer = (t0 - t1)
		t1 = timestamp
		if (t1 - t0) > threshold
		   inner = (t1 - t0)
		if inner or outer:
		   print
		if t1 > duration:
		   goto out
		goto loop
	out:

t0 は、各ループの開始時のタイムスタンプです。t1 は、各ループの最後にあるタイムスタンプです。内部のループの比較では、t0 - t1 が指定したしきい値 (10 us デフォルト) を超えないことを確認します。外部のループの比較では、ループの下部と上位の t0 - t1 間の時間を確認します。タイムスタンプレジスターの連続読み取り間の時間は数十ナノ秒 (通常はレジスター読み取り、比較、条件付きジャンプ) である必要があるため、連続読み取り間のその他の遅延は、ファームウェアによって導入されるか、またはシステムコンポーネントの接続方法によって導入されます。

注記

内部と外部の hwlatdetector ユーティリティーによって出力される値は、最善のケースで最大レイテンシーになります。レイテンシーの値は、現在のシステムクロックソース (通常は Time Stamp Counter または TSCレジスターですが、HPET または ACPI 電源管理クロックの可能性もあります) の連続読み取りと、ハードウェアとファームウェアの組み合わせによって生じる連続読み取り間の遅延との間の差になります。

適切なハードウェアファームウェアの組み合わせを見つけた後、次のステップは、負荷がかかった間にシステムのリアルタイムパフォーマンスをテストすることです。

第4章 システムレイテンシーテストの実行および解釈

RHEL for Real Time は、負荷がかかった状態でシステムのリアルタイムパフォーマンスをテストするための rteval ユーティリティーを提供します。

4.1. 前提条件

  • RHEL for Real Time パッケージグループがインストールされている。
  • システムの root パーミッション。{Is this true?}

4.2. システムレイテンシーテストの実行

rteval ユーティリティーを実行して、負荷がかかった状態でシステムのリアルタイムパフォーマンスをテストできます。

前提条件

  • RHEL for Real Time パッケージグループがインストールされている。
  • システムの root パーミッション。

手順

  • rteval ユーティリティーを実行します。

    # rteval

    rteval ユーティリティーは、SCHED_OTHER タスクの大規模なシステム負荷を開始します。次に、それぞれのオンライン CPU でリアルタイムの応答を測定します。負荷は、ループの Linux カーネルツリーと hackbench の合成ベンチマークの並列の make になります。

    この目的は、システムを状態にすることにあります。それぞれのコアには、常にスケジュールするジョブがあります。ジョブは、メモリーの割り当て/解放、ディスク I/O、計算タスク、メモリーコピーなどのさまざまなタスクを実行します。

    負荷が開始されると、rtevalcyclictest 測定プログラムを開始します。このプログラムは、各オンラインコアで 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

第5章 永続的なカーネルチューニングパラメーターの設定

システムで機能するチューニング設定を決定したら、再起動後も変更を永続化できます。

デフォルトでは、編集したカーネルチューニングパラメーターは、システムが再起動するか、パラメーターが明示的に変更されるまで有効になります。この方法は、初期チューニング設定を確立するために有効です。また、安全性のメカニズムも提供します。編集したパラメーターによって、マシンの動作が不安定になった場合、マシンを再起動すると、パラメーターが以前の設定に戻ります。

5.1. 永続的なカーネルチューニングパラメーターの変更

パラメーターを /etc/sysctl.conf ファイルに追加することにより、カーネルチューニングパラメーターに永続的な変更を加えることができます。

注記

この手順では、現行のセッションのカーネルチューニングパラメーターは 変更されません/etc/sysctl.conf に入力した変更は、今後のセッションにのみ影響します。

前提条件

  • root 権限

手順

  1. テキストエディターで /etc/sysctl.conf を開きます。
  2. パラメーターの値を使用して、新規エントリーをファイルに挿入します。

    /proc/sys/ パスを削除し、残りのスラッシュ (/) をピリオド (.) に変更して、パラメーターの値を追加することで、パラメーター名を変更します。

    たとえば、コマンド echo 0 > /proc/sys/kernel/hung_task_panic を永続化するには、以下を /etc/sysctl.conf に入力します。

    # Enable gettimeofday(2)
    kernel.hung_task_panic = 0
  3. ファイルを保存してから閉じます。
  4. システムを再起動して、変更を有効にします。

検証

  • 設定を確認するには、以下を実行します。

    ~]# cat /proc/sys/kernel/hung_task_panic
    0

第6章 不要なアプリケーションの実行を回避してパフォーマンスを改善

実行中のアプリケーションはすべて、システムリソースを使用します。システムで不要なアプリケーションが実行されていないことを確認することで、パフォーマンスを大幅に向上させることができます。

前提条件

  • システムの root パーミッション。

手順

  1. 絶対に必要とされない場所 (特にサーバー上) では、グラフィカルインターフェース を実行しないでください。

    システムが、デフォルトで GUI で起動するように設定されているかどうかを確認します。

    # systemctl get-default
  2. コマンドの出力が graphical.target の場合は、システムがテキストモードに起動するように設定します。

    # systemctl set-default multi-user.target
  3. チューニングしているシステムで Mail Transfer Agent (MTA) をアクティブに使用している場合を除き、無効にしてください。MTA が必要な場合は、適切に調整されていることを確認するか、専用のマシンに移動することを検討してください。

    詳細は MTA のドキュメントを参照してください。

    重要

    MTA は、cron などのプログラムで実行されるシステム生成メッセージを送信するために使用されます。これには、logwatch などのロギング関数によって生成されるレポートが含まれます。マシン上の MTA が無効になっていると、これらのメッセージを受信することはできません。

  4. マウス、キーボード、Webcams などの 周辺機器 は、レイテンシーに悪影響を与える可能性のある割り込みを送信します。グラフィカルインターフェースを使用していない場合は、未使用の周辺機器をすべて取り外して無効にします。

    詳細は、デバイスのドキュメントを参照してください。

  5. パフォーマンスに影響を及ぼす可能性のある自動 cron ジョブの有無を確認します。

    # crontab -l

    crond サービスまたは不要な cron ジョブを無効にします。

    詳細は、CRON(8) の man ページを参照してください。

  6. サードパーティーのアプリケーションおよび外部のハードウェアベンダーが追加したコンポーネントの有無についてシステムを確認し、不要なものをすべて削除します。

第7章 ジャーナリングに起因するシステムの速度低下を最小限に抑えるか回避する

ジャーナルの変更がディスクに書き込まれる順序は、到達する順序とは異なる場合があります。カーネル I/O システムは、ジャーナルの変更の並べ替えを行い、利用可能なストレージ領域の使用を最適化できます。ジャーナルアクティビティーは、ジャーナルの変更を並べ替え、データおよびメタデータをコミットすることで、システムレイテンシーが発生する可能性があります。その結果、ファイルシステムのジャーナリングによってシステムの速度が低下する可能性があります。

XFS は、RHEL 8 で使用されるデフォルトのファイルシステムです。これはジャーナリングファイルシステムです。ext2 と呼ばれる古いファイルシステムは、ジャーナリングを使用しません。組織が特にジャーナリングを必要とする場合を除き、ext2 の使用を検討してください。Red Hat の最良なベンチマーク結果の多くでは、ext2 ファイルシステムが使用されています。これは、上位の初期チューニングの推奨項目の 1 つです。

XFS のようなジャーナリングファイルシステムは、ファイルが最後にアクセスされた時刻を記録します (atime)。ジャーナリングファイルシステムを使用する必要がある場合は、atime を無効にすることを検討してください。

7.1. atime の無効化

atime を無効にするとパフォーマンスが向上し、ファイルシステムジャーナルへの書き込み回数を制限することで電力使用量が減少します。

手順

atime を無効にするには、以下を実行します。

  1. 選択したテキストエディターを使用して /etc/fstab ファイルを開き、root マウントポイントのエントリーを見つけます。

    /dev/mapper/rhel-root       /       xfs    defaults&hellip;
  2. オプションのセクションを編集して、noatime および nodiratime という用語を追加します。noatime オプションは、ファイルの読み取り時のアクセスタイムスタンプの更新を阻止し、nodiratime オプションは、ディレクトリーの inode アクセス時刻の更新を停止します。

    /dev/mapper/rhel-root       /       xfs    noatime,nodiratime&hellip;
重要

一部のアプリケーションは、更新される atime に依存します。したがって、このオプションは、このようなアプリケーションが使用されていないシステムでのみ妥当です。

または、前のアクセス時刻が現在の変更時刻よりも古い場合にのみ、アクセス時刻が更新されるようにする relatime マウントオプションを使用することができます。

7.2. 関連情報

  • mkfs.ext2(8) の man ページ
  • mkfs.xfs(8) の man ページ
  • mount(8) の man ページ

第8章 アプリケーションのニーズを満たすためのシステムクロックの管理

NUMA や SMP などのマルチプロセッサーシステムには、複数のハードウェアクロックインスタンスがあります。起動時に、カーネルは利用可能なクロックソースを検出し、使用するクロックソースを選択します。パフォーマンスを改善するために、リアルタイムシステムの最小要件を満たすために使用されるクロックソースを変更できます。

8.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 つのオプションは、読み取るのにコストがかかるか、解像度 (時間粒度) が低いかのどちらかであるため、リアルタイムカーネルでの使用は準最適となります。

8.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 です。

8.3. 現在使用中のクロックソースの表示

システムで現在使用されているクロックソースは、/sys/devices/system/clocksource/clocksource0/current_clocksource ファイルに保存されています。

手順

  • current_clocksource ファイルを表示します。

    # cat /sys/devices/system/clocksource/clocksource0/current_clocksource
    tsc

    この例では、システムの現在のクロックソースは TSC です。

8.4. 使用するクロックソースを一時的に変更

システムメインアプリケーションの最適なクロックは、クロックの既知の問題により使用されないことがあります。すべての問題のあるクロックを実行した後、システムはリアルタイムシステムの最低要件を満たすことができないハードウェアクロックで残すことができます。

重要なアプリケーションの要件は、システムごとに異なります。したがって、各アプリケーションに適したクロックも異なります。その結果、各システムも異なります。アプリケーションによっては、クロックの解像度により異なり、信頼できるナノ秒の読み取りを提供するクロックの方が適しています。クロックを読み取るアプリケーションは、読み取りコストが少なくてクロックのメリットを得ることができます (読み取り要求と結果の間隔)。

これらのケースでは、このオーバーライドの副次的な影響を理解し、特定のハードウェアクロックの既知の欠点をトリガーしない環境を作成できる場合は、カーネルが選択したクロックをオーバーライドできます。

重要

カーネルは、利用可能な最適なクロックソースを自動的に選択します。選択したクロックソースの上書きは、影響が明確に理解されない限り推奨されません。

前提条件

  • システム上の root パーミッション。

手順

  1. 利用可能なクロックソースを表示します。

    # cat /sys/devices/system/clocksource/clocksource0/available_clocksource
    tsc hpet acpi_pm

    この例では、システムで利用可能なクロックソースは TSC、HPET、および ACPI_PM です。

  2. /sys/devices/system/clocksource/clocksource0/current_clocksource ファイルに使用するクロックソースの名前を書き込みます。

    # echo hpet > /sys/devices/system/clocksource/clocksource0/current_clocksource
    注記

    この手順では、現在使用中のクロックソースを変更します。システムの再起動後、デフォルトのクロックが使用されます。変更を永続化させるには、「Making persistent kernel tuning parameter changes」を参照してください。

検証手順

  • current_clocksource ファイルを表示して、現在のクロックソースが指定されたクロックソースであることを確認します。

    # cat /sys/devices/system/clocksource/clocksource0/current_clocksource
    hpet

    この例では、システムの現在のクロックソースは HPET です。

8.5. ハードウェアクロックソースの読み込みコストの比較

システムのクロックの速度を比較できます。TSC からの読み取りは、プロセッサーからレジスターを読み取ることを意味します。HPET クロックからの読み取りには、メモリーエリアを読み取る必要があります。TSC からの読み取りが速く、毎秒数百万のメッセージをタイムスタンプにすると、パフォーマンスが大幅に向上します。

前提条件

  • システム上の root パーミッション。
  • clock_timing プログラムはシステム上にある必要があります。詳細は、「the clock_timing program」を参照してください。

手順

  1. clock_timing プログラムを保存するディレクトリーに移動します。

    # cd clock_test
  2. システムで利用可能なクロックソースを表示します。

    # cat /sys/devices/system/clocksource/clocksource0/available_clocksource
    tsc hpet acpi_pm

    この例では、システムで利用可能なクロックソースは TSCHPET、および ACPI_PM になります。

  3. 現在使用中のクロックソースを表示します。

    # cat /sys/devices/system/clocksource/clocksource0/current_clocksource
    tsc

    この例では、システムの現在のクロックソースは TSC です。

  4. ./clock_timing プログラムとともに time ユーティリティーを実行します。この出力は、クロックソースを 10 万回読み込むために必要な期間を表示します。

    # time ./clock_timing
    
    	real	0m0.601s
    	user	0m0.592s
    	sys	0m0.002s

    以下の例は、次のパラメーターを示しています。

    • real: プログラムの呼び出しから始まり、プロセスが終了するまでに費やした合計時間real には、ユーザーとカーネル時間が含まれており、通常は後者 2 の合計値よりも大きくなります。このプロセスが、優先度の高いアプリケーションや、ハードウェア割り込み (IRQ) などのシステムイベントによって中断される場合、待機に費やされたこの時間も real 下で計算されます。
    • user: カーネルの介入を必要としないタスクを実行するプロセスがユーザ空間で過ごした時間。
    • sys: ユーザープロセスで必要なタスクの実行中にカーネルが費やした時間。これらのタスクには、ファイルのオープン、ファイルまたは I/O ポートの読み取りおよび書き込み、メモリーの割り当て、スレッドの作成、およびネットワーク関連のアクティビティーが含まれます。
  5. /sys/devices/system/clocksource/clocksource0/current_clocksource ファイルに、テストする次のクロックソースの名前を書き込みます。

    # echo hpet > /sys/devices/system/clocksource/clocksource0/current_clocksource

    この例では、現在のクロックソースが HPET に変更されています。

  6. 利用可能なクロックソースすべてに対して、ステップ 4 と 5 を繰り返します。
  7. 利用可能なすべてのクロックソースに対して、ステップ 4 の結果を比較します。

関連情報

  • time(1) の man ページ

8.6. clock_timing プログラム

clock_timing プログラムは、現在のクロックソースを 1,000万時間読み取ります。time ユーティリティーとともに、これを行うために必要な時間を測定します。

手順

clock_timing プログラムを作成するには、以下を実行します。

  1. プログラムファイルのディレクトリーを作成します。

    $ mkdir clock_test
  2. 作成したディレクトリーに移動します。

    $ cd clock_test
  3. ソースファイルを作成してテキストエディターで開きます。

    vi clock_timing.c
  4. ファイルに以下のコマンドを入力します。

    #include <time.h>
    void main()
    {
    	int rc;
    	long i;
    	struct timespec ts;
    
            for(i=0; i<10000000; i++) {
    		rc = clock_gettime(CLOCK_MONOTONIC, &ts);
    	}
    }
  5. ファイルを保存して、エディターを終了します。
  6. ファイルをコンパイルします。

    $ gcc clock_timing.c -o clock_timing -lrt

    clock_timing プログラムの準備ができ、保存されているディレクトリーから実行できます。

第9章 電源管理移行の制御

電源管理の移行を制御すると、レイテンシーが改善されます。

前提条件

  • システムの root パーミッション。

9.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 ステート (省電力モード) に入ることを阻止します。

アプリケーションが /dev/cpu_dma_latency ファイルを開いたままにすると、PM QoS インターフェースはプロセッサーが深いスリープ状態に入ることを阻止します。これにより、終了する際に予期せぬレイテンシーが発生します。ファイルが閉じられると、システムは省電力状態に戻ります。

9.2. 電源管理状態の設定

/dev/cpu_dma_latency ファイルに値を書き込むことで、プロセスの最大応答時間 (マイクロ秒単位) を変更できます。このファイルは、アプリケーションやスクリプトで参照することもできます。

前提条件

  • システム上の root パーミッション。

手順

  1. /dev/cpu_dma_latency ファイルを開きます。ファイル記述子を低レイテンシー操作の期間中開いたままにします。
  2. 32 ビットの数字をファイルに書き込みます。この数は、最大応答時間 (マイクロ秒単位) を表します。可能な限り最速の応答時間を得るには、0 を使用します。

以下は、この方法を使用して電源の遷移を防ぎ、低レイテンシーを維持するプログラムの例になります。

main()

static int pm_qos_fd = -1;

void start_low_latency(void)
{
	s32_t target = 0;

	if (pm_qos_fd >= 0)
		return;
	pm_qos_fd = open("/dev/cpu_dma_latency", O_RDWR);
	if (pm_qos_fd < 0) {
	   fprintf(stderr, "Failed to open PM QOS file: %s",
	           strerror(errno));
	   exit(errno);
	}
	write(pm_qos_fd, &target, sizeof(target));
}

void stop_low_latency(void)
{
	if (pm_qos_fd >= 0)
	   close(pm_qos_fd);
}

9.3. 関連情報

  • Linux System Programming』(Robert Love 著)

第10章 システムチューニング用の BIOS パラメーターの設定

このセクションでは、システムパフォーマンスを改善するために設定できるさまざまな BIOS パラメーターについて説明します。

注記

システムおよび BIOS ベンダーはすべて、さまざまな用語とナビゲーション方法を使用します。したがって、本セクションでは、BIOS 設定に関する一般的な情報のみを説明します。

特定の設定を見つけるためのサポートが必要な場合は、BIOS のドキュメントを確認するか、BIOS ベンダーに連絡してください。

10.1. 電源管理の無効化による応答時間の向上

BIOS 電源管理オプションは、システムクロックの周波数を変更したり、CPU をさまざまなスリープ状態の 1 つにすることで、電力を節約できるようにします。このようなアクションは、システムが外部イベントに応答する速度に影響を与える可能性があります。

応答時間を改善するには、BIOS の電源管理オプションをすべて無効にします。

10.2. エラー検出と修正ユニットの無効化による応答時間の改善

Error Detection and Correction (EDAC) ユニットは、Error Correcting Code (ECC) メモリーから通知されたエラーを検出および訂正するためのデバイスです。通常、EDAC オプションは、ECC チェックなしから、エラーに関するすべてのメモリーノードの定期的なスキャンまであります。EDAC レベルが高いほど、BIOS が使用する時間が長くなります。これにより、重要なイベントの期限を逃す可能性があります。

応答時間を改善するには、EDAC をオフにします。これができない場合は、EDAC を最小機能レベルに設定します。

10.3. システム管理割り込みの設定による応答時間の向上

System Management Interrupts (SMI) は、システムが正常に動作していることを確認するハードウェアベンダーの機能です。BIOS コードは、通常、SMI 割り込みを処理します。SMI は通常、温度管理、リモートコンソール管理(IPMI)、EDAC チェック、およびその他のハウスキーピングタスクに使用されます。

BIOS に SMI オプションが含まれる場合は、ベンダーおよび関連ドキュメントを確認して、それらを無効にしても安全な範囲を判断してください。

警告

SMI を完全に無効にすることは可能ですが、Red Hat ではこれを行わないことを強くお勧めします。SMI を生成してサービスするシステムの機能を削除すると、壊滅的なハードウェア障害が発生する可能性があります。

第11章 割り込みとユーザープロセスを分離してシステムレイテンシーを最小限に抑える

リアルタイム環境では、さまざまなイベントに応答する際にレイテンシーを最小限に抑える必要があります。これを行うには、異なる専用 CPU 上で割り込み (IRQ) をユーザープロセスから相互に分離できます。

11.1. 割り込みおよびプロセスバインディング

異なる専用 CPU 上のユーザープロセスから割り込み (IRQ) を分離することで、リアルタイム環境におけるレイテンシーを最小限に抑えるか、なくすことができます。

通常、割り込みは CPU 間で均等に共有されます。これにより、CPU が新しいデータおよび命令キャッシュを書き込む必要があるときに、割り込み処理を遅延させることができます。これらの割り込み遅延は、同じ CPU で実行されている他の処理との競合を引き起こす可能性があります。

タイムクリティカルな割り込みおよびプロセスを特定の CPU (または CPU の範囲) に割り当てることができます。これにより、この割り込みを処理するコードおよびデータ構造がプロセッサーおよび命令キャッシュにある可能性が非常に高くなります。その結果、専用のプロセスはできるだけ迅速に実行でき、他のすべてのタイムクリティカルでないプロセスは他の CPU で実行されます。これは、関連する速度がメモリーおよび使用可能なペリフェラルバス帯域幅に近いか限界にある場合に、特に重要になる可能性があります。メモリーがプロセッサーキャッシュにフェッチされるのを待つと、全体的な処理時間と決定論に顕著な影響があります。

実際には、最適なパフォーマンスはアプリケーションによって完全に異なってきます。たとえば、異なる企業に同様の機能を持つアプリケーションをチューニングするには、全く異なる最適なパフォーマンスチューニングが必要になります。

  • ある企業は、オペレーティングシステムの機能と割り込み処理のために 4 つの CPU のうち 2 つを分離したときに、最適な結果を確認しました。残りの 2 つの CPU は、純粋にアプリケーション処理専用でした。
  • 別の会社は、ネットワーク関連のアプリケーションプロセスを、ネットワークデバイスドライバーの割り込みを処理している単一の CPU にバインドしたときに、最適な決定論を見つけました。
重要

プロセスを CPU にバインドするには、通常、特定の CPU または CPU の範囲の CPU マスクを把握する必要があります。CPU マスクは通常、使用するコマンドに応じて、32 ビットのビットマスク、10 進数、または 16 進数で表されます。

表11.1 例

CPU

Bitmask

10 進数

16 進数

0

00000000000000000000000000000001

1

0x00000001

0, 1

00000000000000000000000000000011

3

0x00000011

11.2. irqbalance デーモンの無効化

irqbalance デーモンはデフォルトで有効になっており、CPU が割り込みを均等に処理するように定期的に強制します。ただし、リアルタイムのデプロイメントでは、アプリケーションは通常特定の CPU にバインドされているため、irqbalance は必要ありません。

手順

  1. irqbalance のステータスを確認します。

    # systemctl status irqbalance
    irqbalance.service - irqbalance daemon
       Loaded: loaded (/usr/lib/systemd/system/irqbalance.service; enabled)
       Active: active (running) …
  2. irqbalance が実行されている場合、これを無効にして停止します。

    # systemctl disable irqbalance
    # systemctl stop irqbalance

検証

  • irqbalance ステータスが非アクティブであることを確認します。

    ~]# systemctl status irqbalance

11.3. IRQ バランスからの CPU の除外

IRQ バランシングサービスを使用して、割り込み (IRQ) バランシングを考慮する際に除外する CPU を指定できます。/etc/sysconfig/irqbalance 設定ファイルの IRQBALANCE_BANNED_CPUS パラメーターは、この設定を制御します。パラメータの値は 64 ビットの 16 進数ビットマスクで、マスクの各ビットは CPU コアを表します。

手順

  1. 任意のテキストエディターで /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=
  2. IRQBALANCE_BANNED_CPUS 変数のコメントを解除します。
  3. 適切なビットマスクを入力し、IRQ バランスメカニズムで無視される CPU を指定します。
  4. ファイルを保存してから閉じます。
注記

最大 64 個の CPU コアを持つシステムを実行している場合は、それぞれ 8 桁の 16 進数のグループをコンマで区切ります。例: IRQBALANCE_BANNED_CPUS=00000001,0000ff00

表11.2 例

CPU

Bitmask

0

00000001

8 - 15

0000ff00

8 - 15, 33

00000001,0000ff00

注記

IRQBALANCE_BANNED_CPUS/etc/sysconfig/irqbalance に設定されていない場合、RHEL 7.2 以降では、irqbalance ユーティリティーは isolcpus カーネルパラメータを介して分離した CPU コアの IRQ を自動的に回避します。

11.4. 個々の IRQ への CPU アフィニティーの手動割り当て

CPU アフィニティーを割り当てると、指定した CPU または CPU の範囲にプロセスとスレッドをバインドおよびバインド解除できます。これにより、キャッシュの問題を減らすことができます。

手順

  1. /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
  2. 特定の IRQ の smp_affinity エントリーに CPU マスクを書き込みます。CPU マスクは、16 進数で表記する必要があります。

    たとえば、以下のコマンドは、IRQ 番号 142 を CPU 0 でのみ実行されるように指示します。

    ~]# echo 1 > /proc/irq/142/smp_affinity

    この変更は、割り込みが発生した場合にのみ有効になります。

検証手順

  1. 指定の割り込みをトリガーするアクティビティーを実行します。
  2. /proc/interrupts で変更を確認します。

    設定された IRQ の指定された CPU の割り込みの数は増加し、指定されたアフィニティー外の CPU で設定された IRQ の割り込みの数は増加しませんでした。

11.5. taskset ユーティリティーを使用したプロセスの CPU へのバインド

taskset ユーティリティーは、タスクのプロセス ID (PID) を使用して、その CPU アフィニティーを表示または設定します。このユーティリティーを使用して、選択した CPU アフィニティーでコマンドを起動できます。

アフィニティーを設定するには、CPU マスクを 10 進数または 16 進数にする必要があります。マスクの引数は、コマンドまたは変更される PID に対してどの CPU コアが有効なかを指定するビットマスクです。

重要

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
注記

一覧表示されているオプションを組み合わせることができます。

関連情報

  • taskset(1) の man ページ
  • numactl(8) の man ページ

第12章 Out of Memory (OOM) 状態の管理

OOM (Out of Memory) は、スワップ領域を含む利用可能なメモリーがすべて割り当てられているコンピューティング状態を指します。通常、これによりシステムがパニックになり、想定どおりに機能しなくなります。

以下では、システムで OOM の状態を回避する手順を説明します。

12.1. 前提条件

  • システム上の root パーミッション。

12.2. 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 の値を変更できます。

手順

  1. /proc/sys/vm/panic_on_oom の現在の値を表示します。

    # cat /proc/sys/vm/panic_on_oom
    0

    /proc/sys/vm/panic_on_oom の値を変更するには、次のコマンドを実行します。

  2. 新しい値を /proc/sys/vm/panic_on_oom に echo します。

    # echo 1 > /proc/sys/vm/panic_on_oom
注記

OOM で Real-Time カーネルパニックを発生させることが推奨されます (1)。そうしないと、システムが OOM 状態になった場合、その状態は決定論的ではなくなります。

検証手順

  1. /proc/sys/vm/panic_on_oom の値を表示します。

    # cat /proc/sys/vm/panic_on_oom
    1
  2. 表示される値が指定された値と一致していることを確認します。

12.3. Out of Memory 状態のときに強制終了するプロセスの優先順位付け

oom_killer 関数で終了するプロセスに優先順位を付けることができます。これにより、優先順位の高いプロセスが OOM 状態の間も実行され続けることが保証されます。各プロセスには /proc/PID ディレクトリーがあります。各ディレクトリーには、以下のファイルが含まれます。

  • oom_adj: oom_adj の有効なスコアは、-16 から +15 の範囲にあります。この値は、他の要因の中でも特に、プロセスの実行時間も考慮に入れるアルゴリズムを使用して、プロセスのパフォーマンスフットプリントを計算するために使用されます。
  • oom_score: oom_adj の値を使用して計算されたアルゴリズムの結果が含まれます。

メモリー不足の状態では、oom_killer 関数は oom_score が最も高いプロセスを終了します。

プロセスの oom_adj ファイルを編集して、終了するプロセスに優先順位を付けることができます。

前提条件

  • 優先するプロセスのプロセス ID (PID) を把握している。

手順

  1. プロセスの現在の oom_score を表示します。

    # cat /proc/12465/oom_score
    79872
  2. プロセスの oom_adj の内容を表示します。

    # cat /proc/12465/oom_adj
    13
  3. oom_adj の値を編集します。

    # echo -5 > /proc/12465/oom_adj

検証手順

  1. プロセスの現在の oom_score を表示します。

    # cat /proc/12465/oom_score
    78
  2. 表示される値が以前の値よりも小さいことを確認します。

12.4. プロセスの Out of Memory Killer の無効化

oom_adj を予約値の -17 に設定することで、プロセスの oom_killer 関数を無効にできます。これにより、OOM 状態でもプロセスが存続します。

手順

  1. oom_adj の値を -17 に設定します。

    # echo -17 > /proc/12465/oom_adj

検証手順

  1. プロセスの現在の oom_score を表示します。

    # cat /proc/12465/oom_score
    0
  2. 表示される値が 0 であることを確認します。

第13章 PC カードデーモンを無効にすることで CPU の使用量を減らします。

pcscd デーモンは、並列通信 (PC または PCMCIA) およびスマートカード (SC) リーダーへの接続を管理します。通常 pcscd は優先度が低いタスクですが、多くの場合、他のデーモンよりも多くの CPU を使用することができます。この新たな背景の根本的な影響により、リアルタイムタスクやその他の決定論的な影響が高まる可能性があります。

前提条件

  • システム上の root パーミッション。

手順

  1. 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-exit

    Active パラメーターは、pcsd デーモンの状態を表示します。

  2. pcsd デーモンを実行している場合は停止します。

    # systemctl stop pcscd
    Warning: Stopping pcscd.service, but it can still be activated by:
      pcscd.socket
  3. システム起動時に pcsd デーモンが再起動しないようにシステムを設定します。

    # systemctl disable pcscd
    Removed /etc/systemd/system/sockets.target.wants/pcscd.socket.

検証手順

  1. 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
  2. Active パラメーターの値が inactive (dead) であることを確認します。

第14章 ロギングパラメーターのバランシング

syslog サーバーは、ネットワーク経由でプログラムからログメッセージを送信します。多くの場合、これはより大きく、保留中のトランザクションである可能性が高くなります。トランザクションが非常に大きい場合、I/O スパイクが発生する可能性があります。これを防ぐには、間隔を合理的に小さく維持します。

システムロギングデーモン syslogd は、異なるプログラムからメッセージを収集するために使用されます。また、カーネルロギングデーモン klogd からカーネルが報告する情報を収集します。通常、syslogd によりローカルファイルにログが記録されますが、リモートロギングサーバーにネットワーク経由でログを記録するように設定することもできます。

手順

リモートロギングを有効にするには、以下を実行します。

  1. ログの送信先となるマシンを設定します。詳細は、「Remote Syslogging with rsyslog on Red Hat Enterprise Linux」を参照してください。
  2. ログをリモートログサーバーに送信する各システムを設定して、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 システムを使用する場合は、組織がリモートでのログ記録を要求するメッセージのみをログに記録することをお勧めします。たとえば、カーネルの警告、認証要求などです。その他のメッセージはローカルに記録する必要があります。

関連情報

  • syslog(3) の man ページ
  • rsyslog.conf(5) の man ページ
  • rsyslogd(8) の man ページ

第15章 tuna CLI を使用したレイテンシーの向上

tuna CLI を使用して、システムのレイテンシーを改善できます。tuna コマンドで使用されるオプションにより、レイテンシーを改善するために呼び出されるメソッドが決定されます。

15.1. 前提条件

  • RHEL for Real Time パッケージグループと tuna パッケージがインストールされている。
  • システムの root パーミッション。

15.2. tuna CLI

tuna コマンドラインインターフェース (CLI) は、システムのチューニング変更を行うためのツールです。

注記

tuna に対して新しいグラフィカルインターフェースが開発されていますが、まだリリースされていません。

tuna CLI を使用して、スケジューラーのチューニング可能機能、チューニングスレッドの優先度、IRQ ハンドラー、CPU コアとソケットの分離を調整することができます。tuna は、チューニングタスクの実行の複雑さを軽減することを目的としています。このツールは、実行中のシステムでの使用を目的として設計されており、直ちに変更が行われます。これにより、アプリケーション固有の測定ツールは、変更が加えられた直後にシステムパフォーマンスを確認および分析できます。

tuna CLI には、アクションオプションと修飾子オプションの両方があります。修飾子オプションは、変更するアクションの前にコマンドラインで指定する必要があります。すべての修飾子オプションは、修飾子オプションがオーバーライドされるまで続くアクションに適用されます。

15.3. tuna CLI を使用した CPU の分離

tuna CLI を使用して、さまざまな専用 CPU 上のユーザープロセスから割り込み (IRQ) を分離し、リアルタイム環境でのレイテンシーを最小限に抑えることができます。CPU の分離に関する詳細は、「Interrupt and process binding」を参照してください。

前提条件

  • RHEL for Real Time パッケージグループと tuna パッケージがインストールされている。
  • システムの root パーミッション。

手順

  • 1 つ以上の CPU を分離します。

    # tuna --cpus=cpu_list --isolate

    cpu_list は、分離する CPU のコンマ区切りの一覧です。

    例:

    # tuna --cpus=0,1 --isolate

15.4. tuna CLI を使用した指定の CPU への割り込みの移動

tuna CLIを使用して、割り込み (IRQ) を専用のCPUに移動し、リアルタイム環境でのレイテンシーを最小化または排除できます。IRQ の移動に関する詳細は、「Interrupt and process binding」を参照してください。

前提条件

  • RHEL for Real Time パッケージグループと tuna パッケージがインストールされている。
  • システムの root パーミッション。

手順

  1. IRQ の一覧が割り当てられている CPU を一覧表示します。

    # tuna --irqs=irq_list --show_irqs

    irq_list は、割り当てられた CPU を一覧表示する IRQ のコンマ区切りリストです。

    例:

    # tuna --irqs=128 --show_irqs
       # users         affinity
     128 iwlwifi          0,1,2,3
  2. IRQ の一覧を CPU の一覧に割り当てます。

    # tuna --irqs=irq_list --cpus=cpu_list --move

    irq_list はアタッチする IRQ のコンマ区切りリストで、cpu_list はそれらがアタッチされる CPU のコンマ区切りのリストです。

    例:

    # tuna --irqs=128 --cpus=3 --move

検証手順

  • IRQ を指定された CPU に移動する前後で、選択されたIRQの状態を比較します。

    # tuna --irqs=128 --show_irqs
       # users         affinity
     128 iwlwifi          3

15.5. tuna CLI を使用したプロセススケジューリングポリシーおよび優先順位の変更

tuna CLI を使用して、プロセススケジューリングポリシーおよび優先順位を変更できます。

前提条件

  • RHEL for Real Time パッケージグループと tuna パッケージがインストールされている。
  • システムの root パーミッション。

    注記

    OTHER および NATCH スケジューリングポリシーの割り当てには、root 権限は必要ありません。

手順

  1. スレッドの情報を表示します。

    # tuna --threads=thread_list --show_threads

    thread_list は、表示するプロセスのコンマ区切りリストになります。

    例:

    # tuna --threads=rngd --show_threads
                          thread       ctxt_switches
        pid SCHED_ rtpri affinity voluntary nonvoluntary             cmd
      3571   OTHER     0  0,1,2,3    167697          134            rngd
  2. プロセススケジューリングポリシーとスレッドの優先度を変更します。

    # tuna --threads=thread_list --priority scheduling_policy:priority_number

    ここでは、以下のようになります。

    • 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 --threads=rngd --priority FIFO:1

検証手順

  • スレッドの情報を表示して、情報が変更されることを確認します。
# tuna --threads=rngd --show_threads
                      thread       ctxt_switches
    pid SCHED_ rtpri affinity voluntary nonvoluntary             cmd
  3571   FIFO     1  0,1,2,3    167697          134            rngd

第16章 kdump および kexec のインストール

多くの場合、kdump パッケージは RHEL インストールにデフォルトでインストールされ、サービスが有効化および開始されます。

以下で、kdump パッケージのインストール方法を説明します。

前提条件

  • 管理者権限

16.1. kdump および kexec

kdump サービスは、クラッシュしたシステムメモリーの内容を後で分析するために保存するクラッシュダンプメカニズムを提供します。kdump サービスは kexec システムコールを使用して、現在実行中のカーネルから 2 番目のカーネル (キャプチャカーネル) で起動します。次に kdump は、クラッシュしたカーネルメモリーの内容 (クラッシュダンプまたは vmcore) をキャプチャーして保存します。この第 2 のカーネルは、システムメモリーの予約部分に収納されています。

カーネルクラッシュダンプは、システム障害 (重大なバグなど) の発生時に利用できる唯一の情報になります。したがって、ミッションクリティカルな環境で kdump が確実に動作することを確認することが重要です。Red Hat では、システム管理者が通常のカーネル更新サイクルで kexec-tools を定期的に更新してテストすることを推奨しています。これは、新しいカーネル機能が実装される場合に重要になります。

16.2. kdump および kexec のインストール

クラッシュダンプメカニズムを利用して、RHEL for Real Time を使用して停止したシステムをトラブルシューティングするには、kexec-tools および rt-setup-kdump ユーティリティーをインストールする必要があります。これらはコマンドラインからインストールできます。

注記

Anaconda インストーラーには、グラフィカルまたはテキストインターフェイスを使用してインタラクティブインストールを実行する際の kdump 設定の画面が含まれています。インストーラーの画面には Kdump という名前が付けられ、メインの Installation Summary 画面から利用できます。Kdump 画面は、インストール後に kdump を有効にするかどうかについて、および予約するメモリー量についてのみ有効にします。

カスタムの Kickstart インストールなどの一部のインストールオプションでは、デフォルトで kdump がインストールまたは有効化されない場合があります。

前提条件

  • rhel-8-for-x86_64-rt-rpms リポジトリーが有効になっている
  • kdump 設定とターゲットの要件をすべて満たしている

手順

  1. kexec-tools パッケージがシステムにインストールされているかどうかを確認します。

    $ rpm -q kexec-tools
    • パッケージがすでにインストールされている場合は、出力には kexec-tools パッケージのバージョン番号が表示されます。

      kexec-tools-2.0.17-11.el8.x86_64
    • パッケージがインストールされていない場合は、出力は以下のようになります。

      package kexec-tools is not installed

      kdump ツールをインストールします。

      # yum install kexec-tools
  2. rt-setup パッケージをインストールして、rt-setup-kdump ユーティリティーを取得します。
# yum install rt-setup

検証

  1. システムに kdump がインストールされているかどうかを確認します。

    $ rpm -q kexec-tools
    kexec-tools-2.0.17-11.el8.x86_64

第17章 一般的なシステムチューニング

本章では、Red Hat Enterprise Linux の標準的なインストールで実行できる一般的なチューニングについて説明します。これは、Red Hat Enterprise Linux for Real Time カーネルの利点をより効果的に確認するために、最初に実行されることが重要です。

これらのセクションを最初に読み込むことが推奨されます。これらには、チューニングパラメーターの変更方法についての背景情報が含まれ、本ガイドの他のタスクを実行する上で役立ちます。

17.1. メモリーのヒントのスワップと不足

メモリースワップ

ページをディスクにスワップアウトすると、どの環境でもレイテンシーが発生する可能性があります。レイテンシーを低くするには、システムに十分なメモリーを使用するため、スワップが必要ありません。アプリケーションおよびシステム用に物理 RAM を常にサイズにします。vmstat を使用してメモリーの使用状況を監視し、si (swap in) フィールドおよび so (swap out) フィールドを監視します。可能な限りゼロのままにすることが最適です。

OOM (out of Memory)

OOM (Out of Memory) は、スワップ領域を含む利用可能なメモリーがすべて割り当てられているコンピューティング状態を指します。通常、これによりシステムがパニックが発生し、予想通りに機能しなくなります。/proc/sys/vm/panic_on_oom には OOM の動作を制御するスイッチがあります。1 に設定すると、カーネルは OOM でパニックになります。デフォルト設定は 0 で、OOM で oom_killer という名前の関数を呼び出すようカーネルに指示します。通常、oom_killer は不正プロセスを強制終了でき、システムは存続します。

17.2. ネットワーク決定のヒント

TCP (Transmission Control Protocol)

TCP はレイテンシーに大きな影響を及ぼす可能性があります。TCP は、効率性の取得、輻輳を制御し、信頼できる配信を保証するためにレイテンシーを追加します。チューニング時には、以下の点を考慮してください。

  • 配信の順番が必要ですか。
  • パケットロスに対して保護する必要がありますか。

    複数のパケットを送信すると遅延が発生する可能性があります。

  • TCP を使用する必要がある場合は、ソケット上で TCP_NODELAY を使用して、Nagle バッファリングアルゴリズムを無効にすることを検討してください。Nagle アルゴリズムは小さな送信パケットを収集し、すべてを一度に送信し、レイテンシーに悪影響を及ぼす可能性があります。

ネットワークチューニング

ネットワークを調整するためのツールは多数あります。以下は、より便利なものになります。

コアの割り込み

割り込みの量を減らすには、パケットを収集し、パケットのコレクションに対して単一の割り込みが生成されます。

スループットが最優先である大容量のデータを転送するシステムでは、デフォルト値を使用するかコアレシーを増やし、スループットを高め、CPU にアクセスする割り込みの数を減らすことができます。ネットワークへの迅速な応答を必要とするシステムでは、コアレスを削減または無効化することが推奨されます。

有効化するには、ethtool コマンドに -C (--coalesce) オプションを指定して使用します。

輻輳

多くの場合、I/O スイッチは、フルバッファーの結果としてネットワークデータがビルドされるバックプレッシングの対象になることがあります。

pause パラメーターを変更し、ネットワークの輻輳を回避するには、ethtool コマンドで -A (--pause) オプションを指定して使用します。

Infiniband (IB)
InfiniBand は多くの場合、帯域幅を高め、サービスやフェイルオーバーの品質を提供するために使用される通信アーキテクチャーのタイプです。Remote Direct Memory Access (RDMA) 機能によるレイテンシーを改善するためにも使用できます。
ネットワークプロトコルの統計
ネットワークトラフィックを監視するには、netstat コマンドに -s (--statistics) オプションを指定して使用します。

「TCP パフォーマンスの急増減」 および 「TCP の遅延 ACK タイムアウトの削減」 も参照してください。

  • ethtool(8)
  • netstat(8)

17.3. TCP パフォーマンスの急増減

タイムスタンプをオフにし、タイムスタンプの生成に関連するパフォーマンスの急増を低減します。sysctl コマンドは、TCP 関連のエントリーの値を制御し、/proc/sys/net/ipv4/tcp_timestamps にあるタイムスタンプカーネルパラメーターを設定します。

  • 次のコマンドを実行してタイムスタンプをオフにします。

    ~]# sysctl -w net.ipv4.tcp_timestamps=0
    net.ipv4.tcp_timestamps = 0
  • 以下のコマンドを使用してタイムスタンプをオンにします。

    ~]# sysctl -w net.ipv4.tcp_timestamps=1
    net.ipv4.tcp_timestamps = 1
  • 以下のコマンドで現在の値を出力します。

    ~]# sysctl net.ipv4.tcp_timestamps
    net.ipv4.tcp_timestamps = 1

    1 は、タイムスタンプがオンであることを示します。値 0 はオフであることを示します。

17.4. システムのパーティション設定

リアルタイムチューニングの主要な手法の 1 つが、システムの分割です。つまり、システムで実行している 1 つまたは複数のリアルタイムアプリケーションを排他的に使用するために、CPU コアのグループを分離します。最善の結果を得るには、CPU トポロジーを考慮して、2 次キャッシュと 3 次キャッシュの共有を最大化するために、同じ NUMA (Non-Uniform Memory Access) ノードに含まれるコアに配置されるようにする必要があります。lscpu および tuna ユーティリティーは、システムの CPU トポロジーを判断するために使用されます。Tuna GUI を使用すると、CPU を動的に分離し、スレッドをある CPU から別の CPU に移動して、パフォーマンスへの影響を測定することができます。

パーティション設定がシステムのレイアウトとアプリケーションの構造に基づいて判断されたら、起動時に自動的にパーティションを設定する手順を説明します。そのためには、tuned-profiles-realtime パッケージが提供するユーティリティーを使用します。RedHat EnterpriseLinux for Real Time パッケージがインストールされると、このパッケージがデフォルトでインストールされます。tuned-profiles-realtime を手動でインストールするには、root で以下のコマンドを実行します。

~]# yum install tuned-profiles-realtime

tuned-profiles-realtime パッケージは、追加のユーザー入力を必要とせずに、起動時にパーティション設定やその他のチューニングを可能にする tuned リアルタイムプロファイルを提供します。2 つの設定ファイルにより、プロファイルの動作が制御されます。

  • /etc/tuned/realtime-variables.conf
  • /usr/lib/tuned/realtime/tuned.conf

realtime-variables.conf ファイルは、分離する CPU コアのグループを指定します。システムから CPU コアのグループを分離するには、以下の例のように isolated_cores オプションを使用します。

# Examples:
# isolated_cores=2,4-7
# isolated_cores=2-23
#
isolated_cores=1-3,5,9-14

上記の例では、プロファイルは CPU 1、2、3、5、9、10、11、12、13、および 14 を分離 CPU カテゴリーに配置します。これらの CPU のスレッドのみが、コアにバインドされるカーネルスレッドです。これらのカーネルスレッドは、移行スレッドやウォッチドッグスレッドなどの特定の状態が発生する場合にのみ実行されます。

isolated_cores 変数を設定したら、tuned-adm コマンドでプロファイルをアクティベートします。

~]# tuned-adm profile realtime

プロファイルは bootloader プラグインを使用します。このプラグインを有効にすると、Linux カーネルコマンドラインに以下のブートパラメーターが追加されます。

isolcpus
realtime-variables.conf ファイルに一覧表示されている CPU を指定します。
nohz
アイドル状態の CPU でタイマーティックをオフにし、デフォルトで off に設定します。
nohz_full
CPU に実行可能なタスクが 1 つしかない場合は、CPU でタイマーティックをオフにします。nohzon に設定する必要があります。
intel_pstate=disable
Intel のアイドルドライバーが電源状態および CPU 周波数を管理しないようにする
nosoftlockup
カーネルがユーザースレッドのソフトロックアップを検出しないようにする

上記の例では、カーネルブートコマンドラインパラメーターは以下のようになります。

isolcpus=1-3,5,9-14 nohz=on nohz_full=1-3,5,9-14 intel_pstate=disable nosoftlockup

プロファイルは、tuned.conf[script] セクションで指定した script.sh シェルスクリプトを実行します。スクリプトは、sysfs 仮想ファイルシステムの以下のエントリーを調整します。

  • /sys/bus/workqueue/devices/writeback/cpumask
  • /sys/devices/system/machinecheck/machinecheck*/ignore_ce

上記の workqueue エントリーは分離された CPU マスクの逆に設定され、2 番目のエントリーはマシンのチェック例外を無効にします。

このスクリプトは、/etc/sysctl.conf ファイルに以下の変数も設定します。

kernel.hung_task_timeout_secs = 600
kernel.nmi_watchdog = 0
kernel.sched_rt_runtime_us = 1000000
vm.stat_interval = 10

このスクリプトは tuna インターフェースを使用して、分離された CPU 番号上のバインドされていないスレッドを分離された CPU から移動します。

さらにチューニングするには、デフォルトの /usr/lib/tuned/realtime/script.sh をコピーして変更してから、変更したスクリプトを指すように tuned.conf JSON ファイルを変更します。

17.5. CPU パフォーマンスの急増減

カーネルコマンドラインパラメーター skew_tick は、レイテンシーの影響を受けやすいアプリケーションが実行されている中規模から大規模のシステムで、ジッターをスムーズにする際に役立ちます。リアルタイム Linux システムでレイテンシーが急増する一般的なソースは、Linux カーネルタイマーティックハンドラーの共通のロックに複数の CPU が競合する場合です。競合の原因となる通常のロックは、xtime_lock (タイムキーピングシステムで使用) と、RCU (Read-Copy-Update) 構造ロックです。

skew_tick=1 ブートパラメーターを使用すると、これらのカーネルロックの競合が軽減されます。このパラメーターにより、CPU ごとのティックは、開始時間は「スキュー (skewed)」により同時に発生しません。CPU タイマーごとの開始時間を短縮すると、ロックの競合の可能性が低くなり、割り込み応答時間が短縮されます。

第18章 リアルタイム固有のチューニング

17章一般的なシステムチューニング で最適化が完了したら、Red Hat Enterprise Linux for Real Time 固有のチューニングを開始できます。この手順のために Red Hat Enterprise Linux for Real Time カーネルがインストールされている必要があります。

重要

このセクションのツールは、最初に 17章一般的なシステムチューニング を完了させてから使用するようにしてください。パフォーマンスは改善されません。

システムで調整を開始する準備ができたら、本章の他のセクションを試してください。

本章では、パフォーマンス監視ツールについても説明します。

本章のすべてのチューニングの提案が完了したら、19章アプリケーションのチューニングとデプロイメント に進みます。

18.1. Opteron CPU での TSC タイマーの同期

AMD64 Opteron プロセッサーの現行世代は、大きな gettimeofday スキューの影響を受けやすい可能性があります。このスキューは、cpufreq および Time Stamp Counter (TSC) の両方が使用されている場合に発生します。Red Hat Enterprise Linux for Real Time は、すべてのプロセッサーが同じ頻度に同時に変更することで、このスキューを防ぐ方法を提供します。そのため、1 つのプロセッサーの TSC は、別のプロセッサーの TSC とは異なる速度で増加することはありません。

TSC タイマー同期の有効化

  1. 任意のテキストエディターで /etc/default/grub ファイルを開き、パラメーター clocksource=tsc powernow-k8.tscsync=1GRUB_CMDLINE_LINUX 変数に追加します。これにより、TSC の使用が強制され、同時にコアプロセッサーの周波数遷移が有効になります。

    GRUB_CMDLINE_LINUX="rd.md=0 rd.lvm=0 rd.dm=0 $([ -x /usr/sbin/rhcrashkernel-param ] && /usr/sbin/rhcrashkernel-param || :) rd.luks=0 vconsole.keymap=us rhgb quiet clocksource=tsc powernow-k8.tscsync=1"
  2. 変更を有効にするには、システムを再起動する必要があります。
  • gettimeofday(2)

18.2. Infiniband

InfiniBand は多くの場合、帯域幅を高め、サービスやフェイルオーバーの品質を提供するために使用される通信アーキテクチャーのタイプです。Remote Direct Memory Access (RDMA) 機能によるレイテンシーを改善するためにも使用できます。

Red Hat Enterprise Linux for Real Time での Infiniband のサポートは、Red Hat Enterprise Linux 8 で提供されるサポートとは異なります。

注記

詳細は Infiniband のスタートガイド を参照してください。

18.3. RoCEE および高パフォーマンスのネットワーク

RoCEE (RDMA over Converged Enhanced Ethernet) は、10 ギガビットイーサネットネットワークを介した RDMA (Remote Direct Memory Access) を実装するプロトコルです。これにより、重要なトランザクションに対して確定的で低レイテンシーのデータトランスポートを提供する一方で、データセンターで一貫した高速環境を維持できます。

High Performance Networking (HPN) は、RoCEE インターフェースをカーネルに提供する共有ライブラリーセットです。HPN は、独立したネットワークインフラストラクチャーを使用する代わりに、標準の 10 ギガビットイーサネットインフラストラクチャーを使用してデータをリモートシステムメモリーに直接配置するため、CPU のオーバーヘッドが少なく、インフラストラクチャーコストが削減されます。

Red Hat Enterprise Linux for Real Time における RoCEE および HPN のサポートは、Red Hat Enterprise Linux 8 で提供されるサポートとは異なります。

注記

イーサネットネットワークを設定する方法は、ネットワークの設定および管理を参照してください。

18.4. 非非統合メモリーアクセス

NUMA (Non-Uniform Memory Access) は、メモリーリソースを特定の CPU に割り当てるために使用される設計です。これにより、アクセス時間を改善し、メモリーロックが少なくなる可能性があります。これは、レイテンシーを短縮するのに便利なように見えますが、NUMA システムは予期せぬイベントのレイテンシーを引き起こす可能性があるため、リアルタイムアプリケーションと適切に対話することが知られています。

taskset ユーティリティーは CPU のアフィニティーでのみ機能し、メモリーノードなどの他の NUMA リソースに関する知識はありません。NUMA と組み合わせてプロセスバインディングを実行する場合は、taskset の代わりに numactl コマンドを使用します。

NUMA API の詳細は、Andi Kleen のホワイトペーパー An NUMA API for Linux を参照してください。

  • numactl(8)

18.5. TCP の遅延 ACK タイムアウトの削減

RedHat EnterpriseLinux では、データの受信を確認するために TCP によって 2 つのモードが使用されます。

クイック ACK
  • このモードは TCP 接続の開始時に使用され、輻輳ウインドウがすぐに拡張できるようにします。
  • acknowledgment (ACK) のタイムアウト間隔 (ATO) が、最低限のタイムアウト値 tcp_ato_min に設定されています。
  • デフォルトの TCP ACK タイムアウト値を変更するには、必要な値をミリ秒単位で /proc/sys/net/ipv4/tcp_ato_min ファイルに書き込みます。

    ~]# echo 4 > /proc/sys/net/ipv4/tcp_ato_min
ACK の遅延
  • 接続が確立されると TCP は、複数の受信パケットの ACK を単一のパケットで送信できるこのモードを想定します。
  • ATO は tcp_delack_min に設定され、タイマーの再起動またはリセットを行います。
  • デフォルトの TCP Delayed ACK 値を変更するには、必要な値をミリ秒単位で /proc/sys/net/ipv4/tcp_delack_min ファイルに書き込みます。

    ~]# echo 4 > /proc/sys/net/ipv4/tcp_delack_min

現在の輻輳により、2 つのモード間で TCP が切り替えられます。

小規模なネットワークパケットを送信するアプリケーションの中には、TCP が迅速かつ遅延した承認のタイムアウト (以前はデフォルトで 40 ミリ秒) により、レイテンシーが発生する可能性があります。つまり、まれな情報をネットワーク経由で送信するアプリケーションからのパケットの小さいパケットは、パケットが別の側で受信されたことを認識するために最長 40 ミリ秒の遅延が生じる可能性があります。この問題を最小限にするために、tcp_ato_mintcp_delack_min の両方のタイムアウトは、デフォルトで 4 ミリ秒になりました。

これらのデフォルト値は tunable で、上記のようにユーザーの環境のニーズに応じて調整できます。

注記

低すぎる、または高すぎるタイムアウト値を使用すると、アプリケーションが経験したネットワークのスループットとレイテンシーに悪影響を及ぼす可能性があります。異なる環境では、これらのタイムアウトに異なる設定が必要になる場合があります。

18.6. debugfs ファイルシステムの使用

debugfs ファイルシステムは、デバッグしてユーザーが情報を利用できるようにするために特別に設計されています。これは ftracetrace-cmd で使用するようにマウントする必要があり、RHEL 8 では /sys/kernel/debug/ ディレクトリーの下に自動的にマウントされます。

以下のコマンドを実行して、debugfs がマウントされていることを確認できます。

~]# mount | grep ^debugfs

18.7. ftrace ユーティリティーを使用したレイテンシーの追跡

Red Hat Enterprise Linux for Real Time カーネルで提供される診断機能の 1 つは ftrace です。これは、ユーザー空間外で発生するレイテンシーおよびパフォーマンスの問題を分析し、デバッグするために、開発者によって使用されます。この ftrace ユーティリティーには、さまざまな方法でユーティリティーを使用できるさまざまなオプションがあります。これは、コンテキストスイッチの追跡、優先順位の高いタスクでのウェイクアップにかかる時間の測定、割り込みが無効になっている期間の測定、特定の期間中に実行されたカーネル関数の一覧の表示に使用できます。

関数トレーサーなどの一部のトレーサーは、大量のデータ量を生成し、トレースログ分析を時間の消費タスクに切り替えます。ただし、トレーサーに対し、アプリケーションが重要なコードパスに到達した場合にのみ開始および終了するように指示することが可能です。

この ftrace ユーティリティーは、Red Hat Enterprise Linux for Real Time カーネルの trace バリアントがインストールされ、使用されると、セットアップすることができます。

ftrace ユーティリティーの使用

  1. /sys/kernel/debug/tracing/ ディレクトリーには、available_tracers という名前のファイルがあります。このファイルには、ftrace が使用できるすべてのトレーサーが含まれます。利用可能なトレーサーの一覧を表示するには、cat コマンドを使用してファイルの内容を表示します。

    ~]# cat /sys/kernel/debug/tracing/available_tracers
    function_graph wakeup_rt wakeup preemptirqsoff preemptoff irqsoff function nop

    ftrace のユーザーインターフェースは、debugfs 内の一連のファイルです。ftrace ファイルは、/sys/kernel/debug/tracing/ ディレクトリーにあります。以下を入力します。

    ~]# cd /sys/kernel/debug/tracing

    トレースを有効にするとシステムのパフォーマンスに影響を及ぼす可能性があるため、このディレクトリーのファイルを変更することができるのは root ユーザーのみです。

    ftrace ファイル

    このディレクトリー内のメインファイルは、以下のとおりです。

    trace
    ftrace トレースの出力を表示するファイル。これは、このファイルが読み込まれ、イベント読み取りを消費しないため、トレースを停止するため、実際にはトレースのスナップショットです。これは、ユーザーがトレースを無効にしてこのファイルを読み取ると、読み取り時に毎回同じ内容を報告します。
    trace_pipe
    「trace」と似ていますが、トレースをライブで読み込むために使用されます。プロデューサー/コンシューマートレースで、各読み取りが読み取られるイベントを消費します。ただし、これにより、トレースが読み取られることなく、アクティブなトレースを確認することができます。
    available_tracers
    カーネルにコンパイルされた ftrace トレーサーの一覧。
    current_tracer
    ftrace トレーサーを有効または無効にします。
    events
    トレースするイベントが含まれ、イベントを有効または無効にするのに使用できるディレクトリーと、イベントのフィルターの設定を行うことができます。
    tracing_on

    ftrace バッファーへの録画を無効および有効にします。tracing_on ファイル経由でトレースを無効にしても、カーネル内で行われている実際のトレースは無効になりません。バッファーへの書き込みのみを無効にします。トレースを実行する作業は継続されますが、データはどこにも移動しません。

    トレーサー

    カーネルの設定方法によっては、指定のカーネルですべてのトレーサーが利用できるとは限りません。Red Hat Enterprise Linux for Real Time カーネルの場合、トレースカーネルとデバッグカーネルは、実稼働用のカーネルとは異なるトレーサーを持ちます。これは、トレーサーの一部にトレーサーがカーネルに設定され、アクティブではない場合に大きなオーバーヘッドが発生するためです。このトレーサーは、トレースおよびデバッグカーネルに対してのみ有効になります。

    function
    最も広く適用されるトレーサーの 1 つ。カーネル内の関数呼び出しを追跡します。トレースされた関数の数によっては、認識可能なオーバーヘッドが発生する可能性があります。アクティブでない場合にオーバーヘッドがほとんど作成されます。
    function_graph

    function_graph トレーサーは、より視覚に訴える形式で結果を表示するように設計されています。このトレーサーは、関数の終了を追跡し、カーネル内の関数呼び出しのフローを表示します。

    このトレーサーは、有効化されると function トレーサーよりもオーバーヘッドが高くなりますが、無効化されると同じオーバーヘッドが低くなることに注意してください。

    wakeup
    すべての CPU でアクティビティーが発生することを報告する完全な CPU トレーサー。リアルタイムタスクであるかに関わらず、システム内で最も優先度の高いタスクを起動するのにかかる時間を記録します。非リアルタイムタスクを起動するのにかかる最大時間の記録では、リアルタイムタスクを起動するのにかかる時間が非表示になります。
    wakeup_rt
    すべての CPU でアクティビティーが発生することを報告する完全な CPU トレーサー。現在の最も高い優先度タスクから、ウェイクアップ時間まで経過時間を記録します。リアルタイムタスクの時間を記録します。
    preemptirqsoff
    プリエンプションまたは割り込みを無効にするエリアを追跡し、プリエンプションまたは割り込みが無効となった最大時間を記録します。
    preemptoff
    preemptirqsoff トレーサーと似ていますが、プリエンプションが無効化された最大間隔のみをトレースします。
    irqsoff
    preemptirqsoff トレーサーと似ていますが、割り込みが無効化された最大間隔のみをトレースします。
    nop
    デフォルトのトレーサー。トレース機能自体は提供しませんが、イベントがトレーサーにインターリーブする可能性があるため、nop トレーサーは、イベントのトレースに特に関心がある場合に使用されます。
  2. トレースセッションを手動で開始するには、最初に available_tracers のリストから使用するトレーサーを選択してから、echo コマンドを使用してトレーサーの名前を /sys/kernel/debug/tracing/current_tracer に挿入します。

    ~]# echo preemptoff > /sys/kernel/debug/tracing/current_tracer
  3. function および function_graph トレースが有効になっているかどうかを確認するには、cat コマンドを使用して /sys/kernel/debug/tracing/options/function-trace ファイルを表示します。値が 1 の場合は、これが有効であることを示し、0 は無効であることを示します。

    ~]# cat /sys/kernel/debug/tracing/options/function-trace
    1

    デフォルトでは、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>, and 2> (空白文字なし) を使用するシェルプロンプトでは、標準入力、標準出力、および標準エラーを参照します。誤ってそれらを使用すると、トレースが予期せぬ出力になる可能性があります。

    function-trace オプションは、wakeup_rtpreemptirqsoff などを使用してレイテンシーをトレースすると、関数のトレースが自動的に有効になり、オーバーヘッドが誇張される可能性があるため便利です。

  4. /debugfs/tracing/ ディレクトリー内のさまざまなファイルの値を変更して、トレーサーの詳細とパラメーターを調整します。以下に例を示します。

    irqsoff、preemptoff、preempirqsoff、および wakeup トレーサーは、レイテンシーを継続的に監視します。tracing_max_latency に記録されたレイテンシーよりも大きいレイテンシーを記録すると、そのレイテンシーのトレースが記録され、tracing_max_latency が新しい最大時間に更新されます。これにより、tracing_max_latency は、最後にリセットされてから記録された最大のレイテンシーを常に表示します。

    最大レイテンシーをリセットするには、0tracing_max_latency ファイルに echo します。設定された量よりも大きいレイテンシーのみを表示するには、マイクロ秒単位で量を echo します。

    ~]# echo 0 > /sys/kernel/debug/tracing/tracing_max_latency

    トレースのしきい値を設定すると、最大レイテンシー設定が上書きされます。しきい値より大きいレイテンシーが記録されると、最大レイテンシーに関係なく記録されます。トレースファイルを確認すると、最後に記録されたレイテンシーのみが表示されます。

    しきい値を設定するには、それを超えるとレイテンシーを記録する必要があるマイクロ秒数をecho します。

    ~]# echo 200 > /sys/kernel/debug/tracing/tracing_thresh
  5. トレースログを表示します。

    ~]# cat /sys/kernel/debug/tracing/trace
  6. トレースログを保存するには、別のファイルにコピーします。

    ~]# cat /sys/kernel/debug/tracing/trace > /tmp/lat_trace_log
  7. 関数のトレースは、/sys/kernel/debug/tracing/set_ftrace_filter ファイルの設定を変更してフィルターできます。ファイルにフィルターが指定されていない場合、すべての関数がトレースされます。cat を使用して、現在のフィルターを表示します。

    ~]# cat /sys/kernel/debug/tracing/set_ftrace_filter
  8. フィルターを変更するには、トレースする関数の名前を echo します。このフィルターでは、検索用語の先頭または末尾に * ワイルドカードを使用できます。

    * ワイルドカードは、単語の先頭 および 末尾の両方で使用することもできます。たとえば、\*irq\* は、名前に irq を含むすべての関数を選択します。ただし、ワイルドカードは単語内で使用できません。

    検索用語とワイルドカード文字を二重引用符で囲むと、シェルが検索を現在の作業ディレクトリーに拡張しないようにします。

    フィルターの例を以下に示します。

    • schedule 関数のみをトレースします。

      ~]# echo schedule > /sys/kernel/debug/tracing/set_ftrace_filter
    • lock で終わるすべての関数をトレースします。

      ~]# echo "*lock" > /sys/kernel/debug/tracing/set_ftrace_filter
    • spin_ で始まるすべての関数をトレースします。

      ~]# echo "spin_*" > /sys/kernel/debug/tracing/set_ftrace_filter
    • 名前に cpu のあるすべての関数をトレースします。

      ~]# echo "cpu" > /sys/kernel/debug/tracing/set_ftrace_filter
      注記

      echo コマンドとともに単一の > を使用する場合は、ファイル内の既存の値が上書きされます。ファイルに値を追加する場合は、代わりに>> を使用します。

18.8. trace-cmd ユーティリティーを使用したレイテンシートレース

trace-cmd は、ftrace へのフロントエンドツールです。/sys/kernel/debug/tracing/ ディレクトリーに書き込む必要なしに、前述の ftrace インタラクションを有効にできます。これは、特別なトレースカーネルバリアントなしでインストールでき、インストール時にはオーバーヘッドは追加されません。

  1. trace-cmd ツールをインストールするには、root として以下のコマンドを入力します。

    ~]# yum install trace-cmd
  2. ユーティリティーを起動するには、以下の構文を使用して、シェルプロンプトで必要なオプションとともに trace-cmd と入力します。

    ~]# trace-cmd command

    コマンドの例を以下に示します。

    • myapp の実行中に、カーネル内で実行中の録画機能を有効にして開始します。

      ~]# trace-cmd record -p function myapp

      これは、myapp に無関係なタスクであっても、すべての CPU およびすべてのタスクの関数を記録します。

    • 結果を表示します。

      ~]# trace-cmd report
    • myapp の実行中に、sched で開始する関数のみを記録します。

      ~]# trace-cmd record -p function -l 'sched*' myapp
    • すべての IRQ イベントを有効にします。

      ~]# trace-cmd start -e irq
    • wakeup_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 function で再度有効にできます。

    • trace-cmd がシステムの変更を開始する前のシステムの状態を復元します。

      ~]# trace-cmd start -p nop

      これは、trace-cmd を使用した後に debugfs ファイルシステムを使用する場合、その間にシステムが再起動されたかどうかに関係なく重要です。

      注記

      コマンドおよびオプションの完全なリストは、man ページの trace-cmd(1) を参照してください。すべての個々のコマンドには、独自の man ページ trace-cmd-コマンド もあります。

  3. この例では、trace-cmd ユーティリティーは単一のトレースポイントをトレースします。

    ~]# trace-cmd record -e sched_wakeup ls /bin

18.9. sched_nr_migrate 変数を使用して SCHED_OTHER タスクの移行を制限します。

SCHED_OTHER タスクが他の多数のタスクを生成する場合、それらはすべて同じ CPU 上で実行されます。移行タスクまたは softirq は、アイドル状態の CPU で実行できるように、これらのタスクのバランスをとろうとします。sched_nr_migrate オプションを設定して、一度に移動するタスクの数を指定できます。リアルタイムタスクは移行方法が異なるため、これによる直接の影響は受けませんが、softirq がタスクを移動すると、割り込みを無効にするために必要な実行キューのスピンロックがロックされます。移動が必要なタスクが多数ある場合は、割り込みが無効になっているときに発生するため、タイマーイベントやウェイクアップは同時に行われません。これにより、sched_nr_migrate が大きい値に設定されると、リアルタイムタスクに深刻なレイテンシーが生じることがあります。

sched_nr_migrate 変数の値の調整

  1. sched_nr_migrate 変数を増やすと、リアルタイムレイテンシーを犠牲にして、多くのタスクを生成する SCHED_OTHER スレッドから高いパフォーマンスが得られます。SCHED_OTHER タスクパフォーマンスを犠牲にしてリアルタイムのタスクレイテンシーを低くするには、値を下げる必要があります。デフォルト値は 8 です。
  2. sched_nr_migrate 変数の値を調整するには、/proc/sys/kernel/sched_nr_migrate に値を直接 echo できます。

    ~]# echo 2 > /proc/sys/kernel/sched_nr_migrate

18.10. リアルタイムのスロットリング

リアルタイムスケジューリングの問題

Red Hat Enterprise Linux for Real Time の 2 つのリアルタイムスケジューリングポリシーには、主要な特性が 1 つあります。これらは、優先度の高いスレッドによってプリエンプティブされるか、スリープまたは I/O を実行することによって「待機」するまで、実行される特性です。SCHED_RR の場合、同等の SCHED_RR 優先度の別のスレッドを実行できるように、スレッドがオペレーティングシステムによってプリエンプティブされる可能性があります。このようないずれの場合も、POSIX 仕様では、優先度の低いスレッドが CPU 時間を取得できるようにするポリシーを定義するプロビジョニングはありません。

リアルタイムスレッドのこの特性は、特定の CPU の 100% を独占するアプリケーションの作成が非常に簡単であることを意味します。一見、これは良い考えであるように見えますが、実際にはオペレーティングシステムに多くの問題を引き起こします。OS は、システム全体のリソースと CPU ごとのリソースを管理し、定期的にこれらのリソースを記述するデータ構造を調べ、ハウスキーピングアクティビティーを実行する必要があります。コアが SCHED_FIFO スレッドにより独占されている場合、コアはハウスキーピングタスクを実行できず、最終的にシステム全体が不安定になり、クラッシュを引き起こす可能性があります。

Red Hat Enterprise Linux for Real Time カーネルでは、割り込みハンドラーは SCHED_FIFO 優先度のスレッド (デフォルト: 50) として実行されます。割り込みハンドラースレッドよりも高い SCHED_FIFO または SCHED_RR ポリシーを持つ cpu-hog スレッドは、割り込みハンドラーの実行を妨ぎ、それらの割り込みによって通知されたデータを待機しているプログラムが不足して失敗する原因となる可能性があります。

リアルタイムスケジューラーのスロットリング

Red Hat Enterprise Linux for Real Time には、システム管理者がリアルタイムタスクで使用できる帯域幅を割り当てる安全なメカニズムが含まれています。このセーフガードメカニズムは、real-time scheduler throttling と呼ばれており /proc ファイルシステムの 2 つのパラメーターで制御されます。

/proc/sys/kernel/sched_rt_period_us
CPU 帯域幅の 100% と見なされる μ (マイクロ秒) の期間を定義します。デフォルト値は、1,000,000 μs (1 秒)です。期間の値の変更は、期間が長すぎるか、または小さすぎると、非常に大きな影響を及ぼす必要があります。
/proc/sys/kernel/sched_rt_runtime_us
すべてのリアルタイムタスクで利用可能な合計帯域幅。デフォルト値は 950,000 μs (0.95 秒)、つまり CPU 帯域幅の 95% です。値を -1 に設定すると、リアルタイムタスクで CPU 時刻が 100% になる可能性があることを意味します。これは、リアルタイムタスクが良好で、無制限のポーリングループなどの明確な注意がない場合にのみ適切です。

リアルタイムスロットリングメカニズムのデフォルト値は、リアルタイムタスクで使用 できる CPU 時間の 95% を定義します。残りの 5% はリアルタイム以外のタスク (SCHED_OTHER および同様のスケジューリングポリシーで実行されるタスク) に割り当てられます。1 つのリアルタイムタスクが CPU タイムスロットの 95% を占有している場合、その CPU 上の残りのリアルタイムタスクは実行されないことに注意してください。CPU 時間の残りの 5% は、リアルタイム以外のタスクでのみ使用されます。

デフォルト値の影響は 2 倍です。リアルタイム以外のタスクの実行を許可しないことで、不正なリアルタイムタスクがシステムをロックしません。一方、リアルタイムタスクには最大 95% の CPU 時間がパフォーマンスに影響する可能性があります。

RT_RUNTIME_GREED 機能

Real Time スロットリングメカニズムは、システムをハングさせるリアルタイムタスクを回避するために機能しますが、上級ユーザーは、リアルタイム以外のタスクでリソースが不足していなくてもリアルタイムタスクを継続できるようにしたいかもしれません。つまり、システムがアイドル状態になるのを回避することも可能です。

有効にすると、リアルタイムタスクがスロットリングされる前にリアルタイム以外のタスクが枯渇しているかどうかを確認します。リアルタイムタスクがスロットリングされた場合は、システムがアイドル状態になった時点、または次の期間が開始される時点ですぐにスロットリングが解除されます。

以下のコマンドで RT_RUNTIME_GREED を有効にします。

# echo RT_RUNTIME_GREED > /sys/kernel/debug/sched_features

すべての CPU を同じ rt_runtime で保つには、NO_RT_RUNTIME_SHARE ロジックを無効にします。

# echo NO_RT_RUNTIME_SHARE > /sys/kernel/debug/sched_features

上記 2 つのオプションを設定すると、リアルタイムタスクをできる限り実行しつつ、すべての CPU の非 rt-task に対してランタイムを保証します。

参考資料

kernel-rt-doc パッケージで入手可能なカーネルドキュメントから、以下を行います。

  • /usr/share/doc/kernel-rt-doc-3.10.0/Documentation/scheduler/sched-rt-group.txt

18.11. tuned-profiles-realtime を使用した CPU の分離

アプリケーションスレッドに可能な限り長い実行時間を割り当てるには、CPU を分離します。つまり、CPU からできるだけ多くの余分なタスクを削除することになります。通常、CPU の分離には、以下が関係します。

  • ユーザー空間スレッドをすべて削除
  • バインドされていないカーネルスレッドの削除 (バインドされたカーネルスレッドは特定の CPU に関連付けられ、移動できない)
  • システム内の各 Interrupt Request (IRQ) 番号 N/proc/irq/N/smp_affinity プロパティーを変更して割り込みを削除します。

このセクションでは、tuned-profiles-realtime パッケージの isolated_cores=cpulist 設定オプションを使用して、これらの操作を自動化する方法を示します。

分離する CPU の選択

分離する CPU を選択するには、システムの CPU トポロジーを慎重に検討する必要があります。ユースケースによっては、異なる設定が必要になる場合があります。

  • スレッドがキャッシュを共有して相互に通信する必要があるマルチスレッドアプリケーションがある場合、同じ NUMA ノードまたは物理ソケットでスレッドを保持する必要がある場合があります。
  • 関連のない複数の real-time アプリケーションを実行すると、NUMA ノードまたはソケットごとに CPU を分離することができます。

hwloc パッケージは、lstopo-no-graphics および numactlなどの CPU に関する情報を取得する際に便利なコマンドを提供します。

  • 物理パッケージで利用可能な CPU のレイアウトを表示するには、lstopo-no-graphics --no-io --no-legend --of txt コマンドを使用します。

    図18.1 lstopo-no-graphics を使用した CPU のレイアウトの表示

    lstopo no graphics output

    上記のコマンドは、利用可能なコアとソケットの数と NUMA ノードの論理距離を表示するため、マルチスレッドアプリケーションに役立ちます。

    さらに、hwloc-gui パッケージは、グラフィカル出力を生成する lstopo コマンドを提供します。

  • ノード間の距離など、CPU に関する詳細は、numactl --hardware コマンドを使用します。

    ~]# 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

hwloc パッケージが提供するユーティリティーの詳細は、hwloc(7) の man ページを参照してください。

tuned の isolated_cores オプションを使用した CPU の分離

CPU を分離する最初のメカニズムは、カーネルブートコマンドラインの isolcpus=cpulist ブートパラメーターを指定することです。Red Hat Enterprise Linux for Real Time でこれを行うための推奨される方法は、tuned デーモンとその tuned-profiles-realtime パッケージを使用することです。

isolcpus ブートパラメーターを指定するには、以下の手順に従います。

  1. tuned パッケージおよび tuned-profiles-realtime パッケージをインストールします。

    ~]# yum install tuned tuned-profiles-realtime
  2. ファイル /etc/tuned/realtime-variables.conf で、設定オプション isolated_cores=cpulist を設定します。ここで、cpulist は、分離する CPU のリストです。この一覧はコンマで区切られ、CPU 番号または範囲を 1 つ含めることができます。以下に例を示します。

    isolated_cores=0-3,5,7

    上記の行では、CPU 0、1、1、2、3、5、および 7 を分離します。

    例18.1 通信スレッドでの CPU の分離

    8 コアを持つ 2 つのソケットシステムでは、NUMA ノードのゼロにはコア 0-3 と NUMA ノード 1 のコア 4-8 があり、マルチスレッドアプリケーション用に 2 つのコアを割り当てる場合は、以下の行を追加します。

    isolated_cores=4,5

    tuned-profiles-realtime プロファイルがアクティブ化されると、isolcpus=4,5 パラメーターが起動コマンドラインに追加されます。これにより、ユーザー空間スレッドが CPU 4 および 5 に割り当てられなくなります。

    例18.2 通信していないスレッドでの CPU の分離

    関係のないアプリケーションの別の NUMA ノードから CPU を選択する場合は、以下を指定できます。

    isolated_cores=0,4

    これにより、ユーザー空間スレッドが CPU 0 および 4 に割り当てられるのを防ぎます。

  3. tuned-adm ユーティリティーを使用して tuned プロファイルをアクティベートしてから、再起動します。

    ~]# tuned-adm profile realtime
    ~]# reboot
  4. 再起動時に、ブートコマンドラインで isolcpus パラメーターを検索して、選択した CPU が分離されていることを確認します。

    ~]$ cat /proc/cmdline | grep isolcpus
    BOOT_IMAGE=/vmlinuz-3.10.0-394.rt56.276.el7.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

nohz パラメーターおよび nohz_full パラメーターを使用した CPU の分離

nohz および nohz_full カーネルブートパラメーターを有効にするには、realtime-virtual-hostrealtime-virtual-guest、または cpu-partitioning のいずれかのプロファイルを使用する必要があります。

nohz=on
特定の CPU セットのタイマーアクティビティーを減らすために使用できます。nohz パラメーターは、主にアイドル状態の CPU におけるタイマー割り込みを減らすために使用されます。これにより、アイドル状態の CPU を低電力モードで実行させることにより、バッテリーのライフサイクルが容易になります。リアルタイムの応答時間には直接有用ではありませんが、nohz パラメーターは直接、リアルタイムの応答時間を下回ることはありません。また、リアルタイムパフォーマンスに肯定的な意味を 持つ 次のパラメーターをアクティブ化する必要があります。
nohz_full=cpulist
nohz_full パラメーターは、タイマーティックに関して CPU の一覧を異なる方法で処理するために使用されます。CPU が nohz_full CPU として一覧表示され、CPU に実行可能なタスクが 1 つしかない場合、カーネルはその CPU へのタイマーティックの送信を停止するため、アプリケーションの実行に費やす時間が少なくなり、割り込みとコンテキストの切り替えに費やされた時間が短縮されます。

これらのパラメーターに関する詳細は、「Configuring kernel tick time」を参照してください。

18.12. RCU コールバックのオフロード

Read-Copy-Update (RCU) システムは、カーネル内で相互に除外されるロックレスメカニズムです。RCU 操作を実施することで、メモリーを安全に削除する際に、将来実行される CPU にコールバックがキューに置かれることがあります。

RCU コールバックは、rcu_nocbs および rcu_nocb_poll カーネルパラメーターを使用してオフロードが可能です。

  • RCU コールバックを実行する候補から 1 つ以上の CPU を削除するには、rcu_nocbs カーネルパラメーターの CPU の一覧を指定します。以下に例を示します。

    rcu_nocbs=1,4-6

    または

    rcu_nocbs=3

    2 つ目の例では、CPU 3 が no-callback CPU であることをカーネルに指示します。つまり、RCU コールバックは CPU 3 に固定された rcuc/$CPU スレッドではなく、ハウスキーピング CPU に移動できる rcuo/$CPU スレッドで実行され、CPU 3 が RCU コールバックジョブを実行することを防ぎます。

    RCU コールバックスレッドをハウスキーピング CPU に移動するには、tuna -t rcu* -c X -m コマンドを使用します。ここで、X はハウスキーピング CPU を示しています。たとえば、CPU 0 がハウスキーピング CPU のシステムでは、以下のコマンドを使用してすべての RCU コールバックスレッドを CPU 0 に移動できます。

    ~]# tuna -t rcu* -c 0 -m

    これは、CPU 0 以外のすべての CPU が RCU の動作に依存します。

  • RCU オフロードスレッドは別の CPU で RCU コールバックを実行できますが、各 CPU は対応する RCU オフロードスレッドを実行します。RCU オフロードスレッドを発生させる責任から各 CPU を解放するには、rcu_nocb_poll カーネルパラメーターを設定します。

    rcu_nocb_poll

    rcu_nocb_poll を設定すると、実行するコールバックがあるかどうかを確認するために、タイマーによって RCU オフロードスレッドが定期的に発生します。

以下の 2 つのオプションに対する一般的なユースケースは以下のとおりです。

  1. rcu_nocbs=cpulist を使用して、すべての RCU オフロードスレッドをハウスキーピング CPU に移動できるようにします。
  2. rcu_nocb_poll を設定して、RCU オフロードスレッドを発生させる責任から各 CPU を解放します。

この組み合わせにより、ユーザーのワークロードに特化した CPU への干渉が軽減されます。

リアルタイムでの RCU チューニングの詳細は、Avoiding RCU Stalls in the real-time kernel を参照してください。

第19章 アプリケーションのチューニングとデプロイメント

本章では、Red Hat Enterprise Linux for Real Time アプリケーションを拡張し、開発するためのヒントを紹介します。

注記

通常、POSIX (Portable Operating System Interface) の定義 API の使用を試みます。Red Hat Enterprise Linux for Real Time は POSIX 標準に準拠しており、Red Hat Enterprise Linux for Real Time カーネルにおけるレイテンシーの軽減も POSIX に基づいています。

関連資料

独自の Red Hat Enterprise Linux for Real Time アプリケーションの開発に関する詳細をお読みいただくには、RTW の記事をお読みください。

19.1. リアルタイムアプリケーションでのシグナル処理

従来の UNIX および POSIX シグナルには、特にエラー処理に使用されますが、リアルタイムアプリケーションでイベント配信メカニズムとしての使用には適していません。これは、レガシー動作やサポートが必要な API の複数であるため、現在の Linux カーネルシグナル処理コードは非常に複雑です。この複雑さは、シグナルの配信時に取得されるコードパスが常に最適とは限らず、アプリケーションで非常に長いレイテンシーが発生する可能性があることを意味します。

UNIX シグナルの元の目的は、実行の異なるスレッド間の 1 つの制御スレッド (プロセス) を多重化することでした。シグナルはオペレーティングシステムの割り込みのように動作します。シグナルがアプリケーションに配信されると、アプリケーションのコンテキストが保存され、以前に登録されたシグナルハンドラーの実行が開始します。シグナルハンドラーが完了すると、アプリケーションはシグナルの配信時の場所に戻ります。これにより、実際には複雑になる可能性があります。

シグナルは、リアルタイムアプリケーションで信頼するには非決定論ではありません。POSIX スレッド (pthreads) を使用してワークロードを分散し、さまざまなコンポーネント間の通信を行うことが望ましいオプションです。mutex、条件変数、バリアの pthreads メカニズムを使用してスレッドのグループは調整でき、比較的新しいコンストラクトを経由したコードパスが、シグナルのレガシー処理コードよりもはるかにクリーンであることを確認できます。

関連資料

詳細は、以下のリンクは本セクションに記載の情報に関連しています。

RTWiki の Build an RT Application

Ulrich 開発者の Requirements of the POSIX Signal Model)

19.2. sched_yield およびその他の同期メカニズムの使用

sched_yield システムコールは、スレッドによって使用され、他のスレッドに実行するチャンスを与えます。多くの場合、sched_yield を使用すると、スレッドは実行キューの最後に移動して再スケジュールに時間がかかる場合があります。または、すぐに再スケジュールして CPU にビジーループを作成する場合もあります。スケジューラーは、実際に実行したい他のスレッドがあるかどうかを判別できます。RT タスクでは sched_yield を使用しないでください。

詳細は、Earthquaky kernel interfaces の Armaldo Caralho de Melo の記事を参照してください。

  • pthread.h(P)
  • sched_yield(2)
  • sched_yield(3p)

19.3. mutex オプション

標準のミューテックス作成

相互除外 (mutex) アルゴリズムは、共通のリソースを使用するプロセスを同時に防ぎます。高速ユーザー空間ミューテックス (futex) は、mutex が別のスレッドによって保持されていない場合に、ユーザー空間スレッドがカーネル領域にコンテキストスイッチを必要とせずに mutex を要求することを可能にするツールです。

注記

本書では、POSIX スレッド (pthread) mutex コンストラクトを記述するために、futex と mutex という用語を使用します。

  1. 標準属性で pthread_mutex_t オブジェクトを初期化すると、プライベートで再帰的ではなく、堅牢ではない優先度継承対応ではないミューテックスが作成されます。
  2. pthreads の下で、ミューテックスは以下の文字列で初期化できます。

    pthread_mutex_t my_mutex;
    
    pthread_mutex_init &my_mutex; NULL;
  3. この場合、アプリケーションは pthreads API および Red Hat Enterprise Linux for Real Time カーネルが提供する利点はありません。アプリケーションの書き込みまたはポート時に考慮する必要のある mutex オプションは複数あります。

高度なミューテックスオプション

ミューテックスの追加機能を定義するには、pthread_mutexattr_t オブジェクトを作成する必要があります。このオブジェクトは、futex の定義済み属性を保存します。

重要

この例では、関数の戻り値の確認は含まれません。これは基本的な安全手順で、常に実行する必要があります。

  1. mutex オブジェクトを作成します。

    pthread_mutex_t my_mutex;
    
    pthread_mutexattr_t (my_mutex_attr);
    
    pthread_mutexattr_init &my_mutex_attr;
  2. 共有およびプライベートのミューテックス:

    共有ミューテックスはプロセス間で使用できますが、オーバーヘッドを大きくすることができます。

    pthread_mutexattr_setpshared &my_mutex_attr, PTHREAD_PROCESS_SHARED;
  3. リアルタイム優先度の継承:

    優先度の反転の問題は、優先度継承を使用して回避できます。

    pthread_mutexattr_setprotocol &my_mutex_attr, PTHREAD_PRIO_INHERIT;
  4. 強固なミューテックス:

    所有者の終了時には堅牢なミューテックがリリースされますが、オーバーヘッドのコストも高くなる場合があります。この文字列の _NP は、このオプションが非 POSIX であるか、移植性がないことを示します。

    pthread_mutexattr_setrobust_np &my_mutex_attr, PTHREAD_MUTEX_ROBUST_NP;
  5. mutex の初期化:

    属性が設定されたら、これらのプロパティーを使用して mutex を初期化します。

    pthread_mutex_init &my_mutex, &my_mutex_attr;
  6. attributes オブジェクトをクリーンアップします。

    mutex を作成したら、属性オブジェクトを保持して同じタイプのミューテックスを初期化したり、クリーンアップしたりできます。mutex はいずれの場合も影響を受けません。属性オブジェクトをクリーンアップするには、_destroy コマンドを使用します。

    pthread_mutexattr_destroy &my_mutex_attr;

    ミューテックスは通常の pthread_mutex として動作するようになり、通常どおりにロック、ロック解除、破棄できます。

  • futex(7)
  • pthread_mutex_destroy(P)

    pthread_mutex_t および pthread_mutex_init に関する詳細

  • pthread_mutexattr_setprotocol(3p)

    pthread_mutexattr_setprotocol および pthread_mutexattr_getprotocol に関する詳細

  • pthread_mutexattr_setprioceiling(3p)

    pthread_mutexattr_setprioceiling および pthread_mutexattr_getprioceiling に関する詳細

19.4. TCP_NODELAY および小さなバッファー書き込み

TCP (Transmission Control Protocol) で簡単に説明しているように、デフォルトでは、TCP は Nagle のアルゴリズムを使用して小さな送信パケットを収集し、すべてを一度に送信します。レイテンシーに悪影響を与える可能性があります。

TCP_NODELAY および TCP_CORK を使用したネットワークレイテンシーの改善

  1. 送信されるすべてのパケットでより低いレイテンシーを必要とするアプリケーションは、TCP_NODELAY を有効化しているソケットで実行する必要があります。ソケット API を使用して setsockopt コマンドで有効にできます。

    # int one = 1;
    
    # setsockopt(descriptor, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
  2. これを効果的に使用するには、アプリケーションは、小規模で論理的に関連するバッファー書き込みを実行しないようにする必要があります。TCP_NODELAY が有効であるため、これらの小さな書き込みにより、TCP はこれらの複数のバッファーを個別のパケットとして送信し、これにより、全体的なパフォーマンスが低下する可能性があります。

    アプリケーションに論理的に関連する複数のバッファーがあり、これらが 1 つのパケットとして送信される場合は、メモリー内に連続したパケットを作成してから、TCP_NODELAY で設定されたソケット上の TCP に論理パケットを送信することができます。

    または、I/O ベクトルを作成し、TCP_NODELAY で設定されたソケット上で writev を使用してカーネルに渡します。

  3. もう 1 つのオプションは、TCP_CORK を使用することです。これは、パケットを送信する前に、アプリケーションがコルクを削除するのを待つように TCP に指示します。このコマンドにより、受信するバッファーが既存のバッファーに追加されます。これにより、アプリケーションはカーネル領域にパケットを構築できます。これは、レイヤーの抽象化を提供する異なるライブラリーを使用する場合は必要です。TCP_CORK を有効にするには、setsockopt ソケット API (これは「corking the socket」と呼ばれる) を使用して、これを 1 の値に設定します。

    # int one = 1;
    
    # setsockopt(descriptor, SOL_TCP, TCP_CORK, &one, sizeof(one));
  4. アプリケーションの各種コンポーネントで論理パケットがカーネルにビルドされたら、コードを削除するように TCP に指示します。TCP は、アプリケーションからのパケットをこれ以上待たずに、累積された論理パケットをすぐに送信します。

    # int zero = 0;
    
    # setsockopt(descriptor, SOL_TCP, TCP_CORK, &zero, sizeof(zero));
  • tcp(7)
  • setsockopt(3p)
  • setsockopt(2)

19.5. リアルタイムスケジューラーの優先度の設定

systemd を使用して、スケジューラーの優先度を設定することは、「ブート時のサービス優先度の決定」を参照してください。この例では、一部のカーネルスレッドに非常に高い優先順位が付与されている可能性があります。これは、デフォルトの優先度が Real Time Specification for Java (RTSJ) の要件と適切に統合されるようにします。RTSJ には 10 から 89 までの優先度の範囲が必要です。

RTSJ が使用されていないデプロイメントでは、アプリケーションの破棄段階である 90 未満のスケジューリングの優先度が多数あります。通常、この機能が存在するにも関わらず、ユーザーレベルのアプリケーションは優先度 50 以上で実行されることは危険です。必須のシステムサービスが実行されないようにすると、ファイルシステムジャーナリングがブロックされるため、ネットワークトラフィックのブロック、仮想メモリーページングのブロック、データ破損など、予測できない動作が発生する可能性があります。

優先度 49 を超えるアプリケーションスレッドをスケジュールする場合は、細心の注意を払ってください。アプリケーションスレッドが優先度 89 を超えてスケジュールされている場合は、スレッドが非常に短いコードパスのみを実行するようにしてください。これに失敗すると、Red Hat Enterprise Linux for Real Time カーネルのレイテンシーが低くなります。

非特権ユーザーのリアルタイム優先度の設定

一般的には、root ユーザーのみが優先順位やスケジューリングの情報を変更できます。非特権ユーザーがこれらの設定を調整できるようにする必要がある場合は、ユーザーを realtime グループに追加することが最善の方法になります。

重要な影響

また、/etc/security/limits.conf ファイルを編集して、ユーザー権限を変更することもできます。これにより重複が発生する可能性があり、通常のユーザーにシステムが使用できなくなる可能性があります。このファイルを編集する場合は、必ず変更を 行う 前にコピーを作成してください。

19.6. 動的ライブラリーの読み込み

real-time アプリケーションの開発時には、起動時にシンボルの解決を検討してください。プログラムの初期化が遅くなる可能性がありますが、プログラムの実行中に非決定的な遅延を避ける方法の 1 つとなります。

動的ライブラリーは、動的リンカー/ローダーである 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 &
  • ld.so(8)

19.7. アプリケーションのタイムスタンプに _COARSE POSIX クロックを使用

タイムスタンプを頻繁に実行するアプリケーションは、クロックを読み取るコストの影響を受けます。クロックの読み取りにかかるコストと時間がかかると、アプリケーションのパフォーマンスに悪影響を及ぼす可能性があります。

概念としては、ドロワー内のクロックを使用して、監視される時間イベントへの概念を示します。ドロワーを開くたびに、クロックを取得し、時間を読むだけにかかる場合は、クロックの読み取りコストが高すぎるため、欠落しているイベントが発生したり、誤ってタイムスタンプのタイムスタンプが付いてしまう可能性があります。

ウイン、壁上のクロックは読み取りにより速くなり、タイムスタンプにより観察されるイベントへの干渉が少なくなります。ウォールクロックの直前には、時間読み取りを取得する方がさらに速くなります。

同様に、読み取りメカニズムの高速なハードウェアクロックを選択すると、このパフォーマンスが向上します(クロックの読み取りコストが削減)。Red Hat Enterprise Linux for Real Time では、POSIX クロックを clock_gettime() 関数とともに使用して、可能な限り低いコストでクロックの読み取り値を生成することにより、パフォーマンスをさらに向上させることができます。

POSIX クロック

POSIX クロックは、タイムソースを実装して表すための標準です。POSIX クロックは、システムの他のアプリケーションに影響を及ぼさずに、各アプリケーションで選択できます。これは、カーネルによって選択され、システム全体に実装されるハードウェアクロックとは対照的です。

指定の POSIX クロックを読み取るために使用される関数は <time.h> で定義される clock_gettime() です。clock_gettime() は、システムコールの形式で、対応するものがカーネルにあります。ユーザープロセスが clock_gettime() を呼び出す際に、対応する C ライブラリー (glibc) が要求された操作を実行する sys_clock_gettime() システムコールを呼び出し、その結果をユーザープログラムに返します。

ただし、このコンテキストはユーザーアプリケーションからカーネルへの切り替えにはコストがかかります。このコストは非常に低くなりますが、操作が数千回繰り返し行われると、累積されたコストはアプリケーション全体のパフォーマンスに影響を及ぼす可能性があります。カーネルへのコンテキストスイッチを回避し、クロックの読み取りを高速化するために、CLOCK_MONOTONIC_COARSE および CLOCK_REALTIME_COARSE POSIX クロックのサポートが VDSO ライブラリー関数の形式で作成されました。

_COARSE クロックバリアントのいずれかを使用して clock_gettime() によって実行される時間読み取りは、カーネルの介入を必要とせず、完全にユーザースペースで実行されるため、パフォーマンスが大幅に向上します。_COARSE クロックの時間読み取りの分解能はミリ秒 (ms) です。つまり、1ms 未満の時間間隔は記録されません。POSIX クロックの _COARSE バリアントは、ミリ秒のクロック分解能に対応できるすべてのアプリケーションに適しており、読み取りコストの高いハードウェアクロックを使用するシステムでその利点がより明確になります。

注記

_COARSE 接頭辞がある場合とない場合の POSIX クロックの読み取りのコストと解像度を比較するには、「Red Hat Enterprise Linux for Real Time Reference guide for Red Hat Enterprise Linux for Real Time」を参照してください。

clock_gettime で _COARSE クロックバリアントを使用

#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 コマンドラインに追加して、rt ライブラリーにリンクする必要があります。

~]$ gcc clock_timing.c -o clock_timing -lrt
  • clock_gettime()
  • Linux System Programming (Robert Love 著)
  • Understanding The Linux Kernel ( Daniel P. Bovet および Marco Cesati 著)

19.8. perf について

perf は、パフォーマンス分析ツールです。これは、簡単なコマンドラインインターフェースを提供し、Linux のパフォーマンス測定における CPU ハードウェアの相違点を分けます。perf は、カーネルがエクスポートした perf_events インターフェースに基づいています。

perf の 1 つの利点は、カーネルとアーキテクチャーの両方です。分析データは、特定のシステム設定なしに確認できます。

perf を使用できるようにするには、root で以下のコマンドを実行して、perf パッケージをインストールします。

~]# yum install perf

perf には以下のオプションがあります。最も一般的なオプションや機能の例は以下のとおりですが、すべてのオプションの詳細は、perf help COMMAND を参照してください。

perf オプションの例

]# perf

 usage: perf [--version] [--help] COMMAND [ARGS]

 The most commonly used perf commands are:
   annotate        Read perf.data (created by perf record) and display annotated code
   archive         Create archive with object files with build-ids found in perf.data file
   bench           General framework for benchmark suites
   buildid-cache   Manage build-id cache.
   buildid-list    List the buildids in a perf.data file
   diff            Read two perf.data files and display the differential profile
   evlist          List the event names in a perf.data file
   inject          Filter to augment the events stream with additional information
   kmem            Tool to trace/measure kernel memory(slab) properties
   kvm             Tool to trace/measure kvm guest os
   list            List all symbolic event types
   lock            Analyze lock events
   record          Run a command and record its profile into perf.data
   report          Read perf.data (created by perf record) and display the profile
   sched           Tool to trace/measure scheduler properties (latencies)
   script          Read perf.data (created by perf record) and display trace output
   stat            Run a command and gather performance counter statistics
   test            Runs sanity tests.
   timechart       Tool to visualize total system behavior during a workload
   top             System profiling tool.
   trace           strace inspired tool
   probe           Define new dynamic tracepoints

See 'pert help COMMAND' for more information on a specific command.

以下の例は、レコード、アーカイブ、レポート、統計、一覧など、最も使用される機能の選択を示しています。

perf record

perf レコード機能は、システム全体の統計を収集するために使用されます。すべてのプロセッサーで使用できます。

~]# 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) ]

この例では、すべての CPU がオプション -a で示され、プロセスは数秒後に終了しました。その結果は、0.725 MB のデータを収集し、以下の結果ファイルを作成していることが示されています。

~]# ls
perf.data

perf レポートおよびアーカイブ機能の例

perf record 機能からのデータは、perf report コマンドを使用して直接調査できるようになりました。サンプルを別のシステムで分析する場合は、perf archive コマンドを使用します。~/.debug/ キャッシュなどの分析システムに、DSO (バイナリーやライブラリーなど) がすでに存在する場合や、両方のシステムに同じバイナリーセットがある場合は、これは常に必要になるわけではありません。

アーカイブコマンドを実行し、結果のアーカイブを作成します。

~]# perf archive

結果を tar アーカイブとして収集して、pref report のデータを準備します。

~]# tar xvf perf.data.tar.bz2 -C ~/.debug

perf report を実行して tarball を分析します。

~]# perf report

レポートの出力は、アプリケーションによる CPU 使用率の最大使用率に応じて並べ替えられます。これは、サンプルがプロセスのカーネルまたはユーザー空間で発生したかどうかを示します。

カーネルモジュールで実行されていない場合、カーネルサンプルは [kernel.kallsyms] という表記でマークされます。カーネルモジュールでカーネルサンプルを実行すると、[module][ext4] のマークが付けられます。ユーザー空間のプロセスでは、プロセスにリンクした共有ライブラリーが結果に表示される可能性があります。

レポートは、プロセスがカーネルまたはユーザースペースでも発生するかどうかを示します。結果 [.] はユーザースペースを示し、[k] はカーネルスペースを示します。経験のある perf 開発者に適したデータなど、詳細を確認することができます。

perf list および stat 機能の例

perf list および 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 秒以内に 5 つのファイルを作成すると、inode 要求が 5 つあることが分かります。

ハードウェアトレースポイントアクティビティーを取得するために利用可能なオプションは複数あります。以下の例は、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]...
重要

周波数が高くなりすぎると、リアルタイムシステムのパフォーマンスに悪影響を及ぼす可能性があります。

第20章 コンテナーの設定およびチューニング

本章では、コンテナーサポートを利用するためにリアルタイムカーネルを設定する方法を説明します。

20.1. 前提条件

20.2. コンテナーの作成および実行

以下のオプションはすべて、リアルタイムカーネルとメインの RHEL カーネルの両方で使用できます。kernel-rt パッケージにより潜在的な決定論が改善され、通常のトラブルシューティングが可能となります。

以下の手順では、リアルタイムカーネルに関連する Linux コンテナーを設定する方法を説明します。

  1. コンテナーに使用するディレクトリーを作成し、そのディレクトリーに移動します。

    # mkdir cyclictest
    # cd cyclictest/
  2. コンテナーレジストリーサービスを提供するホストにログインします。

    # podman login registry.redhat.io
    Username: my_customer_portal_login
    Password: **
    Login Succeeded!

    レジストリーホストへのログインの詳細は、コンテナーの構築、実行、および管理 を参照してください。

  3. 以下の Dockerfile を作成します。

    # vim Dockerfile
    FROM rhel8
    RUN subscription-manager repos --enable=rhel-8-for-x86_64-rt-rpm
    RUN dnf -y install rt-tests
    ENTRYPOINT cyclictest --smp -p95
  4. Dockerfile を含むディレクトリーからコンテナーイメージを構築します。

    # podman build -t cyclictest .
  5. 前の手順でビルドしたイメージを使用して、コンテナーを実行します。

    # 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 アフィニティーを設定することもできます。これは、リアルタイムのワークロードを調整する際に別の重要な設定ディメンションです。

    --device=/dev/cpu_dma_latency オプションは、コンテナー内でホストデバイスを利用できるようにします (続いて、CPU アイドル時間管理を設定するために cyclictest ワークロードによって使用されます)。このようなデバイスを利用できない場合は、以下のようなエラーメッセージが表示されます。

    WARN: stat /dev/cpu_dma_latency failed: No such file or directory

    上記の例のようなエラーメッセージが表示されている場合は、podman-run の man ページを参照してください。コンテナー内で実行中の特定のワークロードを取得する場合に役立つ他のオプションがあります。

    場合によっては、--device=/dev/cpu オプションを追加して、そのディレクトリー階層、/dev/cpu/*/msr などの CPU ごとのデバイスファイルをマッピングする必要があります。

20.3. その他の考慮事項

メインの RHEL カーネルは、デフォルトでリアルタイムグループスケジューリング機能 CONFIG_RT_GROUP_SCHED を有効にしますが、リアルタイムカーネルの場合は、これは無効になっています。

CONFIG_RT_GROUP_SCHED 機能は、kernel-rt パッケージで使用される PREEMPT_RT パッチセットとは独立して開発され、メインの RHEL カーネル上のリアルタイムプロセスで動作することを目的としています。CONFIG_RT_GROUP_SCHED 機能は、レイテンシーのスパイクを引き起こすことが知られているため、PREEMPT_RT が有効なカーネルでは無効化されています。したがって、メインの RHEL カーネルで実行しているコンテナーでワークロードをテストする場合は、コンテナー内で SCHED_FIFO または SCHED_RR タスクを実行できるように、一部のリアルタイム帯域幅をコンテナーに割り当てる必要があります。リアルタイム帯域幅の割り当てに関する詳細は、podman-run(1) の man ページを参照してください。

  • podman の --cpu-rt-runtime コマンドラインオプションを使用する前に、以下のグローバル設定を行います。

    # echo 950000 > /sys/fs/cgroup/cpu,cpuacct/machine.slice/cpu.rt_runtime_us

    CPU 分離の場合は、既存の推奨事項に従って RT ワークロード用にコアセットを確保してください。次に、使用する分離された CPU コアの一覧と共に podman run --cpuset-cpus コマンドを使用します。

    NUMA (Non-Uniform Memory Access) ノードメモリーアクセスをクロスしないようにするには、podman run --cpuset-mems=[number_of_memory_nodes] コマンドを使用して、使用する NUMA メモリーノードを指定します。詳細は podman-run の man ページを参照してください。

    podman run --memory-reservation=[limit] コマンドを使用して、コンテナーで実行されるリアルタイムワークロードに必要な最小メモリー量がコンテナーの起動時に確保されていることを確認します。メモリー予約の詳細は、podman-run の man ページを参照してください。