示例#1
0
/**
 * Print the recorded profiling information to the specified file.
 */
void profile_print_info(FILE* f) {
  typedef std::vector< std::pair<Key, size_t> > BacktraceVector;

  CountGreater is_greater;

  // Grab both locks for the duration of the print operation,
  // to ensure the output is a consistent snapshot of a single point in time
  Guard generic_calls_guard(generic_calls_mutex);
  Guard virtual_calls_guard(virtual_calls_mutex);

  // print the info from generic_calls, sorted by frequency
  //
  // We print the generic_calls info ahead of virtual_calls, since it is more
  // useful in some cases.  All T_GENERIC_PROTOCOL calls can be eliminated
  // from most programs.  Not all T_VIRTUAL_CALLs will be eliminated by
  // converting to templates.
  BacktraceVector gp_sorted(generic_calls.begin(), generic_calls.end());
  std::sort(gp_sorted.begin(), gp_sorted.end(), is_greater);

  for (BacktraceVector::const_iterator it = gp_sorted.begin();
       it != gp_sorted.end();
       ++it) {
    Key const &key = it->first;
    size_t const count = it->second;
    fprintf(f, "T_GENERIC_PROTOCOL: %zu calls to %s with a %s:\n",
            count, key.getTypeName(), key.getTypeName2());
    key.getBacktrace()->print(f, 2);
    fprintf(f, "\n");
  }

  // print the info from virtual_calls, sorted by frequency
  BacktraceVector vc_sorted(virtual_calls.begin(), virtual_calls.end());
  std::sort(vc_sorted.begin(), vc_sorted.end(), is_greater);

  for (BacktraceVector::const_iterator it = vc_sorted.begin();
       it != vc_sorted.end();
       ++it) {
    Key const &key = it->first;
    size_t const count = it->second;
    fprintf(f, "T_VIRTUAL_CALL: %zu calls on %s:\n", count, key.getTypeName());
    key.getBacktrace()->print(f, 2);
    fprintf(f, "\n");
  }
}
示例#2
0
/**
 * Write a BacktraceMap as Google CPU profiler binary data.
 */
static void profile_write_pprof_file(FILE* f, BacktraceMap const& map) {
  // Write the header
  uintptr_t header[5] = { 0, 3, 0, 0, 0 };
  fwrite(&header, sizeof(header), 1, f);

  // Write the profile records
  for (BacktraceMap::const_iterator it = map.begin(); it != map.end(); ++it) {
    uintptr_t count = it->second;
    fwrite(&count, sizeof(count), 1, f);

    Backtrace const* bt = it->first.getBacktrace();
    uintptr_t num_pcs = bt->getDepth();
    fwrite(&num_pcs, sizeof(num_pcs), 1, f);

    for (uintptr_t n = 0; n < num_pcs; ++n) {
      void* pc = bt->getFrame(n);
      fwrite(&pc, sizeof(pc), 1, f);
    }
  }

  // Write the trailer
  uintptr_t trailer[3] = { 0, 1, 0 };
  fwrite(&trailer, sizeof(trailer), 1, f);

  // Write /proc/self/maps
  // TODO(simpkins): This only works on linux
  FILE *proc_maps = fopen("/proc/self/maps", "r");
  if (proc_maps) {
    uint8_t buf[4096];
    while (true) {
      size_t bytes_read = fread(buf, 1, sizeof(buf), proc_maps);
      if (bytes_read == 0) {
        break;
      }
      fwrite(buf, 1, bytes_read, f);
    }
    fclose(proc_maps);
  }
}