プロセスは、開発の学生がよく知っている概念であり、プロセスコンテキストの切り替えのオーバーヘッドについても聞いたことがあるかもしれません。では、今日、プロセスコンテキストスイッチが消費するCPU時間について考えてみましょう。スレッドはプロセスよりも軽いと言われていますが、コンテキストの切り替えはプロセスの切り替えよりもCPU時間を大幅に節約できますか?
0 1
プロセスとプロセスの切り替え
このプロセスは、オペレーティングシステムの優れた発明の1つであり、CPUスケジューリングやメモリ管理などのハードウェアの詳細からアプリケーションを保護し、プロセスの概念を抽象化して、アプリケーションが独自のビジネスロジックの実装に集中できるようにし、限られたCPUで使用できるようにします。多くのタスクを「同時に」実行できます。
プロセスAをプロセスBに切り替えるプロセスでは、最初にプロセスAのコンテキストを保存します。これにより、Aが実行を再開したときに、プロセスAの次の命令が何であるかを知ることができます。次に、実行するBプロセスのコンテキストをレジスタに復元します。このプロセスは、コンテキスト切り替えと呼ばれます。
コンテキスト切り替えのオーバーヘッドは、プロセスが少なく、切り替えの頻度が低いアプリケーションシナリオでは大きな問題ではありません。しかし現在、Linuxオペレーティングシステムは、並行性の高いネットワークプログラムのバックエンドサーバーとして使用されています。1台のマシンが数万のユーザー要求をサポートする場合、このオーバーヘッドについて言及する必要があります。
ユーザープロセスがRedis、Mysqlデータおよびその他のネットワークIOのブロックを要求したとき、またはプロセスタイムスライスが到着したときに、コンテキストスイッチがトリガーされるためです。
0 2
簡単なプロセス切り替えオーバーヘッドテスト
あまり意味がないので、実験を使用して、コンテキストスイッチに必要なCPU時間をテストしましょう!
実験的な方法は、2つのプロセスを作成し、それらの間にトークンを渡すことです。トークンを読み取るときに、プロセスの1つがブロックされます。トークンの送信後、別のプロセスが返されるのを待っている間も、別のプロセスがブロックされます。この方法で特定の回数を転送してから、それらの平均シングルスイッチング時間のオーバーヘッドをカウントします。コンパイルして実行
# gcc main.c -o main
# ./main./main
Before Context Switch Time1565352257 s, 774767 us
After Context SWitch Time1565352257 s, 842852 us
実行時間はそれぞれ異なります。複数回実行した後、コンテキストスイッチごとに平均で約3.5usかかります。もちろん、この数はマシンごとに異なるため、実際のマシンでテストすることをお勧めします。
以前にシステム呼び出しをテストしたとき、最小値は200nsでした。コンテキスト切り替えのオーバーヘッドがシステム呼び出しのオーバーヘッドよりも大きいことがわかります。システム呼び出しは、プロセスでユーザーモードをカーネルモードに切り替えてから元に戻すだけですが、コンテキストスイッチはプロセスAからプロセスBに直接切り替えられます。明らかに、このコンテキスト切り替えにはさらに多くの作業が必要です。
0 3
プロセス切り替えオーバーヘッド分析
では、コンテキスト切り替え中の特定のCPUオーバーヘッドは何ですか?オーバーヘッドには2つのタイプがあります。1つは直接オーバーヘッドで、もう1つは間接オーバーヘッドです。
直接オーバーヘッドは、切り替え時にcpuが実行する必要があることです。
1.ページテーブルのグローバルディレクトリを切り替えます
2.カーネルモードスタックを切り替えます
3.ハードウェアコンテキストを切り替えます(プロセスを再開する前にレジスタにロードする必要があるデータをまとめてハードウェアコンテキストと呼びます)
ip(命令ポインタ):現在実行されている命令の次の命令を指します
bp(ベースポインタ):実行中の関数に対応するスタックフレームの最下位アドレスを格納するために使用されます
sp(stack poinger):実行中の関数に対応するスタックフレームのトップアドレスを格納するために使用されます
cr3:ページディレクトリベースアドレスレジスタ、ページディレクトリテーブルの物理アドレスを保存します
……。
4.TLBを更新します
5.システムスケジューラのコード実行
間接オーバーヘッドとは、主に、新しいプロセスに切り替えた後、さまざまなキャッシュがホットではないため、速度が遅くなることを意味します。
プロセスが常に1つのCPUでスケジュールされている方が良いです。プロセスがCPUを通過すると、実行中のプロセスが変更されたため、以前に加熱されたTLB、L1、L2、およびL3が変更されたため、ローカリティの原則によってキャッシュされたコードとデータもすべてそれは役に立たず、新しいプロセスをメモリに浸透させるIOが増加します。
実際、上記の実験ではこの状況を適切に測定できなかったため、実際のコンテキスト切り替えのオーバーヘッドは3.5usを超える可能性があります。
より詳細な操作プロセスを知りたい学生は、「Linuxカーネルについて」の第3章と第9章を参照してください。
0 4
より専門的なツール-lmbench
lmbenchは、システムの全体的なパフォーマンスを評価するために使用されるマルチプラットフォームのオープンソースベンチマークであり、ドキュメントの読み取りと書き込み、メモリ操作、プロセスの作成と破棄のオーバーヘッド、ネットワークパフォーマンスなどのパフォーマンスをテストできます。使い方は簡単ですが、走りが少し遅いので、興味のある方は自分で試してみてください。
このツールの利点は、それぞれ2つのプロセス、8、および16で複数の実験セットが実行されることです。各プロセスで使用されるデータサイズも変化しており、キャッシュミスの影響を完全にシミュレートしています。私は彼と一緒にテストしましたが、結果は次のとおりです(完全に表示するには、下の画像を水平方向にスクロールする必要があります)。
-------------------------------------------------------------------------
Host OS 2p/0K 2p/16K 2p/64K 8p/16K 8p/64K 16p/16K 16p/64K
ctxsw ctxsw ctxsw ctxsw ctxsw ctxsw ctxsw
--------- ------------- ------ ------ ------ ------ ------ ------- -------
bjzw_46_7 Linux 2.6.32- 2.7800 2.7800 2.7000 4.3800 4.0400 4.75000 5.48000
lmbenchによって表示されるプロセスコンテキストの切り替えには、2.7usから5.48usまで時間がかかります。
0 5
時間のかかるスレッドコンテキストの切り替え
プロセスコンテキスト切り替えのオーバーヘッドをテストする前に、Linuxでスレッドのテストを続けましょう。プロセスよりも高速であるかどうか、およびどれだけ高速であるかを確認してください。
実際、Linuxにはスレッドはありません。開発者の好みに応えるためだけに、軽量のプロセスはスレッドと呼ばれます。プロセスと同様に、軽量プロセスには、独自の独立したtask_structプロセス記述子と独自の独立したpidがあります。オペレーティングシステムの観点からは、スケジューリングとプロセスの間に違いはありません。これらはすべて、待機キューの二重リンクリストでtask_structを選択して、実行状態に切り替えています。軽量プロセスと通常のプロセスの違いは、同じメモリアドレス空間、コードセグメント、グローバル変数、および開いているファイルの同じセットを共有できることだけです。
同じプロセス内のスレッドのすべてのgetpid()に表示されるpidは同じです。実際、task_structにはtgidフィールドもあります。マルチスレッドプログラムの場合、getpid()システム呼び出しによって取得されるtgidは実際にはtgidであるため、同じプロセスに属する複数のスレッドは同じPIDを持っているように見えます。
ある実験を使用して別のテストを実行します。原理はプロセステストの原理と似ています。20個のスレッドが作成され、信号がパイプを介してスレッド間で渡されます。信号を受信したらウェイクアップし、信号を次のスレッドに渡して自動的にスリープ状態にします。この実験では、パイプラインに信号を送信するための追加コストが個別に考慮され、最初のステップでカウントされました。
# gcc -lpthread main.c -o main
0.508250
4.363495
各実験の結果には多少の違いがあります。上記の結果は、何度も結果をとった後の平均です。各スレッド切り替えのコストは約3.8usです。時間のかかるコンテキスト切り替えに関しては、Linuxスレッド(軽量プロセス)は実際にはプロセスとそれほど違いはありません。
0 6
Linux関連のコマンド
コンテキスト切り替えがCPU時間を消費することがわかったので、Linuxで発生している切り替えの数を確認するためにどのツールを使用できますか?コンテキストスイッチがシステムの全体的なパフォーマンスに影響を与えた場合、問題のあるプロセスを見つけて最適化する方法はありますか?(完全に表示するには、下の画像を水平方向にスクロールする必要があります)
# vmstat 1
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 0 595504 5724 190884 0 0 295 297 0 0 14 6 75 0 4
5 0 0 593016 5732 193288 0 0 0 92 19889 29104 20 6 67 0 7
3 0 0 591292 5732 195476 0 0 0 0 20151 28487 20 6 66 0 8
4 0 0 589296 5732 196800 0 0 116 384 19326 27693 20 7 67 0 7
4 0 0 586956 5740 199496 0 0 216 24 18321 24018 22 8 62 0 8
またはそれは可能性があります
# sar -w 1
proc/s
Total number of tasks created per second.
cswch/s
Total number of context switches per second.
11:19:20 AM proc/s cswch/s
11:19:21 AM 110.28 23468.22
11:19:22 AM 128.85 33910.58
11:19:23 AM 47.52 40733.66
11:19:24 AM 35.85 30972.64
11:19:25 AM 47.62 24951.43
11:19:26 AM 47.52 42950.50
......
上の図の環境は実稼働環境マシン、構成は8コア8G KVM仮想マシン、環境はnginx + fpm、fpmの数は1000、1秒あたりに処理される平均ユーザーインターフェイス要求は約100です。cs列は、1秒以内にシステムで発生したコンテキストスイッチの数を示します。約1秒で、スイッチの数は4Wに達しました。大まかな見積もりとして、各コアは1秒間に約5K回切り替える必要があり、1秒以内にコンテキストを切り替えるには約20ミリ秒かかります。これは仮想マシンであり、仮想化自体に追加のオーバーヘッドが発生することを知っておく必要があります。実際には、ユーザーインターフェイスロジック処理、システム呼び出しカーネルロジック処理、ネットワーク接続処理、およびソフト割り込みでCPUを消費するため、20ミリ秒のオーバーヘッドが発生します。実際にはもう低くはありません。
さらに、どのプロセスが頻繁なコンテキスト切り替えを引き起こしているのかを見てみましょう。(下の画像を完全に表示するには、水平方向にスクロールする必要がある場合があります)
# pidstat -w 1
11:07:56 AM PID cswch/s nvcswch/s Command
11:07:56 AM 32316 4.00 0.00 php-fpm
11:07:56 AM 32508 160.00 34.00 php-fpm
11:07:56 AM 32726 131.00 8.00 php-fpm
......
fpmは同期ブロッキングモードであるため、Redis、Memcache、またはMysqlが要求されると、ブロックされてcswch / sの自発的なコンテキスト切り替えが発生し、タイムスライスがアップした後にのみnvcswch / sの非自発的な切り替えがトリガーされます。fpmプロセスの切り替えのほとんどは自発的であり、非自発的ではないことがわかります。
特定のプロセスの全体的なコンテキスト切り替えの状況を表示する場合は、/ procインターフェイスで直接表示できますが、これは合計値です。
grep ctxt /proc/32583/status
voluntary_ctxt_switches: 573066
nonvoluntary_ctxt_switches: 89260
0 7
結論として
コンテキスト切り替えの機能を覚えておく必要はありません。1つの結論を覚えておく必要があります。作成者の開発マシンでのコンテキスト切り替えのコストは約2.7〜5.48であると測定されています。私が提供したコードまたはツールを、自分のマシンに使用できます。いくつかのテスト。
lmbenchは、切り替え後のキャッシュミスによって引き起こされる追加のオーバーヘッドを考慮に入れるため、比較的正確です。
ダニエルはどのように訓練しましたか?どのようにお金を稼ぐのですか?
コミック:なぜ量子コンピューティングはとても素晴らしいのですか?