2015-12-11 14 views
6

Chciałem zrobić perfekcję, aby profilować niektóre programy po tym, jak zobaczyłem this rozmowę z CppCon 2015. Pobrałem tę samą bibliotekę testową Google, której używa gość w rozmowie, skompilowałem program z odpowiednimi przełącznikami , połączyłem go z nim, a następnie użyłem perf, aby nagrać przebieg. Opcja raport daje mi to:Perf pokazuje zniekształcone nazwy funkcji

enter image description here

Jak widać nazwy funkcji nie są bardzo czytelne. Zakładam, że ma to związek z mangowaniem nazw w C++. Co ciekawe, wszystkie nazwy funkcji pojawiają się poprawnie w filmie dla faceta, który wygłaszał przemówienie, ale nie dla mnie. Nie sądzę, że jest to przypadek całkowitego braku informacji o symbolu, ponieważ widzę w tym przypadku tylko adresy pamięci. Z jakiegoś powodu perf nie może "cofnąć" mylingowania nazwy C++, co jest frustrujące.

Używam gcc (g ++) wersja 5.2.1, wersja 4.2.6 jest perf i używam tych przełączników podczas kompilacji:

-I<my own include path> -L<path to the benchmark library> -O3 -std=c++14 -gdwarf-2 -fno-rtti -Wall -pedantic -lbenchmark -pthread

Powodem dlaczego nie używam -fno-omit-frame-pointer jest to, że używam opcji -gdwarf-2, która pozostawia informacje o debugowaniu w pliku wykonywalnym karłów, co jest alternatywą dla pozostawienia wskaźnika ramki w tym przypadku. Oznacza to również, że przekazuję --call-graph "dwarf" do perf record. W każdym razie spróbowałem również metody wskaźnika ramki i daje takie same wyniki, więc to nie ma znaczenia.

Dlaczego więc nie perfekcyjnie "cofnąć" mylenie nazwy C++ w tym przypadku? Czy ma to coś wspólnego z używaniem GCC, co oczywiście oznacza, że ​​używam libstdC++?

+1

Używam Arch Linux a 'perf report' pokazuje poprawną zmianę symbolu. Strona podręcznika perf również pokazuje opcję '--demangle', która jest domyślnie włączona. Ponieważ nie widzę takiego zachowania jak ty, nie mam odpowiedzi, ale to, co widzisz, nie jest domyślnym zachowaniem. –

+0

Próbowałem dodać również ten przełącznik ręcznie, ale nic to nie zmieniło – adam10603

+0

@GabrielSouthern Czy używasz również gcc? – adam10603

Odpowiedz

1

Kiedy perf report daje zniekształcone nazwy jak _Z*, _ZN*, _ZL* etc, oznacza to, że narzędzie perf został skompilowany bez dostępu do funkcji demangling lub ona wyłączona. Jest kod do wykrywania demangler w Makefile:

http://elixir.free-electrons.com/linux/v4.2.6/source/tools/perf/Makefile.perf

# Define NO_DEMANGLE if you do not want C++ symbol demangling. 
# Define NO_LIBELF if you do not want libelf dependency (e.g. cross-builds) 

http://elixir.free-electrons.com/linux/v4.2.6/source/tools/perf/config/Makefile

ifdef NO_LIBELF 
... 
    NO_DEMANGLE := 1 
... 
else 
    ifeq ($(feature-libelf), 0) 
    ifeq ($(feature-glibc), 1) 
     LIBC_SUPPORT := 1 
    endif 
    ... 
    ifeq ($(LIBC_SUPPORT),1) 
     ... 
     NO_DEMANGLE := 1 
    ... 

Testy znajdują się w katalogu tools/build/feature: http://elixir.free-electrons.com/linux/v4.2.6/source/tools/build/feature i libelf funkcja jest włączona, jeśli program testowy używając elf_begin funkcję libelf (<libelf.h> header of elfutils package, -lelf linkowanie) jest dostępny (i zwraca coś? Czy jest uruchomiony test? kompiluje się, gdy konstruktor jądra nie może uruchamiać plików binarnych celu maszynowego elfa bezpośrednio z ./test-libelf.bin i musi używać ssh do prawdziwej maszyny lub do jakiegoś użytkownika/systemu qemu?).

I kod w realizacji perf zrobić demangling (używając cplus_demangle jeśli HAVE_CPLUS_DEMANGLE_SUPPORT zdefiniowane za pomocą żadnego demangle jest NO_DEMANGLE jest ustawiony po Makefile, używając bfd.h i bfd_demangle funkcję docs - 2.3.1.24 bfd_demangle): http://elixir.free-electrons.com/linux/v4.2.6/source/tools/perf/util/symbol-elf.c#L19

#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT 
extern char *cplus_demangle(const char *, int); 

static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i) 
{ 
    return cplus_demangle(c, i); 
} 
#else 
#ifdef NO_DEMANGLE 
static inline char *bfd_demangle(void __maybe_unused *v, 
       const char __maybe_unused *c, 
       int __maybe_unused i) 
{ 
    return NULL; 
} 
#else 
#define PACKAGE 'perf' 
#include <bfd.h> 
#endif 

ten wszystko jest trochę dziwne (nadal nie ma standardowej funkcji C++ demangle w świecie Linuksa w erze postu C++ 11?). I Twój perf został źle skompilowany lub źle skonfigurowany - to jest powód, dla którego nie demoluje nazw.billyw linked answer przez Michal Fapso który mówi, że to błąd 1396654 z ubuntu - https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1396654.

Można zrobić siekać filtrowania wyjściu perf z c++filt programu, ale to uniemożliwić korzystanie z interaktywnego domyślny interfejs TUI z perf (dodaj less lub pisać do plików tekstowych, aby zobaczyć bardzo długie ofert z normalnym PageDown/PageUp):

perf report | c++filt | less 
perf annotate function_name | c++filt | less 
# or: perf annotate -s function_name | c++filt | less 

Albo można aktualizować/przekompilować perf jak sugeruje billyw w his comment

4^wydaje się, że jesteś na Ubuntu. Podejrzewam, że to jest twój problem i rozwiązanie: https://stackoverflow.com/a/34061874/2166274 - Billyw Mar 3 '16 o 17:31