Мониторинг системных ЦП / системных вызовов в Linux

9

У меня есть пара процессов, которые поглощают много системного процессорного времени (как определено просмотром vmstat). Есть ли простой способ узнать, какие системные вызовы выполняются?

Я знаю, что есть Strace, но есть ли более быстрый и простой способ? Существует ли что-то вроде «top» для системных вызовов?

bajafresh4life
источник
1
Strace это решение.
Уорнер

Ответы:

15

Я думаю, что Strace с -cфлагом, вероятно, ближе всего, что я знаю. Если вы не использовали -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, так как есть несколько вариантов.

Кристофер Кашелл
источник
2
Блин, бесполезный мьютекс! качает кулак
Гай
2

Возможно, попробуйте один из профилировщиков выборки, например, oprofile или для более новых ядер, perf. Если вам повезет, «perf top» может сказать вам именно то, что вы хотите. Смотрите здесь для некоторых примеров

janneb
источник
2

Тип стринг-переключателей, который я обычно использую, таков.

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 мы используем перф. Я предпочитаю перф, а не опрофиль. Данные о производительности можно собирать в графическом формате, показывающем системный вызов, в котором используется максимальный процент использования ЦП.

С тестовым перфом я вижу это.

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% процессорного времени. Теперь мы можем проверить функцию и посмотреть, что она делает и что она должна делать.

С несколькими примерами это не так уж сложно.

Сохам Чакраборти
источник