Определите системные вызовы или подсистемы, в которых процесс тратит время на ожидание - PullRequest
0 голосов
/ 08 февраля 2019

Я ищу способы узнать , какие системные вызовы или , какие подсистемы процесс или поток тратит время на ожидание, т.е. заблокирован и не запланирован для запуска на ЦП.

В частности, если у меня есть какой-то неизвестный процесс или процесс, в котором все, что мы знаем, это «он медленный», я бы хотел научиться таким вещам, как:

  • «он тратит 80%своего времени в sys_write() на fd 13, который является / some / file "
  • ", он проводит много времени в ожидании чтения () из сетевого сокета "
  • ", в котором он спитepoll_wait () для активности на fds [4,5,6], которые [file / boo], [socket 10.1.1.:42], [notifyfd blah] "

Другими словами когда моя программа не работает на процессоре, что она делает?

Это удивительно трудно ответить с perf, потому что, похоже, не имеет никакого способазаписать длительность системного вызова от sys_enter до sys_exit или иным образом отслеживать как долго событие происходит.Предположительно из-за его природы выборки.

Мне известна некоторая экспериментальная работа с eBPF для Linux 4.6 и выше, которая может помочь с работой Брендана Грегга вне процессора .Но в печальном мире операций и поддержки ядро ​​4.6 - это редкий единорог, который нужно ценить.

Какие есть варианты в реальном мире?

Есть ли здесь какие-нибудь идеи ftrace, systemtap и т.д.?

1 Ответ

0 голосов
/ 09 февраля 2019

Вы можете использовать strace .Во-первых, вы можете получить высокоуровневую сводку стоимости каждого типа системных вызовов.Вы можете получить это резюме, запустив strace -c.Например, одним из возможных выходных данных является следующее:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 90.07    0.000263          26        10           getdents
  3.42    0.000010           0      1572           read
  3.42    0.000010           0       762         1 stat
  3.08    0.000009           0      1574         6 open
  0.00    0.000000           0        11           write
  0.00    0.000000           0      1569           close
  0.00    0.000000           0        48           fstat

Значение % time относится к общему времени ядра, а не к общему времени выполнения (ядро + пользователь).Это резюме говорит вам, что самые дорогие системные вызовы.Однако, если вам нужно определить, какие конкретные экземпляры системных вызовов наиболее дороги и какие аргументы им передаются, вы можете запустить strace -i -T.Опция -i показывает адреса команд для инструкций, которые выполняли системный вызов, а опция -T - время, потраченное на системный вызов.Вывод может выглядеть следующим образом:

[00007f97f1b37367] open("myfile", O_RDONLY|O_CLOEXEC) = 3 <0.000020>
[00007f97f1b372f4] fstat(3, {st_mode=S_IFREG|0644, st_size=159776, ...}) = 0 <0.000018>
[00007f97f1b374ba] mmap(NULL, 159776, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f97f1d19000 <0.000019>
[00007f97f1b37467] close(3)             = 0 <0.000018>

В первом столбце показаны адреса команд, во втором столбце показаны системные вызовы с их аргументами, в третьем столбце показано возвращаемое значение, а в последнем столбце указано время, затраченное наэтот системный вызов.Этот список упорядочен по динамическому вхождению системного вызова.Вы можете отфильтровать этот вывод, используя либо grep, либо параметр -e.Адреса команд могут помочь вам определить, где в исходном коде выполняются эти системные вызовы.Например, если длинная последовательность системных вызовов имеет один и тот же адрес, то есть большая вероятность, что у вас есть цикл где-то в коде, который содержит системный вызов.Если ваш исполняемый двоичный файл не является PIE , динамические адреса совпадают со статическими адресами, показанными objdump.Но даже с PIE относительный порядок динамических адресов одинаков.Я не знаю, есть ли простой способ сопоставить эти системные вызовы со строками исходного кода.

Если вы хотите узнать что-то вроде «он тратит 80% своего времени в sys_write () на fd 13»то есть / some / file ", то вам нужно написать скрипт, который сначала извлекает возвращаемые значения всех вызовов open и соответствующих аргументов имени файла, а затем суммирует время всех вызовов sys_write, чей аргумент fd равенравно некоторому значению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...