const EventType* event_type = EventTypeFactory::FindEventTypeByName("cpu-cycles");
ASSERT_TRUE(event_type != nullptr);
event_attr = CreateDefaultPerfEventAttr(*event_type);
+ event_attr.sample_id_all = 1;
+ event_attr.sample_type |= PERF_SAMPLE_TIME;
std::unique_ptr<EventFd> event_fd = EventFd::OpenEventFileForProcess(event_attr, getpid());
ASSERT_TRUE(event_fd != nullptr);
event_fds.push_back(std::move(event_fd));
// Read and check data section.
std::vector<std::unique_ptr<const Record>> records = reader->DataSection();
ASSERT_EQ(1u, records.size());
- ASSERT_EQ(mmap_record.header.type, records[0]->header.type);
CheckRecordEqual(mmap_record, *records[0]);
// Read and check feature section.
ASSERT_TRUE(reader->Close());
}
+
+TEST_F(RecordFileTest, records_sorted_by_time) {
+ // Write to a record file;
+ std::unique_ptr<RecordFileWriter> writer =
+ RecordFileWriter::CreateInstance(filename, event_attr, event_fds);
+ ASSERT_TRUE(writer != nullptr);
+
+ // Write data section.
+ MmapRecord r1 = CreateMmapRecord(event_attr, true, 1, 1, 0x100, 0x2000, 0x3000, "mmap_record1");
+ MmapRecord r2 = r1;
+ MmapRecord r3 = r1;
+ r1.sample_id.time_data.time = 2;
+ r2.sample_id.time_data.time = 1;
+ r3.sample_id.time_data.time = 3;
+ ASSERT_TRUE(writer->WriteData(r1.BinaryFormat()));
+ ASSERT_TRUE(writer->WriteData(r2.BinaryFormat()));
+ ASSERT_TRUE(writer->WriteData(r3.BinaryFormat()));
+ ASSERT_TRUE(writer->Close());
+
+ // Read from a record file.
+ std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(filename);
+ ASSERT_TRUE(reader != nullptr);
+ std::vector<std::unique_ptr<const Record>> records = reader->DataSection();
+ ASSERT_EQ(3u, records.size());
+ CheckRecordEqual(r2, *records[0]);
+ CheckRecordEqual(r1, *records[1]);
+ CheckRecordEqual(r3, *records[2]);
+
+ ASSERT_TRUE(reader->Close());
+}
return (pid == map->pid && map->start_addr <= ip && map->start_addr + map->len > ip);
}
-const MapEntry* SampleTree::FindMapEntryOrNew(int pid, uint64_t ip) {
+const MapEntry* SampleTree::FindMapEntryOrNew(int pid, uint64_t ip, bool in_kernel) {
// Construct a map_entry which is strictly after the searched map_entry, based on MapComparator.
MapEntry find_map = {
- .pid = pid,
+ .pid = (in_kernel) ? -1 : pid,
.start_addr = ip,
.len = static_cast<uint64_t>(-1),
.time = static_cast<uint64_t>(-1),
};
- auto it = user_map_tree_.upper_bound(&find_map);
- if (it != user_map_tree_.begin() && IsIpInMap(pid, ip, *--it)) {
- return *it;
- }
- find_map.pid = -1;
- it = kernel_map_tree_.upper_bound(&find_map);
- if (it != kernel_map_tree_.begin() && IsIpInMap(-1, ip, *--it)) {
- return *it;
+ if (!in_kernel) {
+ auto it = user_map_tree_.upper_bound(&find_map);
+ if (it != user_map_tree_.begin() && IsIpInMap(pid, ip, *--it)) {
+ return *it;
+ }
+ } else {
+ auto it = kernel_map_tree_.upper_bound(&find_map);
+ if (it != kernel_map_tree_.begin() && IsIpInMap(-1, ip, *--it)) {
+ return *it;
+ }
}
return FindUnknownMapEntryOrNew(pid);
}
return it->second;
}
-void SampleTree::AddSample(int pid, int tid, uint64_t ip, uint64_t time, uint64_t period) {
+void SampleTree::AddSample(int pid, int tid, uint64_t ip, uint64_t time, uint64_t period,
+ bool in_kernel) {
const ProcessEntry* process_entry = FindProcessEntryOrNew(pid);
- const MapEntry* map_entry = FindMapEntryOrNew(pid, ip);
+ const MapEntry* map_entry = FindMapEntryOrNew(pid, ip, in_kernel);
const SymbolEntry* symbol_entry = FindSymbolEntry(ip, map_entry);
SampleEntry find_sample = {
};
TEST_F(SampleTreeTest, ip_in_map) {
- sample_tree->AddSample(1, 1, 1, 0, 0);
- sample_tree->AddSample(1, 1, 5, 0, 0);
- sample_tree->AddSample(1, 1, 10, 0, 0);
+ sample_tree->AddSample(1, 1, 1, 0, 0, false);
+ sample_tree->AddSample(1, 1, 5, 0, 0, false);
+ sample_tree->AddSample(1, 1, 10, 0, 0, false);
std::vector<ExpectedSampleInMap> expected_samples = {
{1, 1, 1, 1, 3},
};
}
TEST_F(SampleTreeTest, different_pid) {
- sample_tree->AddSample(1, 1, 1, 0, 0);
- sample_tree->AddSample(2, 2, 1, 0, 0);
+ sample_tree->AddSample(1, 1, 1, 0, 0, false);
+ sample_tree->AddSample(2, 2, 1, 0, 0, false);
std::vector<ExpectedSampleInMap> expected_samples = {
{1, 1, 1, 1, 1}, {2, 2, 2, 1, 1},
};
}
TEST_F(SampleTreeTest, different_tid) {
- sample_tree->AddSample(1, 1, 1, 0, 0);
- sample_tree->AddSample(1, 11, 1, 0, 0);
+ sample_tree->AddSample(1, 1, 1, 0, 0, false);
+ sample_tree->AddSample(1, 11, 1, 0, 0, false);
std::vector<ExpectedSampleInMap> expected_samples = {
{1, 1, 1, 1, 1}, {1, 11, 1, 1, 1},
};
}
TEST_F(SampleTreeTest, different_map) {
- sample_tree->AddSample(1, 1, 1, 0, 0);
- sample_tree->AddSample(1, 1, 11, 0, 0);
+ sample_tree->AddSample(1, 1, 1, 0, 0, false);
+ sample_tree->AddSample(1, 1, 11, 0, 0, false);
std::vector<ExpectedSampleInMap> expected_samples = {
{1, 1, 1, 1, 1}, {1, 1, 1, 11, 1},
};
}
TEST_F(SampleTreeTest, unmapped_sample) {
- sample_tree->AddSample(1, 1, 0, 0, 0);
- sample_tree->AddSample(1, 1, 31, 0, 0);
- sample_tree->AddSample(1, 1, 70, 0, 0);
+ sample_tree->AddSample(1, 1, 0, 0, 0, false);
+ sample_tree->AddSample(1, 1, 31, 0, 0, false);
+ sample_tree->AddSample(1, 1, 70, 0, 0, false);
// Match the unknown map.
std::vector<ExpectedSampleInMap> expected_samples = {
{1, 1, 1, 0, 3},
}
TEST_F(SampleTreeTest, map_kernel) {
- sample_tree->AddSample(1, 1, 11, 0, 0);
- sample_tree->AddSample(1, 1, 21, 0, 0);
+ sample_tree->AddSample(1, 1, 11, 0, 0, true);
+ sample_tree->AddSample(1, 1, 11, 0, 0, false);
std::vector<ExpectedSampleInMap> expected_samples = {
{1, 1, -1, 11, 1}, {1, 1, 1, 11, 1},
};
TEST(sample_tree, overlapped_map) {
auto sample_tree = std::unique_ptr<SampleTree>(new SampleTree(CompareSampleFunction));
- sample_tree->AddUserMap(1, 1, 10, 0, 0, ""); // Add map 1.
- sample_tree->AddSample(1, 1, 5, 0, 0); // Hit map 1.
- sample_tree->AddUserMap(1, 5, 20, 0, 0, ""); // Add map 2.
- sample_tree->AddSample(1, 1, 6, 0, 0); // Hit map 2.
- sample_tree->AddSample(1, 1, 4, 0, 0); // Hit unknown map.
- sample_tree->AddUserMap(1, 2, 7, 0, 0, ""); // Add map 3.
- sample_tree->AddSample(1, 1, 7, 0, 0); // Hit map 3.
- sample_tree->AddSample(1, 1, 10, 0, 0); // Hit unknown map.
+ sample_tree->AddUserMap(1, 1, 10, 0, 0, ""); // Add map 1.
+ sample_tree->AddSample(1, 1, 5, 0, 0, false); // Hit map 1.
+ sample_tree->AddUserMap(1, 5, 20, 0, 0, ""); // Add map 2.
+ sample_tree->AddSample(1, 1, 6, 0, 0, false); // Hit map 2.
+ sample_tree->AddSample(1, 1, 4, 0, 0, false); // Hit unknown map.
+ sample_tree->AddUserMap(1, 2, 7, 0, 0, ""); // Add map 3.
+ sample_tree->AddSample(1, 1, 7, 0, 0, false); // Hit map 3.
+ sample_tree->AddSample(1, 1, 10, 0, 0, false); // Hit unknown map.
std::vector<ExpectedSampleInMap> expected_samples = {
{1, 1, 1, 0, 2}, {1, 1, 1, 1, 1}, {1, 1, 1, 2, 1}, {1, 1, 1, 5, 1},