回答:
-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ページを参照してください。
私がよく使用する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時間を費やしているカーネル機能を示しています。これで、関数をチェックして、それが何をしているか、何をすべきかを確認できます。
いくつかの例を挙げれば、それほど難しくはありません。