Home | History | Annotate | Download | only in perfprofd
      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