summaryrefslogtreecommitdiff
path: root/simpleperf
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2015-08-18 16:32:18 -0700
committerYabin Cui <yabinc@google.com>2015-08-18 17:58:41 -0700
commitb10a8fb990f71351558ed07b84b57ad5cafe993a (patch)
tree2a2813190e999d55c3ba60acdafc7cfed705d815 /simpleperf
parent2c0f9f263cd6c3857850c7d3a8f2aabb63ce48be (diff)
downloadextras-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.cpp11
-rw-r--r--simpleperf/dso.cpp86
-rw-r--r--simpleperf/dso.h12
-rw-r--r--simpleperf/thread_tree.h7
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);