おおよそのマシン:このマシンはPHPを実行する4C統計マシンであり、同時に複数のプロセスが進行している可能性があります。
Topを使用して次のように観察します
%Cpu(s): 46.7 us, 35.6 sy, 0.0 ni, 17.7 id, 0.0 wa, 0.0 hi, 0.1 si, 0.0 st
syが非常に高くなるという非常に明白な現象があります。通常、この値は比較的小さいはずです。
Syの定義:システム:カーネルプロセスの実行時間。カーネルコードの実行時にCPUが占有するCPU時間を示します。
主にコンテキストの切り替えのために、関連記事を確認しました。元のテキストは次のとおりです。
実行可能なスレッドの数がCPUの数よりも多い場合、OSは最終的に実行中のスレッドを強制的にスワップアウトし、他のスレッドがCPUを使用できるようにします。これにより、コンテキストスイッチが発生し、現在実行中のスレッドの実行コンテキストが保存され、新しく呼び出されたスレッドの実行コンテキストが再構築されます。コンテキストの切り替えには代償が伴います。スレッドのスケジューリングには、OSとJVM間で共有されるデータ構造の操作が必要です。プログラムはOSおよびJVMと同じCPUを使用します。CPUがJVMおよびOSのコードに費やす時間が長いほど、プログラムに費やされる時間は少なくなります。ただし、JVMおよびOSアクティビティのコストだけが、コンテキスト切り替えのオーバーヘッドの原因ではありません。新しいスレッドがスワップインされると、必要なデータが現在のプロセッサのローカルキャッシュにない可能性があるため、コンテキストを切り替えるとキャッシュミスの小さなパニックが発生し、スレッドは最初にスケジュールされたときに少し遅くなります。 。他に多くの待機中のスレッドがある場合でも、スケジューラーは実行可能なスレッドごとに最小実行時間クォータを割り当てます。これは、この理由によるものです。分割払いでコンテキストを切り替えるオーバーヘッドを支払い、中断のない実行時間を取得し、全体としてスループットを向上させます(応答性が失われます)。
上記の回答から、頻繁なコンテキスト切り替えとキャッシングという2つのポイントが抽出されます。
頻繁なコンテキスト切り替え
これらのプロセスが頻繁な朝と午後の切り替えを実行することを証明するにはどうすればよいですか?これらのプロセスは非常に短い時間で高いCPUsyにつながるので、このインスタントタスクがどのように表示されるかを確認したいと思います。
次に、現在のメモリスナップショットとタスクスナップショットを監視し、vmcoreを構築してシステムのすべての情報を保存し、メモリが不足しているときにメモリオーバーヘッドが最も多いプロセスを強制終了するツールsysrqについて考えてみます。
特定の用途
- システム4変数sysctl-w kernel.sysrq = 1を設定します
- カーネルバッファへの出力echot> / proc / sysrq-トリガー
- dmesgを使用してスナップショット情報を表示
します。CPUsyが高いときに手順2を実行しますが、速度が速すぎる場合があります。独身で20年以上、ハンドスピードが足りなかったので、シェルコレクションを書きました。
#!/bin/sh
while [ 1 ]; do
top -bn2 grep "Cpu(s)" tail -1 awk '{
# $2 is usr, $4 is sys.
# 这个规则可以看自己系统情况调节
if ($2 < 10.0 && $4 > 10.0) {
# 日志文件名生成规则
while ("date" getline date) {
split(date, str, " ");
prefix=sprintf("%s_%s_%s_%s", str[2],str[3], str[4], str[5]);
}
# 目录自己调整
sys_usr_file=sprintf("/work/tmp/%s_info.highsys", prefix);
print $2 > sys_usr_file;
print $4 >> sys_usr_file;
# run sysrq
system("echo t > /proc/sysrq-trigger");
}
}'
# 这个时间也可以自己调节
sleep 5s
done
demsgを使用して、上記のスナップショットデータ出力を表示します。いくつかの特別な結果があります。PHPが実行されるたびに、次の呼び出し情報が発生する必要があります。
[73304.409408] php W ffff88023252fba4 0 12374 12369 0x00000080
[73304.409410] ffff88023252fa30 0000000000000086 ffff880232a49700 ffff88023252ffd8
[73304.409412] ffff88023252ffd8 ffff88023252ffd8 ffff880232a49700 ffff88023252fb88
[73304.409414] 00000000039386ff 0000000000000000 0000000000000000 ffff88023252fba4
[73304.409416] Call Trace:
[73304.409418] [<ffffffff8163a909>] schedule+0x29/0x70
[73304.409420] [<ffffffff81639a22>] schedule_hrtimeout_range_clock+0xb2/0x150
[73304.409422] [<ffffffff810a95c0>] ? hrtimer_get_res+0x50/0x50
[73304.409424] [<ffffffff81639a16>] ? schedule_hrtimeout_range_clock+0xa6/0x150
[73304.409426] [<ffffffff81639ad3>] schedule_hrtimeout_range+0x13/0x20
[73304.409428] [<ffffffff811f2bb5>] poll_schedule_timeout+0x55/0xb0
[73304.409430] [<ffffffff811f413d>] do_sys_poll+0x4cd/0x580
[73304.409433] [<ffffffff8163cb5b>] ? _raw_spin_unlock_bh+0x1b/0x40
[73304.409435] [<ffffffff815154a8>] ? release_sock+0x118/0x170
[73304.409437] [<ffffffff815769e6>] ? tcp_sendmsg+0xd6/0xc20
[73304.409439] [<ffffffff811f2ad0>] ? poll_select_copy_remaining+0x150/0x150
[73304.409450] [<ffffffffa01eed4c>] ? xfs_iunlock+0x11c/0x130 [xfs]
[73304.409452] [<ffffffff8116902b>] ? unlock_page+0x2b/0x30
[73304.409454] [<ffffffff81192eb1>] ? __do_fault+0x401/0x510
[73304.409457] [<ffffffff81197088>] ? handle_mm_fault+0x5b8/0xf50
[73304.409459] [<ffffffff81511281>] ? SYSC_sendto+0x121/0x1c0
[73304.409460] [<ffffffff81640ec9>] ? __do_page_fault+0x1f9/0x420
[73304.409463] [<ffffffff81058aaf>] ? kvm_clock_get_cycles+0x1f/0x30
[73304.409465] [<ffffffff810d814c>] ? ktime_get_ts64+0x4c/0xf0
[73304.409467] [<ffffffff811f42f4>] SyS_poll+0x74/0x110
[73304.409469] [<ffffffff81645909>] system_call_fastpath+0x16/0x1b
表示される重要な情報の説明:
schedule_hrtimeoutは、CLOCK_MONOTONICタイミングシステムを使用して
、現在のプロセスを指定された時間スリープさせます。schedule_hrtimeout_rangeは、CLOCK_MONOTONICタイミングシステムを使用して、現在のプロセスを指定された時間範囲でスリープさせます。schedule_hrtimeout_range_clock
は、現在のプロセスを指定された時間範囲、および自分でタイミングシステムを指定できます;
…
上記の推測の頻繁なコンテキスト切り替えを証明します。
キャッシュは
主に、上記の「データが現在のプロセッサのローカルキャッシュにない可能性がある」ために頻繁にページがコピーされるためです。その後、CPUは即座に急上昇しました。したがって、これを証明するには、上記のログを引き続き確認する必要があり、予想どおり、いくつかの有用な情報が見つかりました。
[73304.409471] php R running task 0 12375 12371 0x00000080
[73304.409473] ffff8802328e7f58 0000000000000082 ffff880232a4e780 ffff8802328e7fd8
[73304.409475] ffff8802328e7fd8 ffff8802328e7fd8 ffff880232a4e780 0000000000000000
[73304.409477] 00007ffdf3ab7c98 00000000000000c8 00007ffdf3ab7aa2 0000000000000093
[73304.409479] Call Trace:
[73304.409481] [<ffffffff8163b931>] schedule_user+0x31/0xc0
[73304.409483] [<ffffffff8163d196>] retint_careful+0x14/0x32
[73304.409485] php R running task 0 12376 12373 0x00000080
[73304.409486] 0000000000000001 0000000000000000 ffff8802339aff68 ffffffff8119cc61
[73304.409488] ffff88008ec91800 ffff88008ec91a48 ffff88008ec91800 ffff8802339aff48
[73304.409490] ffffffff816408d9 0000000000000000 0000000000000001 ffffffff8163d438
[73304.409492] Call Trace:
[73304.409494] [<ffffffff816411b3>] ? trace_do_page_fault+0x43/0x110
[73304.409496] [<ffffffff816408d9>] do_async_page_fault+0x29/0xe0
[73304.409498] [<ffffffff8163d438>] async_page_fault+0x28/0x30
プログラムの実行中は、ページフォールトが頻繁に発生しますが(正常ですが)、同時に問題が発生します。メモリページが大きい場合、その時点でCPUの負荷が大きくなります。メモリの巨大なページメカニズムがオンになっていると、さらにクールになりませんか???
案の定、このマシンはオンになっています!!!
$ cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
まとめ
頻繁なコンテキスト切り替えは、主に、プログラムによって開かれるプロセスまたはスレッドの数が、マシンのCPU自体のコアの数をはるかに超えているためです。ビジネスコードを確認した後、実際にはPHPFockの複数のサブプロセスが使用されています。マシン自体もメモリラージページメカニズムをオンにしました。これにより、瞬間的なCPU負荷が高くなりすぎて、アラームが継続的にトリガーされました。
この状況に対する私のアプローチは、最初にコードロジックを最適化することです。次に、メモリの巨大なページのメカニズムを閉じます。メモリの巨大なページは適切ですが、不適切な使用は否定的な最適化です。