/*
|
* Copyright (c) 2016, Google Inc.
|
* All rights reserved.
|
* Use of this source code is governed by a BSD-style license that can be
|
* found in the LICENSE file.
|
*/
|
|
#ifndef PERFTOOLS_PERF_DATA_HANDLER_H_
|
#define PERFTOOLS_PERF_DATA_HANDLER_H_
|
|
#include <vector>
|
|
#include "int_compat.h"
|
#include "string_compat.h"
|
#include "quipper/perf_data.pb.h"
|
|
namespace perftools {
|
|
// PerfDataHandler defines an interface for processing PerfDataProto
|
// with normalized sample fields (i.e., materializing mappings,
|
// filenames, and build-ids).
|
//
|
// To use, subclass PerfDataHandler and implement the required
|
// methods, then call Process() and handler will be called for every
|
// SAMPLE event.
|
//
|
// Context events' pointers to Mappings will be constant for the lifetime of a
|
// process, so subclasses may use the pointer values as a key to various caches
|
// they may want to maintain as part of the output data creation.
|
class PerfDataHandler {
|
public:
|
struct Mapping {
|
public:
|
Mapping(const string* filename, const string* build_id, uint64 start,
|
uint64 limit, uint64 file_offset, uint64 filename_md5_prefix)
|
: filename(filename),
|
build_id(build_id),
|
start(start),
|
limit(limit),
|
file_offset(file_offset),
|
filename_md5_prefix(filename_md5_prefix) {}
|
|
// filename and build_id are pointers into the provided
|
// PerfDataProto and may be nullptr.
|
const string* filename;
|
const string* build_id;
|
uint64 start;
|
uint64 limit; // limit=ceiling.
|
uint64 file_offset;
|
uint64 filename_md5_prefix;
|
|
private:
|
Mapping() {}
|
};
|
|
struct Location {
|
Location() : ip(0), mapping(nullptr) {}
|
|
uint64 ip;
|
const Mapping* mapping;
|
};
|
|
struct BranchStackPair {
|
BranchStackPair() : mispredicted(false) {}
|
|
Location from;
|
Location to;
|
bool mispredicted;
|
};
|
|
struct SampleContext {
|
SampleContext(const quipper::PerfDataProto::EventHeader &h,
|
const quipper::PerfDataProto::SampleEvent &s)
|
: header(h),
|
sample(s),
|
main_mapping(nullptr),
|
sample_mapping(nullptr),
|
file_attrs_index(-1) {}
|
|
// The event's header.
|
const quipper::PerfDataProto::EventHeader &header;
|
// An event.
|
const quipper::PerfDataProto::SampleEvent &sample;
|
// The mapping for the main binary for this program.
|
const Mapping* main_mapping;
|
// The mapping in which event.ip is found.
|
const Mapping* sample_mapping;
|
// Locations corresponding to event.callchain.
|
std::vector<Location> callchain;
|
// Locations corresponding to entries in event.branch_stack.
|
std::vector<BranchStackPair> branch_stack;
|
// An index into PerfDataProto.file_attrs or -1 if
|
// unavailable.
|
int64 file_attrs_index;
|
};
|
|
struct CommContext {
|
// A comm event.
|
const quipper::PerfDataProto::CommEvent* comm;
|
};
|
|
struct MMapContext {
|
// A memory mapping to be passed to the subclass. Should be the same mapping
|
// that gets added to pid_to_mmaps_.
|
const PerfDataHandler::Mapping* mapping;
|
// The process id used as a key to pid_to_mmaps_.
|
uint32 pid;
|
};
|
|
PerfDataHandler(const PerfDataHandler&) = delete;
|
PerfDataHandler& operator=(const PerfDataHandler&) = delete;
|
|
// Process initiates processing of perf_proto. handler.Sample will
|
// be called for every event in the profile.
|
static void Process(const quipper::PerfDataProto& perf_data,
|
PerfDataHandler* handler);
|
|
virtual ~PerfDataHandler() {}
|
|
// Implement these callbacks:
|
// Called for every sample.
|
virtual void Sample(const SampleContext& sample) = 0;
|
// When comm.pid()==comm.tid() it indicates an exec() happened.
|
virtual void Comm(const CommContext& comm) = 0;
|
// Called for every mmap event.
|
virtual void MMap(const MMapContext& mmap) = 0;
|
|
protected:
|
PerfDataHandler();
|
};
|
|
} // namespace perftools
|
|
#endif // PERFTOOLS_PERF_DATA_HANDLER_H_
|