1 2 #include "perf_data_converter.h" 3 #include "quipper/perf_parser.h" 4 #include <map> 5 6 using std::map; 7 8 namespace wireless_android_logging_awp { 9 10 struct RangeTarget { 11 RangeTarget(uint64 start, uint64 end, uint64 to) 12 : start(start), end(end), to(to) {} 13 14 bool operator<(const RangeTarget &r) const { 15 if (start != r.start) { 16 return start < r.start; 17 } else if (end != r.end) { 18 return end < r.end; 19 } else { 20 return to < r.to; 21 } 22 } 23 uint64 start; 24 uint64 end; 25 uint64 to; 26 }; 27 28 struct BinaryProfile { 29 map<uint64, uint64> address_count_map; 30 map<RangeTarget, uint64> range_count_map; 31 }; 32 33 wireless_android_play_playlog::AndroidPerfProfile 34 RawPerfDataToAndroidPerfProfile(const string &perf_file) { 35 wireless_android_play_playlog::AndroidPerfProfile ret; 36 quipper::PerfParser parser; 37 if (!parser.ReadFile(perf_file) || !parser.ParseRawEvents()) { 38 return ret; 39 } 40 41 typedef map<string, BinaryProfile> ModuleProfileMap; 42 typedef map<string, ModuleProfileMap> ProgramProfileMap; 43 ProgramProfileMap name_profile_map; 44 uint64 total_samples = 0; 45 for (const auto &event : parser.parsed_events()) { 46 if (!event.raw_event || 47 event.raw_event->header.type != PERF_RECORD_SAMPLE) { 48 continue; 49 } 50 string dso_name = event.dso_and_offset.dso_name(); 51 string program_name; 52 if (dso_name == "[kernel.kallsyms]_text") { 53 program_name = "kernel"; 54 dso_name = "[kernel.kallsyms]"; 55 } else if (event.command() == "") { 56 program_name = "unknown_program"; 57 } else { 58 program_name = event.command(); 59 } 60 name_profile_map[program_name][dso_name].address_count_map[ 61 event.dso_and_offset.offset()]++; 62 total_samples++; 63 for (size_t i = 1; i < event.branch_stack.size(); i++) { 64 if (dso_name == event.branch_stack[i - 1].to.dso_name()) { 65 uint64 start = event.branch_stack[i].to.offset(); 66 uint64 end = event.branch_stack[i - 1].from.offset(); 67 uint64 to = event.branch_stack[i - 1].to.offset(); 68 // The interval between two taken branches should not be too large. 69 if (end < start || end - start > (1 << 20)) { 70 LOG(WARNING) << "Bogus LBR data: " << start << "->" << end; 71 continue; 72 } 73 name_profile_map[program_name][dso_name].range_count_map[ 74 RangeTarget(start, end, to)]++; 75 } 76 } 77 } 78 79 map<string, int> name_id_map; 80 for (const auto &program_profile : name_profile_map) { 81 for (const auto &module_profile : program_profile.second) { 82 name_id_map[module_profile.first] = 0; 83 } 84 } 85 int current_index = 0; 86 for (auto iter = name_id_map.begin(); iter != name_id_map.end(); ++iter) { 87 iter->second = current_index++; 88 } 89 90 map<string, string> name_buildid_map; 91 parser.GetFilenamesToBuildIDs(&name_buildid_map); 92 ret.set_total_samples(total_samples); 93 for (const auto &name_id : name_id_map) { 94 auto load_module = ret.add_load_modules(); 95 load_module->set_name(name_id.first); 96 auto nbmi = name_buildid_map.find(name_id.first); 97 if (nbmi != name_buildid_map.end()) { 98 const std::string &build_id = nbmi->second; 99 if (build_id.size() == 40 && build_id.substr(32) == "00000000") { 100 load_module->set_build_id(build_id.substr(0, 32)); 101 } else { 102 load_module->set_build_id(build_id); 103 } 104 } 105 } 106 for (const auto &program_profile : name_profile_map) { 107 auto program = ret.add_programs(); 108 program->set_name(program_profile.first); 109 for (const auto &module_profile : program_profile.second) { 110 int32 module_id = name_id_map[module_profile.first]; 111 auto module = program->add_modules(); 112 module->set_load_module_id(module_id); 113 for (const auto &addr_count : module_profile.second.address_count_map) { 114 auto address_samples = module->add_address_samples(); 115 address_samples->add_address(addr_count.first); 116 address_samples->set_count(addr_count.second); 117 } 118 for (const auto &range_count : module_profile.second.range_count_map) { 119 auto range_samples = module->add_range_samples(); 120 range_samples->set_start(range_count.first.start); 121 range_samples->set_end(range_count.first.end); 122 range_samples->set_to(range_count.first.to); 123 range_samples->set_count(range_count.second); 124 } 125 } 126 } 127 return ret; 128 } 129 130 } // namespace wireless_android_logging_awp 131