let's make dependency walker fast again
作者:互联网
let's make dependency walker fast again
原总结优化工具dependency walkerprocess monitorprocess explorer缘起
最近,经常需要调查 dll
加载失败的问题。前一阵子刚分享了一篇,感兴趣的小伙伴而可以点击 这里。相信,有 windows
开发经验的小伙伴儿一定听过 Dependency Walker
这款工具,它可是查看模块依赖关系的神兵利器。但是在我的机器上,Dependency Walker
运行的特别慢,经常无响应!慢了这么久,是时候提提速了。
重现问题
很容易就可以重现问题,随便拖动一个 dll
文件(或者 exe
文件)到 Dependency Walker
中,等大概 5
秒钟,就会出现大名鼎鼎的无响应界面,需要等待很久才能等到分析结果。
探查敌情
在大动干戈之前,先用 process explorer
粗略查看 Dependency walker
中各个线程的运行情况。
view-hang-dependency-walker
看来,只有一个线程在工作(其它两个线程是系统工作线程),也是界面线程。如果界面线程都用来处理其它工作,长时间没有处理界面消息的话,界面就会无响应。
从调用栈可知,Dependency Walker
在运行过程中会不断的调用 SearchPath
和 FindFirstFile
。从这两个函数的名字可以猜测是在搜索文件。
如果有超多文件需要搜素,那么整个过程慢是合理的。只从 process explorer
中并不能知道 Dependency Waler
在搜索哪些文件,在哪些地方搜索。
小贴士:使用
process explorer
的线程功能,可以很方便的快速定位一些问题,如有必要,再上调试器进行分析。
process monitor
观察进程文件操作记录对于 process monitor
来说简直是小菜一碟。因为预计时间会比较长,而且只需要关心 Dependency Walker
相关的事件,所以在开始前,先做好过滤。
拖动 process monitor
上的靶子图标到 Dependency Walker
上,表示只关心当前这个 Dependency Walker
实例相关的事件。勾选 Drop filtered Event
表示丢弃过滤的事件,因为会过滤掉大部分无关的事件,生成的记录文件会比较小,可以记录更多有用的事件。
filter-in-procmon
等 Dependency Walker
完成分析后,停止记录,查看文件相关事件。 dll
相关的事件一共有 247688
条。
好奇我是怎么知道的?请看下图:
filtered-dll-file-event
观察一个比较典型的文件( api-ms-win-core-rtlsupport-l1-1-0.dll
)的相关记录。该文件相关的事件数量是 908
条。
filtered-api-ms-win-core-rtlsupport-l1-1-0-dll-file-event
该文件相关的部分事件截图如下:
api-ms-win-core-rtlsupport-l1-1-0-dll-events-detail
在上图中,可以很明显的看到 Result
列大部分结果不是 Success
。这个在意料之中,因为正常情况下这个 dll
应该只在特定路径下才有。从 Path
列中的记录可知,搜索路径有很多个。
深入观察
如果仔细观察,可以发现搜索路径非常像典型的 Dll
搜索路径。Dll
搜索路径的官方参考资料链接为 https://docs.microsoft.com/zh-cn/windows/win32/dlls/dynamic-link-library-search-order?redirectedfrom=MSDN。
为了方便大家查看,我截取了相关部分,如下图:
dll-search-directories
我机器上的 PATH
环境变量如下图:
PATH-on-my-machine
如此看来,Dependency Walker
正是按照典型的 Dll
搜索路径在查找啊(默认情况,可以修改)!
通过上面的简单分析,可以初步判定:除了把应该写在工作线程的代码写在 UI
线程有点问题,其它地方没有明显问题,确实有很多工作需要处理。
只能从减少搜索路径的方向着手了。如果可以少搜索一些地方,那么工作量会显著下降,速度相应的会提高上来了。我第一个想到的办法就是改变 PATH
环境变量的值。
手动设置 PATH
最简单的办法是,设置 PATH
环境变量的值为空,这样就可以避免搜索 PATH
环境变量指定的相关路径了。如果调整全局的 PATH
环境变量会影响所有程序,不可取。但是可以通过脚本启动 Dependency Walker
,在启动 Dependency Walker
之前,设置 PATH
为空,这样只会影响 Dependency Walker
。保存下面的批处理脚本为 start_depends.bat
,双击运行即可。
set PATH=""
"C:\My\tools\DEPENDS\x64\Depends.exe"
通过以上脚本启动的 Dependency Walker
眼中的 PATH
是空。
如果再次拖动相同的文件到 Dependency Walker
中,基本上是秒出结果。如下图:
dependency-walker-with-empty-path
在修改 PATH
环境变量之前,大概需要 2
分钟左右才能看到结果,而现在只需要用 1
秒左右,是不是不止快了 100
倍呢?对于一些依赖更加复杂的程序,效率提升的会更加明显!
小贴士:只有确定不会从
PATH
中加载对应的DLL
,才可以设置PATH
为空。既然可以设置PATH
为空,就可以设置PATH
为任意值。
但是,这样的操作终究有些不自然。难道,Dependency Walker
本身就不支持设置搜索路径吗?
Dependency Walker 设置
简单的浏览了一遍 Dependency Walker
的菜单,发现可以通过 Options -> Configure Module Search Order...
来设置模块搜索顺序及搜索路径。
configure-module-search-order-in-dependency-walker
设置界面如下图:
set-module-search-order-in-dependency-walker
可以根据自己的需要进行设置。
小贴士:
The system's ’PATH‘ environment variable directories
指的是系统PATH
环境变量对应的路径,排除它,效果与把PATH
设置成空一样。
总结
-
Dependency Walker
可以自定义搜索目录,合理设置搜索目录,会大大提高搜索速度!默认情况下,
Dependency Walker
会搜索PATH
指定的路径,所以也可以通过修改PATH
环境变量的值达到相同的效果。 -
如果长时间(大概
5
秒钟)没有处理界面消息的话,界面就会无响应。
标签:again,make,fast,dll,Dependency,线程,搜索,Walker,PATH 来源: https://www.cnblogs.com/bianchengnan/p/13917836.html