Skip to content

Commit e4ede11

Browse files
author
Pavel Kosov
committed
[LNT] Fixed the time extraction from MMAP and MMAP2 events using the Layout
We used a lot of perf_data files from different systems to analyze, summarize and debug the time extraction from MMAP and MMAP2 events. OS Laboratory. Huawei Russian Research Institute. Saint-Petersburg Reviewed By: thopre Differential Revision: https://reviews.llvm.org/D117008
1 parent d08e890 commit e4ede11

File tree

1 file changed

+47
-39
lines changed

1 file changed

+47
-39
lines changed

lnt/testing/profile/cPerf.cpp

Lines changed: 47 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -268,19 +268,20 @@ struct perf_event_sample {
268268
uint64_t period;
269269
};
270270

271-
struct perf_event_mmap {
271+
struct perf_event_mmap_common {
272272
struct perf_event_header header;
273273

274274
uint32_t pid, tid;
275275
uint64_t start, extent, pgoff;
276+
};
277+
278+
struct perf_event_mmap {
279+
struct perf_event_mmap_common mmap_common;
276280
char filename[1];
277281
};
278282

279283
struct perf_event_mmap2 {
280-
struct perf_event_header header;
281-
282-
uint32_t pid, tid;
283-
uint64_t start, extent, pgoff;
284+
struct perf_event_mmap_common mmap_common;
284285
uint32_t maj, min;
285286
uint64_t ino, ino_generation;
286287
uint32_t prot, flags;
@@ -292,12 +293,6 @@ struct perf_trace_event_type {
292293
char str[64];
293294
};
294295

295-
struct perf_sample_id {
296-
uint32_t pid, tid;
297-
uint64_t time;
298-
uint64_t id;
299-
};
300-
301296
enum perf_type_id {
302297
PERF_TYPE_HARDWARE = 0,
303298
PERF_TYPE_SOFTWARE = 1,
@@ -598,6 +593,7 @@ class PerfReader {
598593
void readAttrs();
599594
void readEventDesc();
600595
void readDataStream();
596+
void registerNewMapping(unsigned char *Buf, const char *FileName);
601597
unsigned char *readEvent(unsigned char *);
602598
perf_event_sample parseEvent(unsigned char *Buf, uint64_t Layout);
603599
void emitLine(uint64_t PC, std::map<const char *, uint64_t> *Counters,
@@ -719,7 +715,7 @@ void PerfReader::readAttrs() {
719715

720716
// Weirdness of perf: if there is only one event descriptor, that
721717
// event descriptor can be referred to by ANY id!
722-
if (NumEvents == 1 && NumIDs == 0) {
718+
if (NumEvents == 1) {
723719
EventIDs[0] = Str;
724720
EventLayouts[0] = attr->sample_type;
725721
}
@@ -758,7 +754,7 @@ void PerfReader::readEventDesc() {
758754

759755
// Weirdness of perf: if there is only one event descriptor, that
760756
// event descriptor can be referred to by ANY id!
761-
if (NumEvents == 1 && NumIDs == 0) {
757+
if (NumEvents == 1) {
762758
EventIDs[0] = Str;
763759
EventLayouts[0] = Layout;
764760
}
@@ -771,45 +767,57 @@ void PerfReader::readEventDesc() {
771767
}
772768
}
773769

770+
static uint64_t getTimeFromSampleId(unsigned char *EndOfStruct,
771+
uint64_t Layout) {
772+
uint64_t *Ptr = (uint64_t *)EndOfStruct;
773+
// Each of the PERF_SAMPLE_* bits tested below adds an 8-byte field.
774+
if (Layout & PERF_SAMPLE_IDENTIFIER)
775+
--Ptr;
776+
if (Layout & PERF_SAMPLE_CPU)
777+
--Ptr;
778+
if (Layout & PERF_SAMPLE_STREAM_ID)
779+
--Ptr;
780+
if (Layout & PERF_SAMPLE_ID)
781+
--Ptr;
782+
assert(Layout & PERF_SAMPLE_TIME);
783+
--Ptr;
784+
return *Ptr;
785+
}
786+
787+
void PerfReader::registerNewMapping(unsigned char *Buf, const char *Filename) {
788+
perf_event_mmap_common *E = (perf_event_mmap_common *)Buf;
789+
auto MapID = Maps.size();
790+
// EXEC ELF objects aren't relocated. DYN ones are,
791+
// so if it's a DYN object adjust by subtracting the
792+
// map base.
793+
bool IsSO = IsSharedObject(BinaryCacheRoot + std::string(Filename));
794+
uint64_t End = E->start + E->extent;
795+
uint64_t Adjust = IsSO ? E->start - E->pgoff : 0;
796+
Maps.push_back({E->start, End, Adjust, Filename});
797+
798+
unsigned char *EndOfEvent = Buf + E->header.size;
799+
// FIXME: The first EventID is used for every event.
800+
// FIXME: The code assumes perf_event_attr.sample_id_all is set.
801+
uint64_t Time = getTimeFromSampleId(EndOfEvent, EventLayouts.begin()->second);
802+
auto &CurrentMap = CurrentMaps[Time];
803+
CurrentMap.insert({E->start, MapID});
804+
}
805+
774806
unsigned char *PerfReader::readEvent(unsigned char *Buf) {
775807
perf_event_header *E = (perf_event_header *)Buf;
776808
switch (E->type) {
777809
case PERF_RECORD_MMAP:
778810
{
779811
perf_event_mmap *E = (perf_event_mmap *)Buf;
780-
auto MapID = Maps.size();
781-
// EXEC ELF objects aren't relocated. DYN ones are,
782-
// so if it's a DYN object adjust by subtracting the
783-
// map base.
784-
bool IsSO = IsSharedObject(BinaryCacheRoot + std::string(E->filename));
785-
Maps.push_back({E->start, E->start + E->extent,
786-
IsSO ? E->start - E->pgoff : 0, E->filename});
787-
788-
// FIXME: use EventLayouts.begin()->second!
789-
perf_sample_id *ID =
790-
(perf_sample_id *)(Buf + E->header.size - sizeof(perf_sample_id));
791-
auto &CurrentMap = CurrentMaps[ID->time];
792-
CurrentMap.insert({E->start, MapID});
812+
registerNewMapping(Buf, E->filename);
793813
}
794814
break;
795815
case PERF_RECORD_MMAP2:
796816
{
797817
perf_event_mmap2 *E = (perf_event_mmap2 *)Buf;
798818
if (!(E->prot & PROT_EXEC))
799819
break;
800-
auto MapID = Maps.size();
801-
// EXEC ELF objects aren't relocated. DYN ones are,
802-
// so if it's a DYN object adjust by subtracting the
803-
// map base.
804-
bool IsSO = IsSharedObject(BinaryCacheRoot + std::string(E->filename));
805-
Maps.push_back({E->start, E->start + E->extent,
806-
IsSO ? E->start - E->pgoff : 0, E->filename});
807-
808-
// FIXME: use EventLayouts.begin()->second!
809-
perf_sample_id *ID =
810-
(perf_sample_id *)(Buf + E->header.size - sizeof(perf_sample_id));
811-
auto &CurrentMap = CurrentMaps[ID->time];
812-
CurrentMap.insert({E->start, MapID});
820+
registerNewMapping(Buf, E->filename);
813821
}
814822
break;
815823
case PERF_RECORD_SAMPLE:

0 commit comments

Comments
 (0)