Профилирование (возможно, связанного с I/O) процесса для уменьшения латентности

Я хочу улучшить производительность конкретного метода в более крупном приложении.

Целью является улучшение латентности (настенное время, затрачиваемое на определенную функцию), а не (необязательно) нагрузка системы.

Требования:

  • Поскольку я ожидаю, что большая часть задержки будет связана с I/O, учтите время, потраченное на ожидание/блокировку (другими словами: посмотрите на время настенных часов вместо процессорного времени).
  • Поскольку программа выполняет гораздо больше, чем фрагмент, который я пытаюсь оптимизировать. Должен быть способ запуска или остановки профилирования программным путем или для фильтрации вывода, чтобы отображать только время между входом и выходом из оптимизируемой функции.
  • Профилирование на уровне метода допустимо (если это можно сделать на уровне инструкций, даже лучше, если он только проецирует системные вызовы, что, вероятно, недостаточно)
  • Это для хобби проекта, поэтому дорогостоящие инструменты на самом деле не вариант
  • Прибор (-finstrument-functions) допустим
  • Критический фрагмент кода, который меня интересует, трудно прерывать вручную (потому что он уже относительно быстр и трудно реалистично вызывается в цикле), поэтому необходима какая-то автоматизация.

Инструменты, отброшенные до сих пор:

  • gprof, oprofile, callgrind (требование 1)
  • создание чего-то пользовательского с использованием getrusage (требование 1)
  • poormansprofiler.org(требование 2)
  • strace -T, dtrace, http://perf.wiki.kernel.org (требования 2 и 3)
  • VTune, Zoom (требование 4)
  • выборка ручного набора вызовов (требование 6)
  • google-perftools (должен быть способен измерять время на стене, но это, похоже, не работает в моем случае, по-видимому, из-за помех SIGALRM.
  • systemtap (мое ядро ​​не исправлено, чтобы включить utrace)

Другие параметры, которые я еще не оценил еще:

  • cprof (не строится здесь из коробки, кажется, только i386)
  • ручная установка точек трассировки (например, с помощью lttng)

Мне бы хотелось услышать о:

  • другие параметры
  • Возможно, я слишком рано отбросил какой-то инструмент?
  • имеют ли параметры, которые я еще не оценил, имеют шанс работать, и если да, то как это сделать лучше всего.

Я наконец решил:

Трассировка этого грубого инструмента трудно интерпретировать, и я могу легко представить некоторые инструменты для дальнейшей обработки его вывода, что делает его бесконечно более полезным. Тем не менее, эта работа для меня на данный момент, поэтому я откладываю этот проект до конца;).

Ответы

Ответ 1

Используйте этот метод.

Это довольно просто и эффективно, чтобы выявить возможности оптимизации, независимо от того, находятся ли они в коде, связанном с ЦП или IO.

Если вы правы, что самые большие возможности есть в определенной функции или модуле, то они найдут их. Если они находятся в другом месте, они найдут их.

Из инструментов, которые вы упомянули и отбросили, он больше всего похож на профайлера плохого человека, но все же не очень похож.

EDIT: Поскольку вы говорите, что это вызвано взаимодействием с пользователем и блокирует дополнительный ввод до тех пор, пока он не завершится, вот как я это сделаю.

Во-первых, я предполагаю, что он не блокирует ручной сигнал прерывания отладчику, потому что в противном случае у вас не было бы способа остановить бесконечный цикл. Во-вторых, я бы обернул цикл 10, 100 или 1000 раз вокруг рассматриваемой процедуры, поэтому он делает это достаточно долго, чтобы вручную прерываться.

Теперь предположим, что он тратит часть времени на ввод-вывод, как 50%. Затем, когда вы прерываете его, у вас есть 50% шанс поймать его в I/O. Поэтому, если вы поймаете его в I/O, который скажет вам стек вызовов, вы также можете увидеть подробные сведения о том, откуда запрашивается ввод-вывод и почему.

Он покажет вам, что происходит, что почти наверняка удивительно. Если вы видите, что он делает что-то всего на двух (2) образцах, которые можно найти для устранения, то вы получите значительное ускорение. Фактически, если вы устраните эту активность, вы заранее не знаете, сколько времени вы сэкономите, но в среднем вы можете рассчитывать сохранить долю F = (s + 1)/(n + 2), где n - это общее количество образцов, которые вы взяли, и s - количество образцов, которые показали активность. (Правило преемственности) Например, если вы взяли 4 образца стека и увидели активность на 2 из них, в среднем это спасло бы вас F = 3/6 = 1/2, что соответствует коэффициенту ускорения 1/(1-F) или 2.

Как только вы это сделаете, вы можете сделать это снова и найти что-то еще, чтобы исправить. Факторы ускорения размножаются вместе, например, сложные проценты.

Тогда, конечно, вы удалите внешний цикл и "получите наличные" все ускорения, которые вы получили.

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

Подробнее обо всем этом.

Ответ 2

Для приложений, связанных с I/O, вы можете использовать опцию --collect-systime=yes для callgrind.

Это собирает время, затрачиваемое на системные вызовы (в миллисекундах). Поэтому, если вы считаете, что у вас есть узкое место ввода-вывода, вы можете использовать эту статистику для ее идентификации.

Ответ 3

Todo: проверьте 'perf' (снова)

Ответ 4

  • вилка()
  • execxxx (проверяемый процесс)
  • в родительском:
    • (в цикле) периодически вызывают:
    • getrusage (RUSAGE_CHILDREN,...)

getrusage() не только даст вам использование процессора, но также основные/мелкие страницы, количество переключателей контекста и т.д. Остальное время, вероятно, потрачено на ожидание ввода-вывода. Это не даст вам подробной информации о профилировании, но дает хороший общий характер поведения программы, сравнимый с запуском vmstat на основе каждого процесса.