blob: f145e80fe7448068684d3b8381272288060e7ff6 [file] [log] [blame]
Yabin Cui9759e1b2015-04-28 15:54:13 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SIMPLE_PERF_RECORD_H_
18#define SIMPLE_PERF_RECORD_H_
19
Yabin Cuib7f481f2015-10-23 19:48:42 -070020#include <stdio.h>
Dan Albert918e4b72015-08-11 15:59:43 -070021#include <sys/types.h>
22
Yabin Cuiffaa9122016-01-15 15:25:48 -080023#include <memory>
Yabin Cuif469c3d2015-10-07 15:00:46 -070024#include <queue>
Yabin Cui9759e1b2015-04-28 15:54:13 -070025#include <string>
26#include <vector>
27
Yabin Cuib4212972016-05-25 14:08:05 -070028#include <android-base/logging.h>
29
Yabin Cui8f622512015-05-05 19:58:07 -070030#include "build_id.h"
Yabin Cui9759e1b2015-04-28 15:54:13 -070031#include "perf_event.h"
32
33struct KernelMmap;
34struct ModuleMmap;
35struct ThreadComm;
36struct ThreadMmap;
37
38enum user_record_type {
Yabin Cuib4212972016-05-25 14:08:05 -070039 PERF_RECORD_USER_DEFINED_TYPE_START = 64,
Yabin Cui9759e1b2015-04-28 15:54:13 -070040 PERF_RECORD_ATTR = 64,
41 PERF_RECORD_EVENT_TYPE,
42 PERF_RECORD_TRACING_DATA,
43 PERF_RECORD_BUILD_ID,
44 PERF_RECORD_FINISHED_ROUND,
Yabin Cuib4212972016-05-25 14:08:05 -070045
46 SIMPLE_PERF_RECORD_TYPE_START = 32768,
47 SIMPLE_PERF_RECORD_KERNEL_SYMBOL,
Yabin Cui767dd172016-06-02 21:02:43 -070048 SIMPLE_PERF_RECORD_DSO,
49 SIMPLE_PERF_RECORD_SYMBOL,
Yabin Cui9759e1b2015-04-28 15:54:13 -070050};
51
52struct PerfSampleIpType {
53 uint64_t ip;
54};
55
56struct PerfSampleTidType {
57 uint32_t pid, tid;
58};
59
60struct PerfSampleTimeType {
61 uint64_t time;
62};
63
64struct PerfSampleAddrType {
65 uint64_t addr;
66};
67
68struct PerfSampleIdType {
69 uint64_t id;
70};
71
72struct PerfSampleStreamIdType {
73 uint64_t stream_id;
74};
75
76struct PerfSampleCpuType {
77 uint32_t cpu, res;
78};
79
80struct PerfSamplePeriodType {
81 uint64_t period;
82};
83
Yabin Cui6e8a9a42015-06-15 14:36:43 -070084struct PerfSampleCallChainType {
85 std::vector<uint64_t> ips;
86};
87
Yabin Cuibfc11b62015-08-19 10:12:51 -070088struct PerfSampleRawType {
89 std::vector<char> data;
90};
91
Yabin Cuib64a8632016-05-24 18:23:33 -070092struct BranchStackItemType {
93 uint64_t from;
94 uint64_t to;
95 uint64_t flags;
96};
97
Yabin Cuiddddc062015-06-02 17:54:52 -070098struct PerfSampleBranchStackType {
Yabin Cuiddddc062015-06-02 17:54:52 -070099 std::vector<BranchStackItemType> stack;
100};
101
Yabin Cui76769e52015-07-13 12:23:54 -0700102struct PerfSampleRegsUserType {
103 uint64_t abi;
104 uint64_t reg_mask;
105 std::vector<uint64_t> regs;
106};
107
108struct PerfSampleStackUserType {
109 std::vector<char> data;
110 uint64_t dyn_size;
111};
112
Yabin Cui767dd172016-06-02 21:02:43 -0700113// SampleId is optional at the end of a record in binary format. Its content is
114// determined by sample_id_all and sample_type in perf_event_attr. To avoid the
115// complexity of referring to perf_event_attr each time, we copy sample_id_all
116// and sample_type inside the SampleId structure.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700117struct SampleId {
118 bool sample_id_all;
119 uint64_t sample_type;
120
Yabin Cui767dd172016-06-02 21:02:43 -0700121 PerfSampleTidType tid_data; // Valid if sample_id_all && PERF_SAMPLE_TID.
122 PerfSampleTimeType time_data; // Valid if sample_id_all && PERF_SAMPLE_TIME.
123 PerfSampleIdType id_data; // Valid if sample_id_all && PERF_SAMPLE_ID.
124 PerfSampleStreamIdType
125 stream_id_data; // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
126 PerfSampleCpuType cpu_data; // Valid if sample_id_all && PERF_SAMPLE_CPU.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700127
128 SampleId();
129
130 // Create the content of sample_id. It depends on the attr we use.
Yabin Cui2d6efe42016-04-01 20:22:35 -0700131 size_t CreateContent(const perf_event_attr& attr, uint64_t event_id);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700132
133 // Parse sample_id from binary format in the buffer pointed by p.
Yabin Cui767dd172016-06-02 21:02:43 -0700134 void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p,
135 const char* end);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700136
137 // Write the binary format of sample_id to the buffer pointed by p.
138 void WriteToBinaryFormat(char*& p) const;
139 void Dump(size_t indent) const;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800140 size_t Size() const;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700141};
142
Yabin Cui767dd172016-06-02 21:02:43 -0700143// Usually one record contains the following three parts in order in binary
144// format:
145// perf_event_header (at the head of a record, containing type and size info)
Yabin Cui9759e1b2015-04-28 15:54:13 -0700146// data depends on the record type
147// sample_id (optional part at the end of a record)
Yabin Cui767dd172016-06-02 21:02:43 -0700148// We hold the common parts (perf_event_header and sample_id) in the base class
149// Record, and hold the type specific data part in classes derived from Record.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700150struct Record {
151 perf_event_header header;
152 SampleId sample_id;
153
Yabin Cui767dd172016-06-02 21:02:43 -0700154 Record() { memset(&header, 0, sizeof(header)); }
155 Record(const perf_event_header* pheader) { header = *pheader; }
Yabin Cui9759e1b2015-04-28 15:54:13 -0700156
Yabin Cui767dd172016-06-02 21:02:43 -0700157 virtual ~Record() {}
Yabin Cuib7f481f2015-10-23 19:48:42 -0700158
Yabin Cui767dd172016-06-02 21:02:43 -0700159 uint32_t type() const { return header.type; }
Yabin Cuib7f481f2015-10-23 19:48:42 -0700160
Yabin Cui767dd172016-06-02 21:02:43 -0700161 uint16_t misc() const { return header.misc; }
Yabin Cuib4212972016-05-25 14:08:05 -0700162
Yabin Cui767dd172016-06-02 21:02:43 -0700163 size_t size() const { return header.size; }
Yabin Cuib4212972016-05-25 14:08:05 -0700164
Yabin Cui767dd172016-06-02 21:02:43 -0700165 static uint32_t header_size() { return sizeof(perf_event_header); }
Yabin Cuib4212972016-05-25 14:08:05 -0700166
Yabin Cuib64a8632016-05-24 18:23:33 -0700167 bool InKernel() const {
Yabin Cui767dd172016-06-02 21:02:43 -0700168 return (header.misc & PERF_RECORD_MISC_CPUMODE_MASK) ==
169 PERF_RECORD_MISC_KERNEL;
Yabin Cuib64a8632016-05-24 18:23:33 -0700170 }
171
Yabin Cuib4212972016-05-25 14:08:05 -0700172 void SetTypeAndMisc(uint32_t type, uint16_t misc) {
173 header.type = type;
174 header.misc = misc;
175 }
176
177 void SetSize(uint32_t size) {
178 CHECK_LT(size, 1u << 16);
179 header.size = size;
180 }
181
Yabin Cui9759e1b2015-04-28 15:54:13 -0700182 void Dump(size_t indent = 0) const;
Yabin Cuicb84c982015-09-30 17:22:35 -0700183 virtual std::vector<char> BinaryFormat() const = 0;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700184 virtual uint64_t Timestamp() const;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700185
186 protected:
Yabin Cuicb84c982015-09-30 17:22:35 -0700187 virtual void DumpData(size_t) const = 0;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700188};
189
190struct MmapRecord : public Record {
191 struct MmapRecordDataType {
192 uint32_t pid, tid;
193 uint64_t addr;
194 uint64_t len;
195 uint64_t pgoff;
196 } data;
197 std::string filename;
198
Yabin Cuicb84c982015-09-30 17:22:35 -0700199 MmapRecord() { // For CreateMmapRecord.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700200 }
201
202 MmapRecord(const perf_event_attr& attr, const perf_event_header* pheader);
Yabin Cuicb84c982015-09-30 17:22:35 -0700203 std::vector<char> BinaryFormat() const override;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800204 void AdjustSizeBasedOnData();
Yabin Cui8f622512015-05-05 19:58:07 -0700205
Yabin Cui767dd172016-06-02 21:02:43 -0700206 static MmapRecord Create(const perf_event_attr& attr, bool in_kernel,
207 uint32_t pid, uint32_t tid, uint64_t addr,
208 uint64_t len, uint64_t pgoff,
209 const std::string& filename, uint64_t event_id);
210
Yabin Cui8f622512015-05-05 19:58:07 -0700211 protected:
212 void DumpData(size_t indent) const override;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700213};
214
Yabin Cui41d4ba92015-06-22 12:27:58 -0700215struct Mmap2Record : public Record {
216 struct Mmap2RecordDataType {
217 uint32_t pid, tid;
218 uint64_t addr;
219 uint64_t len;
220 uint64_t pgoff;
221 uint32_t maj;
222 uint32_t min;
223 uint64_t ino;
224 uint64_t ino_generation;
225 uint32_t prot, flags;
226 } data;
227 std::string filename;
228
Yabin Cui767dd172016-06-02 21:02:43 -0700229 Mmap2Record() {}
Yabin Cui41d4ba92015-06-22 12:27:58 -0700230
231 Mmap2Record(const perf_event_attr& attr, const perf_event_header* pheader);
Yabin Cuicb84c982015-09-30 17:22:35 -0700232 std::vector<char> BinaryFormat() const override;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800233 void AdjustSizeBasedOnData();
Yabin Cui41d4ba92015-06-22 12:27:58 -0700234
235 protected:
236 void DumpData(size_t indent) const override;
237};
238
Yabin Cui9759e1b2015-04-28 15:54:13 -0700239struct CommRecord : public Record {
240 struct CommRecordDataType {
241 uint32_t pid, tid;
242 } data;
243 std::string comm;
244
Yabin Cui767dd172016-06-02 21:02:43 -0700245 CommRecord() {}
Yabin Cui9759e1b2015-04-28 15:54:13 -0700246
247 CommRecord(const perf_event_attr& attr, const perf_event_header* pheader);
Yabin Cuicb84c982015-09-30 17:22:35 -0700248 std::vector<char> BinaryFormat() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700249
Yabin Cui767dd172016-06-02 21:02:43 -0700250 static CommRecord Create(const perf_event_attr& attr, uint32_t pid,
251 uint32_t tid, const std::string& comm,
252 uint64_t event_id);
253
Yabin Cui8f622512015-05-05 19:58:07 -0700254 protected:
255 void DumpData(size_t indent) const override;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700256};
257
Yabin Cui41d4ba92015-06-22 12:27:58 -0700258struct ExitOrForkRecord : public Record {
259 struct ExitOrForkRecordDataType {
Yabin Cui9759e1b2015-04-28 15:54:13 -0700260 uint32_t pid, ppid;
261 uint32_t tid, ptid;
262 uint64_t time;
263 } data;
264
Yabin Cui767dd172016-06-02 21:02:43 -0700265 ExitOrForkRecord() {}
266 ExitOrForkRecord(const perf_event_attr& attr,
267 const perf_event_header* pheader);
Yabin Cuicb84c982015-09-30 17:22:35 -0700268 std::vector<char> BinaryFormat() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700269
270 protected:
Yabin Cui9759e1b2015-04-28 15:54:13 -0700271 void DumpData(size_t indent) const override;
272};
273
Yabin Cui41d4ba92015-06-22 12:27:58 -0700274struct ExitRecord : public ExitOrForkRecord {
275 ExitRecord(const perf_event_attr& attr, const perf_event_header* pheader)
Yabin Cui767dd172016-06-02 21:02:43 -0700276 : ExitOrForkRecord(attr, pheader) {}
Yabin Cui41d4ba92015-06-22 12:27:58 -0700277};
278
279struct ForkRecord : public ExitOrForkRecord {
Yabin Cui767dd172016-06-02 21:02:43 -0700280 ForkRecord() {}
Yabin Cui41d4ba92015-06-22 12:27:58 -0700281 ForkRecord(const perf_event_attr& attr, const perf_event_header* pheader)
Yabin Cui767dd172016-06-02 21:02:43 -0700282 : ExitOrForkRecord(attr, pheader) {}
283
284 static ForkRecord Create(const perf_event_attr& attr, uint32_t pid,
285 uint32_t tid, uint32_t ppid, uint32_t ptid,
286 uint64_t event_id);
Yabin Cui41d4ba92015-06-22 12:27:58 -0700287};
288
Yabin Cui9759e1b2015-04-28 15:54:13 -0700289struct SampleRecord : public Record {
Yabin Cui767dd172016-06-02 21:02:43 -0700290 uint64_t sample_type; // sample_type is a bit mask determining which fields
291 // below are valid.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700292
293 PerfSampleIpType ip_data; // Valid if PERF_SAMPLE_IP.
294 PerfSampleTidType tid_data; // Valid if PERF_SAMPLE_TID.
295 PerfSampleTimeType time_data; // Valid if PERF_SAMPLE_TIME.
296 PerfSampleAddrType addr_data; // Valid if PERF_SAMPLE_ADDR.
297 PerfSampleIdType id_data; // Valid if PERF_SAMPLE_ID.
298 PerfSampleStreamIdType stream_id_data; // Valid if PERF_SAMPLE_STREAM_ID.
299 PerfSampleCpuType cpu_data; // Valid if PERF_SAMPLE_CPU.
300 PerfSamplePeriodType period_data; // Valid if PERF_SAMPLE_PERIOD.
301
Yabin Cui767dd172016-06-02 21:02:43 -0700302 PerfSampleCallChainType callchain_data; // Valid if PERF_SAMPLE_CALLCHAIN.
303 PerfSampleRawType raw_data; // Valid if PERF_SAMPLE_RAW.
304 PerfSampleBranchStackType
305 branch_stack_data; // Valid if PERF_SAMPLE_BRANCH_STACK.
306 PerfSampleRegsUserType regs_user_data; // Valid if PERF_SAMPLE_REGS_USER.
307 PerfSampleStackUserType stack_user_data; // Valid if PERF_SAMPLE_STACK_USER.
Yabin Cuiddddc062015-06-02 17:54:52 -0700308
Yabin Cui9759e1b2015-04-28 15:54:13 -0700309 SampleRecord(const perf_event_attr& attr, const perf_event_header* pheader);
Yabin Cuicb84c982015-09-30 17:22:35 -0700310 std::vector<char> BinaryFormat() const override;
311 void AdjustSizeBasedOnData();
Yabin Cuif469c3d2015-10-07 15:00:46 -0700312 uint64_t Timestamp() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700313
314 protected:
315 void DumpData(size_t indent) const override;
316};
317
Yabin Cui767dd172016-06-02 21:02:43 -0700318// BuildIdRecord is defined in user-space, stored in BuildId feature section in
319// record file.
Yabin Cui8f622512015-05-05 19:58:07 -0700320struct BuildIdRecord : public Record {
321 uint32_t pid;
322 BuildId build_id;
323 std::string filename;
324
Yabin Cui767dd172016-06-02 21:02:43 -0700325 BuildIdRecord() {}
Yabin Cui8f622512015-05-05 19:58:07 -0700326
327 BuildIdRecord(const perf_event_header* pheader);
Yabin Cuicb84c982015-09-30 17:22:35 -0700328 std::vector<char> BinaryFormat() const override;
329
Yabin Cui767dd172016-06-02 21:02:43 -0700330 static BuildIdRecord Create(bool in_kernel, pid_t pid,
331 const BuildId& build_id,
332 const std::string& filename);
333
Yabin Cuicb84c982015-09-30 17:22:35 -0700334 protected:
335 void DumpData(size_t indent) const override;
336};
337
Yabin Cuib4212972016-05-25 14:08:05 -0700338struct KernelSymbolRecord : public Record {
339 bool end_of_symbols;
340 std::string kallsyms;
341
Yabin Cui767dd172016-06-02 21:02:43 -0700342 KernelSymbolRecord() {}
Yabin Cuib4212972016-05-25 14:08:05 -0700343
344 KernelSymbolRecord(const perf_event_header* pheader);
345 std::vector<char> BinaryFormat() const override;
346
Yabin Cui767dd172016-06-02 21:02:43 -0700347 static std::vector<KernelSymbolRecord> Create(const std::string& kallsyms);
348
Yabin Cuib4212972016-05-25 14:08:05 -0700349 protected:
350 void DumpData(size_t indent) const override;
351};
352
Yabin Cui767dd172016-06-02 21:02:43 -0700353struct DsoRecord : public Record {
354 uint64_t dso_type;
355 uint64_t dso_id;
356 std::string dso_name;
357
358 DsoRecord() {}
359
360 DsoRecord(const perf_event_header* pheader);
361 std::vector<char> BinaryFormat() const override;
362
363 static DsoRecord Create(uint64_t dso_type, uint64_t dso_id,
364 const std::string& dso_name);
365
366 protected:
367 void DumpData(size_t indent) const override;
368};
369
370struct SymbolRecord : public Record {
371 uint64_t addr;
372 uint64_t len;
373 uint64_t dso_id;
374 std::string name;
375
376 SymbolRecord() {}
377
378 SymbolRecord(const perf_event_header* pheader);
379 std::vector<char> BinaryFormat() const override;
380
381 static SymbolRecord Create(uint64_t addr, uint64_t len,
382 const std::string& name, uint64_t dso_id);
Yabin Cui4f41df62016-06-01 17:29:06 -0700383 protected:
384 void DumpData(size_t indent) const override;
385};
Yabin Cui767dd172016-06-02 21:02:43 -0700386
Yabin Cui4f41df62016-06-01 17:29:06 -0700387struct TracingDataRecord : public Record {
388 std::vector<char> data;
389
390 TracingDataRecord() {
391 }
392
393 TracingDataRecord(const perf_event_header* pheader);
394 std::vector<char> BinaryFormat() const override;
395
396 static TracingDataRecord Create(std::vector<char> tracing_data);
Yabin Cui767dd172016-06-02 21:02:43 -0700397 protected:
398 void DumpData(size_t indent) const override;
399};
400
401// UnknownRecord is used for unknown record types, it makes sure all unknown
Yabin Cui4f41df62016-06-01 17:29:06 -0700402// records are not changed when modifying perf.data.
Yabin Cuicb84c982015-09-30 17:22:35 -0700403struct UnknownRecord : public Record {
404 std::vector<char> data;
405
406 UnknownRecord(const perf_event_header* pheader);
407 std::vector<char> BinaryFormat() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700408
409 protected:
Yabin Cui9759e1b2015-04-28 15:54:13 -0700410 void DumpData(size_t indent) const override;
411};
412
Yabin Cui767dd172016-06-02 21:02:43 -0700413std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr,
414 const perf_event_header* pheader);
415std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(
416 const perf_event_attr& attr, const char* buf, size_t buf_size);
417
Yabin Cuif469c3d2015-10-07 15:00:46 -0700418// RecordCache is a cache used when receiving records from the kernel.
419// It sorts received records based on type and timestamp, and pops records
420// in sorted order. Records from the kernel need to be sorted because
421// records may come from different cpus at the same time, and it is affected
422// by the order in which we collect records from different cpus.
Yabin Cui767dd172016-06-02 21:02:43 -0700423// RecordCache pushes records and pops sorted record online. It uses two checks
424// to help ensure that records are popped in order. Each time we pop a record A,
425// it is the earliest record among all records in the cache. In addition, we
426// have checks for min_cache_size and min_time_diff. For min_cache_size check,
427// we check if the cache size >= min_cache_size, which is based on the
428// assumption that if we have received (min_cache_size - 1) records after
429// record A, we are not likely to receive a record earlier than A. For
430// min_time_diff check, we check if record A is generated min_time_diff ns
431// earlier than the latest record, which is based on the assumption that if we
432// have received a record for time t, we are not likely to receive a record for
433// time (t - min_time_diff) or earlier.
Yabin Cuif469c3d2015-10-07 15:00:46 -0700434class RecordCache {
435 public:
Yabin Cui2d6efe42016-04-01 20:22:35 -0700436 RecordCache(bool has_timestamp, size_t min_cache_size = 1000u,
Yabin Cuib7f481f2015-10-23 19:48:42 -0700437 uint64_t min_time_diff_in_ns = 1000000u);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700438 ~RecordCache();
Yabin Cuib7f481f2015-10-23 19:48:42 -0700439 void Push(std::unique_ptr<Record> record);
Yabin Cui2d6efe42016-04-01 20:22:35 -0700440 void Push(std::vector<std::unique_ptr<Record>> records);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700441 std::unique_ptr<Record> Pop();
442 std::vector<std::unique_ptr<Record>> PopAll();
443
444 private:
Yabin Cui4913c122016-01-11 17:15:55 -0800445 struct RecordWithSeq {
446 uint32_t seq;
Yabin Cui767dd172016-06-02 21:02:43 -0700447 Record* record;
Yabin Cui4913c122016-01-11 17:15:55 -0800448
449 bool IsHappensBefore(const RecordWithSeq& other) const;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700450 };
451
Yabin Cui4913c122016-01-11 17:15:55 -0800452 struct RecordComparator {
453 bool operator()(const RecordWithSeq& r1, const RecordWithSeq& r2);
454 };
455
Yabin Cui767dd172016-06-02 21:02:43 -0700456 RecordWithSeq CreateRecordWithSeq(Record* r);
Yabin Cui4913c122016-01-11 17:15:55 -0800457
Yabin Cuif469c3d2015-10-07 15:00:46 -0700458 bool has_timestamp_;
459 size_t min_cache_size_;
460 uint64_t min_time_diff_in_ns_;
461 uint64_t last_time_;
Yabin Cui4913c122016-01-11 17:15:55 -0800462 uint32_t cur_seq_;
463 std::priority_queue<RecordWithSeq, std::vector<RecordWithSeq>,
Yabin Cui767dd172016-06-02 21:02:43 -0700464 RecordComparator> queue_;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700465};
466
Yabin Cui9759e1b2015-04-28 15:54:13 -0700467#endif // SIMPLE_PERF_RECORD_H_