diff options
author | Yabin Cui <yabinc@google.com> | 2015-08-18 16:32:18 -0700 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2015-08-18 17:58:41 -0700 |
commit | b10a8fb990f71351558ed07b84b57ad5cafe993a (patch) | |
tree | 2a2813190e999d55c3ba60acdafc7cfed705d815 /simpleperf | |
parent | 2c0f9f263cd6c3857850c7d3a8f2aabb63ce48be (diff) | |
download | extras-b10a8fb990f71351558ed07b84b57ad5cafe993a.tar.gz |
Simpleperf: demangle symbols only when necessary.
Before this change:
$sudo simpleperf record -a sleep 1
$sudo simpleperf stat simpleperf report
Total test time: 4.088779 seconds.
After this change:
$sudo simpleperf record -a sleep 1
$sudo simpleperf stat simpleperf report
Total test time: 1.226267 seconds.
Change-Id: Ifc811f432ac69f770eeb5814e4983f6f19dbc909
Diffstat (limited to 'simpleperf')
-rw-r--r-- | simpleperf/cmd_report.cpp | 11 | ||||
-rw-r--r-- | simpleperf/dso.cpp | 86 | ||||
-rw-r--r-- | simpleperf/dso.h | 12 | ||||
-rw-r--r-- | simpleperf/thread_tree.h | 7 |
4 files changed, 59 insertions, 57 deletions
diff --git a/simpleperf/cmd_report.cpp b/simpleperf/cmd_report.cpp index e7f98f73..5d08993c 100644 --- a/simpleperf/cmd_report.cpp +++ b/simpleperf/cmd_report.cpp @@ -179,11 +179,12 @@ class SymbolItem : public Displayable, public Comparable { } int Compare(const SampleEntry& sample1, const SampleEntry& sample2) const override { - return strcmp(sample1.symbol->name.c_str(), sample2.symbol->name.c_str()); + return strcmp(sample1.symbol->GetDemangledName().c_str(), + sample2.symbol->GetDemangledName().c_str()); } std::string Show(const SampleEntry& sample) const override { - return sample.symbol->name; + return sample.symbol->GetDemangledName(); } }; @@ -214,12 +215,12 @@ class SymbolFromItem : public Displayable, public Comparable { } int Compare(const SampleEntry& sample1, const SampleEntry& sample2) const override { - return strcmp(sample1.branch_from.symbol->name.c_str(), - sample2.branch_from.symbol->name.c_str()); + return strcmp(sample1.branch_from.symbol->GetDemangledName().c_str(), + sample2.branch_from.symbol->GetDemangledName().c_str()); } std::string Show(const SampleEntry& sample) const override { - return sample.branch_from.symbol->name; + return sample.branch_from.symbol->GetDemangledName(); } }; diff --git a/simpleperf/dso.cpp b/simpleperf/dso.cpp index ca45c2d3..55963c2a 100644 --- a/simpleperf/dso.cpp +++ b/simpleperf/dso.cpp @@ -22,6 +22,13 @@ #include "read_elf.h" #include "utils.h" +const std::string& SymbolEntry::GetDemangledName() const { + if (demangled_name_.empty()) { + demangled_name_ = DsoFactory::GetInstance()->Demangle(name); + } + return demangled_name_; +} + bool SymbolComparator::operator()(const std::unique_ptr<SymbolEntry>& symbol1, const std::unique_ptr<SymbolEntry>& symbol2) { return symbol1->addr < symbol2->addr; @@ -103,6 +110,33 @@ std::unique_ptr<DsoEntry> DsoFactory::CreateDso(DsoType dso_type, const std::str return std::unique_ptr<DsoEntry>(new DsoEntry(dso_type, path)); } +extern "C" char* __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status); + +std::string DsoFactory::Demangle(const std::string& name) { + if (!demangle_) { + return name; + } + int status; + bool is_linker_symbol = (name.find(linker_prefix) == 0); + const char* mangled_str = name.c_str(); + if (is_linker_symbol) { + mangled_str += linker_prefix.size(); + } + std::string result = name; + char* demangled_name = __cxa_demangle(mangled_str, nullptr, nullptr, &status); + if (status == 0) { + if (is_linker_symbol) { + result = std::string("[linker]") + demangled_name; + } else { + result = demangled_name; + } + free(demangled_name); + } else if (is_linker_symbol) { + result = std::string("[linker]") + mangled_str; + } + return result; +} + bool DsoFactory::LoadDso(DsoEntry* dso) { switch (dso->type) { case DSO_KERNEL: @@ -122,24 +156,16 @@ static bool IsKernelFunctionSymbol(const KernelSymbol& symbol) { static bool KernelSymbolCallback(const KernelSymbol& kernel_symbol, DsoEntry* dso) { if (IsKernelFunctionSymbol(kernel_symbol)) { - SymbolEntry* symbol = new SymbolEntry{ - kernel_symbol.name, // name - kernel_symbol.addr, // addr - 0, // len - }; - dso->symbols.insert(std::unique_ptr<SymbolEntry>(symbol)); + dso->symbols.insert( + std::unique_ptr<SymbolEntry>(new SymbolEntry(kernel_symbol.name, kernel_symbol.addr, 0))); } return false; } static void VmlinuxSymbolCallback(const ElfFileSymbol& elf_symbol, DsoEntry* dso) { if (elf_symbol.is_func) { - SymbolEntry* symbol = new SymbolEntry{ - elf_symbol.name, // name - elf_symbol.vaddr, // addr - elf_symbol.len, // len - }; - dso->symbols.insert(std::unique_ptr<SymbolEntry>(symbol)); + dso->symbols.insert(std::unique_ptr<SymbolEntry>( + new SymbolEntry(elf_symbol.name, elf_symbol.vaddr, elf_symbol.len))); } } @@ -182,12 +208,8 @@ bool DsoFactory::LoadKernel(DsoEntry* dso) { static void ParseSymbolCallback(const ElfFileSymbol& elf_symbol, DsoEntry* dso, bool (*filter)(const ElfFileSymbol&)) { if (filter(elf_symbol)) { - SymbolEntry* symbol = new SymbolEntry{ - elf_symbol.name, // name - elf_symbol.start_in_file, // addr - elf_symbol.len, // len - }; - dso->symbols.insert(std::unique_ptr<SymbolEntry>(symbol)); + dso->symbols.insert(std::unique_ptr<SymbolEntry>( + new SymbolEntry(elf_symbol.name, elf_symbol.start_in_file, elf_symbol.len))); } } @@ -209,39 +231,11 @@ static bool SymbolFilterForDso(const ElfFileSymbol& elf_symbol) { return elf_symbol.is_func || (elf_symbol.is_label && elf_symbol.is_in_text_section); } -extern "C" char* __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status); - -static void DemangleInPlace(std::string* name) { - int status; - bool is_linker_symbol = (name->find(linker_prefix) == 0); - const char* mangled_str = name->c_str(); - if (is_linker_symbol) { - mangled_str += linker_prefix.size(); - } - char* demangled_name = __cxa_demangle(mangled_str, nullptr, nullptr, &status); - if (status == 0) { - if (is_linker_symbol) { - *name = std::string("[linker]") + demangled_name; - } else { - *name = demangled_name; - } - free(demangled_name); - } else if (is_linker_symbol) { - std::string temp = std::string("[linker]") + mangled_str; - *name = std::move(temp); - } -} - bool DsoFactory::LoadElfFile(DsoEntry* dso) { BuildId build_id = GetExpectedBuildId(dso->path); ParseSymbolsFromElfFile( symfs_dir_ + dso->path, build_id, std::bind(ParseSymbolCallback, std::placeholders::_1, dso, SymbolFilterForDso)); - if (demangle_) { - for (auto& symbol : dso->symbols) { - DemangleInPlace(&symbol->name); - } - } FixupSymbolLength(dso); return true; } diff --git a/simpleperf/dso.h b/simpleperf/dso.h index 8b83000b..5e44a994 100644 --- a/simpleperf/dso.h +++ b/simpleperf/dso.h @@ -29,6 +29,15 @@ struct SymbolEntry { std::string name; uint64_t addr; uint64_t len; + + SymbolEntry(const std::string& name, uint64_t addr, uint64_t len) + : name(name), addr(addr), len(len) { + } + + const std::string& GetDemangledName() const; + + private: + mutable std::string demangled_name_; }; struct SymbolComparator { @@ -57,11 +66,14 @@ struct DsoEntry { class DsoFactory { public: static DsoFactory* GetInstance(); + void SetDemangle(bool demangle); bool SetSymFsDir(const std::string& symfs_dir); void SetVmlinux(const std::string& vmlinux); void SetBuildIds(const std::vector<std::pair<std::string, BuildId>>& build_ids); + std::unique_ptr<DsoEntry> CreateDso(DsoType dso_type, const std::string& dso_path = ""); + std::string Demangle(const std::string& name); bool LoadDso(DsoEntry* dso); private: diff --git a/simpleperf/thread_tree.h b/simpleperf/thread_tree.h index ea52f97d..c0ec3ea4 100644 --- a/simpleperf/thread_tree.h +++ b/simpleperf/thread_tree.h @@ -43,7 +43,7 @@ struct ThreadEntry { class ThreadTree { public: - ThreadTree() : unknown_dso_(DSO_ELF_FILE, "unknown") { + ThreadTree() : unknown_dso_(DSO_ELF_FILE, "unknown"), unknown_symbol_("unknown", 0, ULLONG_MAX) { unknown_map_ = MapEntry{ 0, // start_addr ULLONG_MAX, // len @@ -51,11 +51,6 @@ class ThreadTree { 0, // time &unknown_dso_, // dso }; - unknown_symbol_ = SymbolEntry{ - "unknown", // name - 0, // addr - ULLONG_MAX, // len - }; } void AddThread(int pid, int tid, const std::string& comm); |