Мониторинг системных CPU / системных вызовов в Linux
У меня есть пара процессов, которые поглощают много системного процессорного времени (как определено просмотром vmstat). Есть ли простой способ узнать, какие системные вызовы выполняются?
Я знаю, что есть Strace, но есть ли более быстрый и простой способ? Существует ли что-то вроде "top" для системных вызовов?
3 ответа
Я думаю, что связать с -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, так как есть несколько вариантов.
Тип стринг-переключателей, который я обычно использую, таков.
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% процессорного времени. Теперь мы можем проверить функцию и посмотреть, что она делает и что она должна делать.
С несколькими примерами это не так уж сложно.
Возможно, попробуйте один из профилировщиков выборки, например, oprofile или для более новых ядер, perf. Если вам повезет, "perf top" может сказать вам именно то, что вы хотите. Смотрите здесь для некоторых примеров