xperf 调用堆栈跟踪,特定于 dll

Posted

技术标签:

【中文标题】xperf 调用堆栈跟踪,特定于 dll【英文标题】:xperf callstack tracing, specific to dlls 【发布时间】:2012-01-14 01:10:15 【问题描述】:

我在使用 xperf 跟踪获取完整调用堆栈时遇到了一些问题。这是在 Win7 64 位电脑上。在更高的级别上,我有一个加载多个 dll 的 exe,这些 dll 也完成了大部分工作。所有 pdb 文件都在一个目录中,并且我在可执行代码中获得了有效符号和调用堆栈,所以我很确定我的符号路径设置正确。

只要我的 exe 调用其中一个加载的 dll,我就会丢失调用堆栈信息,并且堆栈列会显示 plugin_name.dll!?,它在展开时会调用自身。权重选项卡显示高百分比(50-90%)和高计数,但我无法获得堆栈的任何实际函数调用。例如:

Process, Stack, Module, Function, Weight, % Weight, Count, TimeStamp
,    |     kernel32.dll!BaseThreadInitThunk, , , 59067.075556, 73.29, 59075, 
,    |     |- plugin_name.dll!?, , , 45036.186642, 55.88, 45042, 
,    |     |     plugin_name.dll!?, , , 45036.186642, 55.88, 45042, 

基于这些,

http://blogs.msdn.com/b/pigscanfly/archive/2009/08/06/stack-walking-in-xperf.aspx http://msdn.microsoft.com/en-us/library/windows/desktop/ff191014(v=vs.85).aspxhttp://msdn.microsoft.com/en-us/library/ff191014.aspx

这似乎表明 xperf

"...不知道该地址是什么可执行映像" “...超出了最大堆栈深度”

我发现的可能原因是 FPO(帧指针优化)已打开(我已使用 /Oy- 明确禁用,即使它们不应该打开),或最大堆栈深度超出了,我不确定如何确定这是否是我要击中的。

由于无法查看在 dll 中花费的时间,我无法获得非常有用的信息,因此我想弄清楚发生了什么。

有人对阅读或尝试的东西有任何建议吗?我缺少的 stackwalk 是否有任何限制?符号是否有任何特殊设置,特定于 dll 中的调用堆栈?

【问题讨论】:

当然,这是一个老问题 - 我仍然发现这是 WPA 的问题,我的 dll 的符号有时无法加载,所以我想注意,确保所有符号路径都指向c:\(对于本地和缓存位置),我从 c:(通过 mklink)运行我想要分析的内容,而且我不卸载我的 dll 似乎有帮助。如果有变化会更新 【参考方案1】:

大多数符号加载问题是由于调试引擎和符号服务器库不匹配造成的。

安装包含 Windows 性能套件的最新 sdk 并从同一目录运行 wpa/xperf 应该可以解决符号加载问题。我假设符号服务器路径是正确的。使用 procexp.exe 查看 dbghelp.dll 和 symsrv.dll 版本以及查看 xperf 的路径或目录中的任何工具都指向上述 dll 的最新可用或已发布版本。

谢谢, 苏珊特B

【讨论】:

【参考方案2】:

从here 尝试以下操作: 禁用寻呼执行器

为了在 64 位 Windows 上进行跟踪,您需要设置 DisablePagingExecutive 注册表项。这告诉操作系统不要将内核模式驱动程序和系统代码分页到磁盘,这是使用 xperf 获取 64 位调用堆栈的先决条件,因为 64 位堆栈遍历依赖于可执行映像中的元数据,并且在某些情况下xperf 堆栈遍历代码不允许触摸分页页面。从提升的命令提示符运行以下命令将为您设置此注册表项。

REG ADD "HKLM\System\CurrentControlSet\Control\Session Manager\Memory Management" -v DisablePagingExecutive -d 0x1 -t REG_DWORD -f

设置此注册表项后,您需要重新启动系统才能记录调用堆栈。设置此标志意味着 Windows 内核将更多页面锁定到 RAM 中,因此这可能会消耗大约 10 MB 的额外物理内存。

【讨论】:

感谢您的回复,不幸的是,我已经有了这套。我注意到的一件事似乎很奇怪,我的 dll 都没有缓存到符号目录 (c:\symbols)。我的 _NT_SYMBOL_PATH 包括 pdb 所在的目录,使用 xperf -symbols -i trace.etl 似乎也没有帮助。【参考方案3】:

创建一个新的环境变量DBGHELP,将其设置为1。现在创建一个环境变量 DBGHELP_LOG 并将其设置为像 D:\DbgHelpLog.txt 这样的日志文件。符号加载完成后,关闭 xperfview/wpa 并查看日志为什么符号加载失败。

诊断 DBGHELP 符号加载

http://blogs.msdn.com/b/matt_pietrek/archive/2005/04/12/407721.aspx

【讨论】:

以上是关于xperf 调用堆栈跟踪,特定于 dll的主要内容,如果未能解决你的问题,请参考以下文章

Android 调试跟踪不包含特定于应用程序的方法调用

来自未处理异常的 C++ 堆栈跟踪?

为啥没有“通用事件”的调用堆栈

NullReferenceException,没有堆栈跟踪......从哪里开始?

未调用特定于类的渲染器组件

为啥从内部类调用特定于对象的方法/字段时没有抛出任何错误?