В настоящее время я вызываю oprofile со следующими параметрами:
operf --callgraph --vmlinux /usr/lib/debug/boot/vmlinux-$(uname -r) <BINARY>
opreport -a -l <BINARY>
В качестве примера, вывод:
CPU: Core 2, speed 2e+06 MHz (estimated)
Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 90000
samples cum. samples % cum. % image name symbol name
12635 12635 27.7674 27.7674 libc-2.15.so __memset_sse2
9404 22039 20.6668 48.4342 vmlinux-3.5.0-21-generic get_page_from_freelist
4381 26420 9.6279 58.0621 vmlinux-3.5.0-21-generic native_flush_tlb_single
3684 30104 8.0962 66.1583 vmlinux-3.5.0-21-generic page_fault
701 30805 1.5406 67.6988 vmlinux-3.5.0-21-generic handle_pte_fault
Вы можете видеть, что большая часть времени проводится в течение __memset_sse2
но не очевидно, какой мой собственный код должен быть оптимизирован. По крайней мере, не из вывода выше.
В моем конкретном случае я смог быстро определить источник проблемы, используя какой-то профиль для бедного человека. Я запустил программу в отладчике, время от времени останавливал ее и просматривал стеки вызовов каждого потока.
Можно ли получить те же результаты непосредственно из вывода oprofile? Стратегия, которую я использовал, скорее всего потерпит неудачу, если узкое место в производительности не так очевидно, как в моем примере.
Есть ли возможность игнорировать все вызовы внешней функции (например, ядра или libc) и просто накапливать время для вызывающей стороны? Например:
void foo() {
// some expensive call to memset...
}
Здесь было бы более проницательным для меня, чтобы увидеть foo
в верхней части вывода профилирования, а не memset
,
(Я старался opreport --exclude-dependent
но нашел это бесполезным, так как кажется, что пропускает только внешние функции в выводе.)
Задача ещё не решена.
Других решений пока нет …