web-dev-qa-db-ja.com

LinuxでシステムCPU /システムコールを監視する

システムのCPU時間を大量に消費しているプロセスがいくつかあります(vmstatを確認することで判断)。どのようなシステムコールが行われているかを簡単に調べる方法はありますか?

Straceがあることは知っていますが、より速くて簡単な方法はありますか?システムコールの「トップ」のようなものはありますか?

9
bajafresh4life

-cフラグの付いたstraceは、おそらく私が知っている最も近いものだと思います。 -cフラグを使用していない場合は、これを試してください:

$  Sudo strace -c -p 12345

12345は、問題のプロセスのプロセスID(PID)です。プロセスをストレーシングするとオーバーヘッドが増えるため、プロセスをトレースしている間は、プロセスの実行が遅くなることに注意してください。

データを収集したい期間それを実行した後、Ctrl-Cを押してデータ収集を停止し、結果を出力します。次のようなものが生成されます。

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 31.88    0.001738         145        12           futex
 16.79    0.000915          11        80           tgkill
 12.36    0.000674          34        20           read
  9.76    0.000532         266         2           statfs
  8.42    0.000459          13        35           time
  4.38    0.000239           6        40           gettimeofday
  3.65    0.000199           4        48           sigprocmask
  2.94    0.000160          18         9           open
  2.88    0.000157          12        13           stat64
  1.32    0.000072           9         8           munmap
  0.90    0.000049           6         8           mmap2
  0.88    0.000048           3        14         7 sigreturn
  0.79    0.000043           5         9           close
  0.77    0.000042           4        10           rt_sigprocmask
  0.64    0.000035           3        12           setitimer
  0.55    0.000030           5         6         6 rt_sigsuspend
  0.53    0.000029           4         8           fstat64
  0.29    0.000016           8         2           setresuid32
  0.13    0.000007           4         2           _llseek
  0.09    0.000005           3         2           prctl
  0.04    0.000002           2         1           geteuid32
------ ----------- ----------- --------- --------- ----------------
100.00    0.005451                   341        13 total

ご覧のとおり、これは、アプリケーションによって行われたすべてのシステムコールの内訳であり、合計時間でソートされ、コールごとの平均時間と各syscallのコール数を含みます。それらを別の方法でソートしたい場合は、いくつかのオプションがあるため、straceのmanページを参照してください。

15

たぶん、oprofileなどのサンプリングプロファイラーの1つを試すか、新しいカーネルのperfを試してみてください。運が良ければ、「perf top」で正確に何が欲しいのかがわかるでしょう。 例はこちら を参照してください

2
janneb

私がよく使用するstraceスイッチのタイプはこれです。

strace -ffttT -p pid -o /tmp/strace.out

この例は次のようになります。

19:35:57.485493 mprotect(0x7f35e7472000, 16384, PROT_READ) = 0 <0.000037>
19:35:57.485599 mprotect(0x7f35e7692000, 4096, PROT_READ) = 0 <0.000030>
19:35:57.485697 mprotect(0x7f35e78b7000, 4096, PROT_READ) = 0 <0.000030>
19:35:57.485782 munmap(0x7f35e7896000, 129588) = 0 <0.000037>
19:35:57.485875 set_tid_address(0x7f35e78949d0) = 10730 <0.000029>
19:35:57.485960 set_robust_list(0x7f35e78949e0, 0x18) = 0 <0.000024>
19:35:57.486048 futex(0x7fff8f58628c, FUTEX_WAKE_PRIVATE, 1) = 0 <0.000025>
19:35:57.486131 futex(0x7fff8f58628c, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1,       NULL, 7f35e7894700) = -1 EAGAIN (Resource temporarily unavailable) <0.000024>

システムコールの右側に時差が表示され、あるシステムコールから別のシステムコールに移動するのにかかった時間を示します。

システムコール間の時間差をキャッチします。したがって、システムコールに次のシステムコールとの間にかなりの数秒のギャップがあることがわかると、ノイズが発生します。

別の方法は、gcoreでコアダンプすることです。ただし、gdbの操作には少し経験が必要です。

ただし、スレッドがカーネルスレッドの場合、straceまたはコアダンプすることはできません。その場合、より複雑なものを使用する必要があります。 RHEL5カーネルでは、oprofileを使用します。 RHEL6では、perfを使用します。私はoprofileよりもパフォーマンスを優先します。パフォーマンスデータは、CPUの最大パーセンテージが使用されているシステムコールを示すグラフのような形式で収集できます。

テストのパフォーマンスで、これがわかります。

38.06%  swapper  [kernel.kallsyms]  [k] mwait_idle_with_hints                                                                                                               ↑

29.45%  swapper  [kernel.kallsyms]  [k] read_hpet 
4.90%  swapper  [kernel.kallsyms]  [k] acpi_os_read_port                                                                                                                   ▒
4.74%  swapper  [kernel.kallsyms]  [k] hpet_next_event   

これは、38%のCPU時間を費やしているカーネル機能を示しています。これで、関数をチェックして、それが何をしているか、何をすべきかを確認できます。

いくつかの例を挙げれば、それほど難しくはありません。

2