2 * Copyright (C) 2015 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #ifndef SIMPLE_PERF_RECORD_H_
18 #define SIMPLE_PERF_RECORD_H_
21 #include <sys/types.h>
28 #include <android-base/logging.h>
31 #include "perf_event.h"
33 enum user_record_type {
34 PERF_RECORD_USER_DEFINED_TYPE_START = 64,
35 PERF_RECORD_ATTR = 64,
36 PERF_RECORD_EVENT_TYPE,
37 PERF_RECORD_TRACING_DATA,
39 PERF_RECORD_FINISHED_ROUND,
41 SIMPLE_PERF_RECORD_TYPE_START = 32768,
42 SIMPLE_PERF_RECORD_KERNEL_SYMBOL,
43 // TODO: remove DsoRecord and SymbolRecord.
44 SIMPLE_PERF_RECORD_DSO,
45 SIMPLE_PERF_RECORD_SYMBOL,
46 SIMPLE_PERF_RECORD_SPLIT,
47 SIMPLE_PERF_RECORD_SPLIT_END,
48 SIMPLE_PERF_RECORD_EVENT_ID,
51 // perf_event_header uses u16 to store record size. However, that is not
52 // enough for storing records like KERNEL_SYMBOL or TRACING_DATA. So define
53 // a simpleperf_record_header struct to store record header for simpleperf
54 // defined records (type > SIMPLE_PERF_RECORD_TYPE_START).
55 struct simpleperf_record_header {
62 sizeof(simpleperf_record_header) == sizeof(perf_event_header),
63 "simpleperf_record_header should have the same size as perf_event_header");
65 struct PerfSampleIpType {
69 struct PerfSampleTidType {
73 struct PerfSampleTimeType {
77 struct PerfSampleAddrType {
81 struct PerfSampleIdType {
85 struct PerfSampleStreamIdType {
89 struct PerfSampleCpuType {
93 struct PerfSamplePeriodType {
97 struct PerfSampleCallChainType {
102 struct PerfSampleRawType {
107 struct BranchStackItemType {
113 struct PerfSampleBranchStackType {
115 const BranchStackItemType* stack;
118 struct PerfSampleRegsUserType {
122 const uint64_t* regs;
125 struct PerfSampleStackUserType {
131 struct RecordHeader {
137 RecordHeader() : type(0), misc(0), size(0) {}
139 explicit RecordHeader(const char* p) {
140 auto pheader = reinterpret_cast<const perf_event_header*>(p);
141 if (pheader->type < SIMPLE_PERF_RECORD_TYPE_START) {
142 type = pheader->type;
143 misc = pheader->misc;
144 size = pheader->size;
146 auto sheader = reinterpret_cast<const simpleperf_record_header*>(p);
147 type = sheader->type;
149 size = (sheader->size1 << 16) | sheader->size0;
153 void MoveToBinaryFormat(char*& p) const {
154 if (type < SIMPLE_PERF_RECORD_TYPE_START) {
155 auto pheader = reinterpret_cast<perf_event_header*>(p);
156 pheader->type = type;
157 pheader->misc = misc;
158 CHECK_LT(size, 1u << 16);
159 pheader->size = static_cast<uint16_t>(size);
161 auto sheader = reinterpret_cast<simpleperf_record_header*>(p);
162 sheader->type = type;
164 sheader->size1 = size >> 16;
165 sheader->size0 = size & 0xffff;
167 p += sizeof(perf_event_header);
171 // SampleId is optional at the end of a record in binary format. Its content is
172 // determined by sample_id_all and sample_type in perf_event_attr. To avoid the
173 // complexity of referring to perf_event_attr each time, we copy sample_id_all
174 // and sample_type inside the SampleId structure.
177 uint64_t sample_type;
179 PerfSampleTidType tid_data; // Valid if sample_id_all && PERF_SAMPLE_TID.
180 PerfSampleTimeType time_data; // Valid if sample_id_all && PERF_SAMPLE_TIME.
181 PerfSampleIdType id_data; // Valid if sample_id_all && PERF_SAMPLE_ID.
182 PerfSampleStreamIdType
183 stream_id_data; // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
184 PerfSampleCpuType cpu_data; // Valid if sample_id_all && PERF_SAMPLE_CPU.
188 // Create the content of sample_id. It depends on the attr we use.
189 size_t CreateContent(const perf_event_attr& attr, uint64_t event_id);
191 // Parse sample_id from binary format in the buffer pointed by p.
192 void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p,
195 // Write the binary format of sample_id to the buffer pointed by p.
196 void WriteToBinaryFormat(char*& p) const;
197 void Dump(size_t indent) const;
201 // Usually one record contains the following three parts in order in binary
203 // RecordHeader (at the head of a record, containing type and size info)
204 // data depends on the record type
205 // SampleId (optional part at the end of a record)
206 // We hold the common parts (RecordHeader and SampleId) in the base class
207 // Record, and hold the type specific data part in classes derived from Record.
212 Record() : binary_(nullptr), own_binary_(false) {}
213 explicit Record(const char* p) : header(p), binary_(p), own_binary_(false) {}
214 Record(Record&& other);
222 void OwnBinary() { own_binary_ = true; }
224 uint32_t type() const { return header.type; }
226 uint16_t misc() const { return header.misc; }
228 uint32_t size() const { return header.size; }
230 static uint32_t header_size() { return sizeof(perf_event_header); }
232 bool InKernel() const {
233 return (header.misc & PERF_RECORD_MISC_CPUMODE_MASK) ==
234 PERF_RECORD_MISC_KERNEL;
237 void SetTypeAndMisc(uint32_t type, uint16_t misc) {
242 void SetSize(uint32_t size) { header.size = size; }
244 void Dump(size_t indent = 0) const;
246 const char* Binary() const { return binary_; }
248 virtual uint64_t Timestamp() const;
249 virtual uint32_t Cpu() const;
250 virtual uint64_t Id() const;
253 void UpdateBinary(const char* new_binary);
254 virtual void DumpData(size_t) const = 0;
259 DISALLOW_COPY_AND_ASSIGN(Record);
262 struct MmapRecord : public Record {
263 struct MmapRecordDataType {
269 const MmapRecordDataType* data;
270 const char* filename;
272 MmapRecord(const perf_event_attr& attr, const char* p);
274 MmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid,
275 uint32_t tid, uint64_t addr, uint64_t len, uint64_t pgoff,
276 const std::string& filename, uint64_t event_id, uint64_t time = 0);
278 void SetDataAndFilename(const MmapRecordDataType& data,
279 const std::string& filename);
282 void DumpData(size_t indent) const override;
285 struct Mmap2Record : public Record {
286 struct Mmap2RecordDataType {
294 uint64_t ino_generation;
295 uint32_t prot, flags;
297 const Mmap2RecordDataType* data;
298 const char* filename;
300 Mmap2Record(const perf_event_attr& attr, const char* p);
302 void SetDataAndFilename(const Mmap2RecordDataType& data,
303 const std::string& filename);
306 void DumpData(size_t indent) const override;
309 struct CommRecord : public Record {
310 struct CommRecordDataType {
313 const CommRecordDataType* data;
316 CommRecord(const perf_event_attr& attr, const char* p);
318 CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
319 const std::string& comm, uint64_t event_id, uint64_t time);
322 void DumpData(size_t indent) const override;
325 struct ExitOrForkRecord : public Record {
326 struct ExitOrForkRecordDataType {
331 const ExitOrForkRecordDataType* data;
333 ExitOrForkRecord(const perf_event_attr& attr, const char* p);
335 ExitOrForkRecord() : data(nullptr) {}
338 void DumpData(size_t indent) const override;
341 struct ExitRecord : public ExitOrForkRecord {
342 ExitRecord(const perf_event_attr& attr, const char* p)
343 : ExitOrForkRecord(attr, p) {}
346 struct ForkRecord : public ExitOrForkRecord {
347 ForkRecord(const perf_event_attr& attr, const char* p)
348 : ExitOrForkRecord(attr, p) {}
350 ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
351 uint32_t ppid, uint32_t ptid, uint64_t event_id);
354 struct LostRecord : public Record {
358 LostRecord(const perf_event_attr& attr, const char* p);
361 void DumpData(size_t indent) const override;
364 struct SampleRecord : public Record {
365 uint64_t sample_type; // sample_type is a bit mask determining which fields
368 PerfSampleIpType ip_data; // Valid if PERF_SAMPLE_IP.
369 PerfSampleTidType tid_data; // Valid if PERF_SAMPLE_TID.
370 PerfSampleTimeType time_data; // Valid if PERF_SAMPLE_TIME.
371 PerfSampleAddrType addr_data; // Valid if PERF_SAMPLE_ADDR.
372 PerfSampleIdType id_data; // Valid if PERF_SAMPLE_ID.
373 PerfSampleStreamIdType stream_id_data; // Valid if PERF_SAMPLE_STREAM_ID.
374 PerfSampleCpuType cpu_data; // Valid if PERF_SAMPLE_CPU.
375 PerfSamplePeriodType period_data; // Valid if PERF_SAMPLE_PERIOD.
377 PerfSampleCallChainType callchain_data; // Valid if PERF_SAMPLE_CALLCHAIN.
378 PerfSampleRawType raw_data; // Valid if PERF_SAMPLE_RAW.
379 PerfSampleBranchStackType
380 branch_stack_data; // Valid if PERF_SAMPLE_BRANCH_STACK.
381 PerfSampleRegsUserType regs_user_data; // Valid if PERF_SAMPLE_REGS_USER.
382 PerfSampleStackUserType stack_user_data; // Valid if PERF_SAMPLE_STACK_USER.
384 SampleRecord(const perf_event_attr& attr, const char* p);
385 SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip,
386 uint32_t pid, uint32_t tid, uint64_t time, uint32_t cpu,
387 uint64_t period, const std::vector<uint64_t>& ips);
389 void ReplaceRegAndStackWithCallChain(const std::vector<uint64_t>& ips);
390 uint64_t Timestamp() const override;
391 uint32_t Cpu() const override;
392 uint64_t Id() const override;
394 uint64_t GetValidStackSize() const {
395 // If stack_user_data.dyn_size == 0, it may be because the kernel misses
396 // the patch to update dyn_size, like in N9 (See b/22612370). So assume
397 // all stack data is valid if dyn_size == 0.
398 if (stack_user_data.dyn_size == 0) {
399 return stack_user_data.size;
401 return stack_user_data.dyn_size;
405 void DumpData(size_t indent) const override;
408 // BuildIdRecord is defined in user-space, stored in BuildId feature section in
410 struct BuildIdRecord : public Record {
413 const char* filename;
415 explicit BuildIdRecord(const char* p);
417 BuildIdRecord(bool in_kernel, pid_t pid, const BuildId& build_id,
418 const std::string& filename);
421 void DumpData(size_t indent) const override;
424 struct KernelSymbolRecord : public Record {
425 uint32_t kallsyms_size;
426 const char* kallsyms;
428 explicit KernelSymbolRecord(const char* p);
430 explicit KernelSymbolRecord(const std::string& kallsyms);
433 void DumpData(size_t indent) const override;
436 struct DsoRecord : public Record {
440 const char* dso_name;
442 explicit DsoRecord(const char* p);
444 DsoRecord(uint64_t dso_type, uint64_t dso_id, const std::string& dso_name,
448 void DumpData(size_t indent) const override;
451 struct SymbolRecord : public Record {
457 explicit SymbolRecord(const char* p);
459 SymbolRecord(uint64_t addr, uint64_t len, const std::string& name,
463 void DumpData(size_t indent) const override;
466 struct TracingDataRecord : public Record {
470 explicit TracingDataRecord(const char* p);
472 explicit TracingDataRecord(const std::vector<char>& tracing_data);
475 void DumpData(size_t indent) const override;
478 struct EventIdRecord : public Record {
485 explicit EventIdRecord(const char* p);
487 explicit EventIdRecord(const std::vector<uint64_t>& data);
490 void DumpData(size_t indent) const override;
493 // UnknownRecord is used for unknown record types, it makes sure all unknown
494 // records are not changed when modifying perf.data.
495 struct UnknownRecord : public Record {
498 explicit UnknownRecord(const char* p);
501 void DumpData(size_t indent) const override;
504 // Read record from the buffer pointed by [p]. But the record doesn't own
506 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr,
507 uint32_t type, const char* p);
509 // Read record from the buffer pointed by [p]. And the record owns the buffer.
510 std::unique_ptr<Record> ReadRecordFromOwnedBuffer(const perf_event_attr& attr,
511 uint32_t type, const char* p);
513 // Read records from the buffer pointed by [buf]. None of the records own
515 std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(
516 const perf_event_attr& attr, const char* buf, size_t buf_size);
518 // Read one record from the buffer pointed by [p]. But the record doesn't
520 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr,
523 // RecordCache is a cache used when receiving records from the kernel.
524 // It sorts received records based on type and timestamp, and pops records
525 // in sorted order. Records from the kernel need to be sorted because
526 // records may come from different cpus at the same time, and it is affected
527 // by the order in which we collect records from different cpus.
528 // RecordCache pushes records and pops sorted record online. It uses two checks
529 // to help ensure that records are popped in order. Each time we pop a record A,
530 // it is the earliest record among all records in the cache. In addition, we
531 // have checks for min_cache_size and min_time_diff. For min_cache_size check,
532 // we check if the cache size >= min_cache_size, which is based on the
533 // assumption that if we have received (min_cache_size - 1) records after
534 // record A, we are not likely to receive a record earlier than A. For
535 // min_time_diff check, we check if record A is generated min_time_diff ns
536 // earlier than the latest record, which is based on the assumption that if we
537 // have received a record for time t, we are not likely to receive a record for
538 // time (t - min_time_diff) or earlier.
541 explicit RecordCache(bool has_timestamp, size_t min_cache_size = 1000u,
542 uint64_t min_time_diff_in_ns = 1000000u);
544 void Push(std::unique_ptr<Record> record);
545 void Push(std::vector<std::unique_ptr<Record>> records);
546 std::unique_ptr<Record> Pop();
547 std::vector<std::unique_ptr<Record>> PopAll();
548 std::unique_ptr<Record> ForcedPop();
551 struct RecordWithSeq {
555 RecordWithSeq(uint32_t seq, Record* record) : seq(seq), record(record) {}
556 bool IsHappensBefore(const RecordWithSeq& other) const;
559 struct RecordComparator {
560 bool operator()(const RecordWithSeq& r1, const RecordWithSeq& r2);
564 size_t min_cache_size_;
565 uint64_t min_time_diff_in_ns_;
568 std::priority_queue<RecordWithSeq, std::vector<RecordWithSeq>,
569 RecordComparator> queue_;
572 #endif // SIMPLE_PERF_RECORD_H_