如何从 perf_event_open 中的环形缓冲区中检索调用链以获取 PERF_RECORD_SWITCH?
Posted
技术标签:
【中文标题】如何从 perf_event_open 中的环形缓冲区中检索调用链以获取 PERF_RECORD_SWITCH?【英文标题】:How to retrieve callchain from ring buffer in perf_event_open for PERF_RECORD_SWITCH? 【发布时间】:2019-09-05 06:33:36 【问题描述】:在环形缓冲区中,我们可以只检索PERF_RECORD_SAMPLE
的调用链,还是也可以检索其他记录类型?
perf_event_open
的手册页仅明确说明调用链可用于PERF_RECORD_SAMPLE
。我对获取PERF_RECORD_SWITCH
的调用链特别感兴趣,以获取我的程序在上下文切换进出时的堆栈跟踪。我尝试了一种从缓冲区读取调用链的方法,但是看到返回的地址,它看起来不正确。
size_t index = mapping->data_tail; //mapping is the pointer to the ring buffer
uintptr_t base = reinterpret_cast<uintptr_t>(mapping) + PageSize;
size_t start_index = index % DataSize;
size_t end_index = start_index + sizeof(struct perf_event_header);
memcpy(buf, reinterpret_cast<void*>(base + start_index), sizeof(struct perf_event_header));
struct perf_event_header* header = reinterpret_cast<struct perf_event_header*>(buf);
uintptr_t p = reinterpret_cast<uintptr_t>(header) + sizeof(struct perf_event_header)
// Only sampling PERF_SAMPLE_CALLCHAIN
uint64_t* base = reinterpret_cast<uint64_t*>(p);
uint64_t size = *base; // Should be callchain size
base++;
for (int i = 0; i < size; i++)
cout << *base << endl; // prints the addresses in the callchain stack
我使用这个 sn-p 得到的输出的两个主要问题是:
1.所有PERF_RECORD_SWITCH
都有相同的调用链。这应该是极不可能的。
2. 多次运行的输出不一致。调用链大小从 0(大部分)到 4,6、16 不等,有时甚至是一个非常大(未定义)的数字。
【问题讨论】:
【参考方案1】:调用链仅适用于PERF_RECORD_SAMPLE
事件。
在读取不同的记录类型时,您应该遵循 perf_event_open
中的 struct
定义,而不是仅仅尝试通过指针访问单个字段,即,
struct perf_record_switch
struct perf_event_header header;
struct sample_id sample_id;
;
然后投射整个事件reinterpret_cast<struct perf_record_switch*>(header)
具体来说,样本类型的布局高度依赖于配置,可能包含多个动态大小的数组,这会阻止使用静态结构。
从技术上讲,您可以使用sched:sched_switch
跟踪点采样事件从切换事件中收集调用链。这会导致PERF_RECORD_SAMPLE
事件。但是,您可能并不总是看到有用的信息,而主要是内核中的调度详细信息。
【讨论】:
性能记录如何为上下文切换创建调用图? perf record -g -e cs ./a.out 然后 perf report 给出一个调用图百分比明智。或者是别的什么?cs
事件使用type=PERF_TYPE_SOFTWARE, config=PERF_COUNT_SW_CONTEXT_SWITCHES
。这也适用于PERF_RECORD_SAMPLE
事件。 sched:sched_switch
跟踪点的优势在于包括切换到和切换到的 pid,PERF_RECORD_SWITCH_CPU_WIDE
事件也是如此。
好的。但是我如何模拟使用perf_event_open
获取调用图以获取sched:sched_switch
或cs
,如perf record -g
?因为PERF_RECORD_SWITCH
样本是在切换事件期间创建的。 PERF_RECORD_SAMPLE
和上下文切换有关系吗?
调用perf_event_open
时,您使用struct perf_event_attr
,其中包括type=PERF_TYPE_SOFTWARE, config=PERF_COUNT_SW_CONTEXT_SWITCHES
或type=PERF_TYPE_TRACEPOINT, config=(/sys/kernel/debug/tracing/events/sched/sched_switch/id)
。以上是关于如何从 perf_event_open 中的环形缓冲区中检索调用链以获取 PERF_RECORD_SWITCH?的主要内容,如果未能解决你的问题,请参考以下文章