我试图获得一个很好的我的Rust代码的火焰图。不幸的是,Xcode 8.3不再支持导出分析数据了,所以我一直在尝试使用DTrace来获取分析数据。
我在我的Cargo.toml
中为发布二进制文件启用了调试信息:
[profile.release]
debug = true
然后我运行发布二进制文件(mybinaryname
),并使用DTrace示例堆栈跟踪:
sudo dtrace -n 'profile-997 /execname == "mybinaryname"/ { @[ustack(100)] = count(); }' -o out.user_stacks
最终结果如下:
0x10e960500
0x10e964632
0x10e9659e0
0x10e937edd
0x10e92aae2
0x10e92d0d7
0x10e982c8b
0x10e981fc1
0x7fff93c70235
0x1
1
为了比较,获得iTerm2
的痕迹让我得到了很好的痕迹:
CoreFoundation`-[__NSArrayM removeAllObjects]
AppKit`_NSGestureRecognizerUpdate+0x769
CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__+0x17
CoreFoundation`__CFRunLoopDoObservers+0x187
CoreFoundation`__CFRunLoopRun+0x4be
CoreFoundation`CFRunLoopRunSpecific+0x1a4
HIToolbox`RunCurrentEventLoopInMode+0xf0
HIToolbox`ReceiveNextEventCommon+0x1b0
HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter+0x47
AppKit`_DPSNextEvent+0x460
AppKit`-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:]+0xaec
AppKit`-[NSApplication run]+0x39e
AppKit`NSApplicationMain+0x4d5
iTerm2`main+0x6e
libdyld.dylib`start+0x1
iTerm2`0x1
1
是否可以在Rust代码中获得带有调试信息的堆栈跟踪? (Xcode的仪器肯定可以看到功能名称,所以它们就在那里!)如果有可能,我是否需要采取一些额外的步骤,或者我只是做错了什么?
答案 0 :(得分:5)
我找到了一个解决方法,并且了解了为什么它可能不起作用,但其原因并非100%明确。
rustc
生成的调试符号可以在target/release/deps/mybinaryname-hashcode.dSYM
中找到。在同一目录中,有一个符号对应的二进制文件target/release/deps/mybinaryname-hashcode
。
MacOS上的调试符号查找库非常神奇 - 与mentioned in the LLDB docs一样,使用各种方法(包括Spotlight搜索)找到符号。我甚至不确定哪些Frameworks是Xcode的仪器和捆绑的DTrace使用的。 (有关于称为DebugSymbols.framework和CoreSymbolication.framework的框架的提及。)由于这种魔力,我放弃了试图理解为什么不起作用。
解决方法是将dtrace
-p
选项与被检查流程的PID一起传递:
sudo dtrace -p $PID -n 'profile-997 /pid == '$PID'/ { @[ustack(100)] = count(); }' -o $TMPFILE &>/dev/null
以下是man
的{{1}}:
获取指定的进程ID pid,缓存其符号表,并在完成时退出。如果命令行中存在多个-p选项,则dtrace会在所有命令退出时退出,并在每个进程终止时报告退出状态。第一个进程ID可用于命令行中指定的任何D程序,或通过$ target宏变量使用-s选项。
目前尚不清楚为什么默认显示各种其他二进制文件的调试信息,或者为什么Rust二进制文件需要-p
选项,但它可以作为一种解决方法。