ronnie
2022-10-23 cb8ede114f8c3e5ead5b294f66344b8a42004745
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 * 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_