Frank Tetzel via llvm-dev
2019-Jan-15 13:09 UTC
[llvm-dev] How to correctly use PerfJITEventListener?
Hello, I'm struggling to get PerfJITEventListener to work. It was already fun to find out that I need to enable LLVM_USE_PERF in cmake during compilation, and that the jitdump files are stored in ~/.debug/jit/ by default. But it's still not working. The steps I do: 1. Get event listener with JITEventListener::createPerfJITEventListener 2. In NotifyLoadedFunction passed to orc::RTDyldObjectLinkingLayer ctor pass object and info to event listener's NotifyObjectEmitted Then, I profile the application with: perf record -k 1 ./app This generates a jit-*.dump file in ~/.debug/jit/llvm-IR-jit-*/. Inject the events into the perf data perf inject -j -i perf.data -o perf.data.jitted This creates jitted-*.so files in ~/.debug/jit/llvm-IR-jit-*/ for each JIT compiled function. Finally, I open the profile report: perf report -i perf.data.jitted But here is the problem. The JIT compiled functions are not "resolved". I cannot "zoom in" to the code and annotate the instructions with profile information. Am I missing something here? Is there a small example somewhere which uses PerfJITEventListener with ORC? Best regards, Frank
Zhang Boyang via llvm-dev
2021-Jan-09 11:45 UTC
[llvm-dev] How to correctly use PerfJITEventListener?
Hello,
I encountered the same problem recently. Finally I found it's a bug
of linux kernel or linux-perf. LLVM uses mmap() and mprotect() to
generate code. However, mprotect() will merge adjacent VMAs (virtual
memory area) and report a event of merged VMA, causing pref think prior
allocated memory has gone. I have reported the bug to Linux Perf Users
mailing list.
As a quick & super dirty workaround, I modified
SectionMemoryManager::allocateSection (in
llvm/lib/ExecutionEngine/SectionMemoryManager.cpp), let it alloc two
pieces of memory for each memory request, and use only one of them:
--- a/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp
+++ b/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp
@@ -101,6 +101,9 @@ uint8_t *SectionMemoryManager::allocateSection(
// FIXME: Initialize the Near member for each memory group to avoid
// interleaving.
std::error_code ec;
+ if (1) MMapper.allocateMappedMemory(
+ Purpose, RequiredSize, &MemGroup.Near,
+ sys::Memory::MF_READ | sys::Memory::MF_WRITE, ec); // XXX: SUPER
DIRTY
sys::MemoryBlock MB = MMapper.allocateMappedMemory(
Purpose, RequiredSize, &MemGroup.Near,
sys::Memory::MF_READ | sys::Memory::MF_WRITE, ec);
Of course this can't be merged into LLVM, but I think this code may
help some people who encountered the same problem.
Zhang Boyang
On 2019/1/15 21:09, llvm-dev at lists.llvm.org (Frank Tetzel via
llvm-dev) wrote:> Hello,
>
> I'm struggling to get PerfJITEventListener to work. It was already fun
> to find out that I need to enable LLVM_USE_PERF in cmake during
> compilation, and that the jitdump files are stored in ~/.debug/jit/ by
> default. But it's still not working.
>
> The steps I do:
>
> 1. Get event listener with JITEventListener::createPerfJITEventListener
> 2. In NotifyLoadedFunction passed to orc::RTDyldObjectLinkingLayer ctor
> pass object and info to event listener's NotifyObjectEmitted
>
> Then, I profile the application with:
> perf record -k 1 ./app
>
> This generates a jit-*.dump file in ~/.debug/jit/llvm-IR-jit-*/.
>
> Inject the events into the perf data
> perf inject -j -i perf.data -o perf.data.jitted
>
> This creates jitted-*.so files in ~/.debug/jit/llvm-IR-jit-*/ for each
> JIT compiled function.
>
> Finally, I open the profile report:
> perf report -i perf.data.jitted
>
> But here is the problem. The JIT compiled functions are not
"resolved".
> I cannot "zoom in" to the code and annotate the instructions with
> profile information.
>
> Am I missing something here? Is there a small example somewhere which
> uses PerfJITEventListener with ORC?
>
> Best regards,
> Frank
>