У меня есть пара процессов, которые потребляют много системного процессорного времени (как определено с помощью vmstat). Есть ли простой способ узнать, какие системные вызовы выполняются?
Я знаю, что есть strace, но есть ли способ быстрее и проще? Есть ли что-то вроде "топа" для системных вызовов?
Я думаю, что с -c
flag, наверное, самый близкий из известных мне. Если вы не использовали -c
флаг, попробуйте это:
$ sudo strace -c -p 12345
Где 12345 - это идентификатор процесса (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
Как видите, это разбивка всех системных вызовов, выполненных приложением, отсортированных по общему времени, включая среднее время на вызов и количество вызовов для каждого системного вызова. Если вы хотите отсортировать их по-другому, см. Страницу руководства по strace, так как есть несколько вариантов.
Я обычно использую следующие переключатели 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.
Но, если поток является потоком ядра, вы не можете его объединить или создать ядро. В этом случае мы должны использовать что-то более сложное. В ядре RHEL5 мы используем oprofile. В RHEL6 мы используем perf. Я предпочитаю перфоманс опрофиле. Данные производительности могут быть собраны в графическом формате, показывающем системный вызов, в котором используется максимальный процент ЦП.
С тестовой перфомансой я это вижу.
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% процессорного времени. Теперь мы можем проверить функцию и посмотреть, что она делает и что должна делать.
На нескольких примерах это не так уж и сложно.
Возможно, попробуйте один из профилировщиков выборки, например oprofile, или для более новых ядер perf. Если вам повезет, «perf top» может сказать вам именно то, что вы хотите. Видеть вот несколько примеров