/*
* 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_