Подтвердить что ты не робот

Получение информации о стеке пользовательского пространства из perf

В настоящее время я пытаюсь отслеживать некоторые операции ввода/вывода phantom в построенной PostgreSQL, которую я тестирую. Это многопроцессорный сервер, и не просто связать дисковый ввод-вывод с конкретным контентом и запросом.

Я думал, что инструмент Linux perf был бы идеальным для этого, но я изо всех сил стараюсь захватить метрики производительности производительности ввода-вывода блоков и связать их с деятельностью пользовательского пространства.

Легко записывать запросы ввода-вывода блоков и их завершения, например:

sudo perf record -g -T -u postgres -e 'block:block_rq_*'

и записывается pid пользовательского пространства, но нет никакого стека ядра или пользовательского пространства или способности к моментальным снимкам кучи процесса пространства пользователя (скажем, текста запроса) и т.д. Поэтому, пока у вас есть pid, вы не знаете, что этот процесс делал в этот момент. Просто perf script вывод:

postgres  7462 [002] 301125.113632: block:block_rq_issue: 8,0 W 0 () 208078848 + 1024 [postgres]

Если я добавлю флаг -g в perf record, он будет делать снимки ядра, но не фиксирует состояние пространства пользователя для перфорированных событий, зафиксированных в ядре. Стек пользовательского пространства только поднимается до точки входа из пользовательского пространства, например LWLockRelease, LWLockAcquire, memcpy (mmap'd IO), __GI___libc_write и т.д.

Итак. Какие-нибудь советы? Возможность захвата моментального снимка стека пользовательского пространства в ответ на события ядра была бы идеальной.

Я на Fedora 19, 3.11.3-201.fc19.x86_64, Schrödingers Cat, с первичным вариантом 3.10.9-200.fc19.x86_64.

4b9b3361

Ответ 1

ОК, похоже, что есть несколько частей:

  • Я нахожусь на x86_64, где по умолчанию большинство дистрибутивов компонуются с -fomit-frame-pointer, а perf не может следовать за стеком без указателей рамки;

  • .... если не новая версия, построенная с поддержкой libunwind, и в этом случае она поддерживает perf record -g dwarf.

См:

Я на Fedora 18, но та же проблема применяется. Поэтому, если вы профилируете код, над которым вы работаете (как, вероятно, в Stack Overflow), перестройте с помощью -fno-omit-frame-pointer и -ggdb.

Я приземлился на восстановление perf, потому что я хотел иметь возможность сравнить с RPM акций:

  • sudo yum build-dep perf
  • sudo yum install yum-utils rpmdevtools libunwind-devel
  • yumdownloader --source perf или загрузите соответствующий kernel-.....src.rpm srpm
  • rpmdev-setuptree
  • rpm -Uvh kernel-*.src.rpm
  • cd $HOME/rpmbuild/SPECS
  • rpmbuild -bp --target=$(uname -m) kernel.spec

На этом этапе вы можете просто создать новый perf, если хотите:

  • cd $HOME/rpmbuild/BUILD/kernel-*/linux-*/tools/perf
  • make

... который я сделал и протестировал, что обновленный perf действительно захватывает полезный стек, если он построен с доступным libunwind.

Вы также можете создать новый rpm:

  • отредактируйте kernel.spec, раскомментируйте строку %define buildid ..., измените buildid на что-то вроде .perfunwind. Обратите внимание: %define not % define.

  • В том же файле spec найдите

    %global perf_make \
    make %{?_smp_mflags} -C tools/perf -s V=1 WERROR=0 NO_LIBUNWIND=1 HAVE_CPLUS_DEMANGLE=1 NO_GTK2=1 NO_LIBNUMA=1 NO_STRLCPY=1 prefix=%{_prefix}
    

    и удалите NO_LIBUNWIND=1

  • rpmbuild -bb --without up --without mp --without pae --without debug --without doc --without headers --without debuginfo --without bootwrapper --without with_vdso_install --with perf kernel.spec для создания новых perf RPM без создания всего ядра. Или, если хотите, опустите --without для нужного вам вкуса ядра, и в этом случае вы также захотите создать заголовки, debuginfo и т.д.

  • sudo rpm -Uvh $HOME/rpmbuild/RPMS/x86_64/perf-*.fc19.x86_64.rpm

Смотрите руководство проекта Fedora по созданию настраиваемого ядра.

Я сообщил об этом Fedora; они не должны использовать NO_LIBUNWIND=1. См. ошибка 1025603.

Как только у вас есть восстановленный perf, вы можете использовать perf record -g dwarf, чтобы получить полные стеки.