分析 DLL/LIB 膨胀
我在VS2005中继承了一个相当大的C++项目,它编译成大约5MB的DLL。我想缩小库的大小,以便对于从慢速网络共享使用它的客户端来说,它可以通过网络更快地加载。
我知道如何通过分析代码、包含内容和项目设置来做到这一点,但我想知道是否有任何可用的工具可以更轻松地查明代码的哪些部分占用了最多的空间。有没有办法生成 DLL 布局的“配置文件”?关于库映像中哪些内容消耗了空间以及消耗了多少空间的报告?
I've inherited a fairly large C++ project in VS2005 which compiles to a DLL of about 5MB. I'd like to cut down the size of the library so it loads faster over the network for clients who use it from a slow network share.
I know how to do this by analyzing the code, includes, and project settings, but I'm wondering if there are any tools available which could make it easier to pinpoint what parts of the code are consuming the most space. Is there any way to generate a "profile" of the DLL layout? A report of what is consuming space in the library image and how much?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
当您构建 DLL 时,您可以将 /MAP 传递给链接器让它生成一个映射文件,其中包含结果图像中所有符号的地址。您可能需要编写一些脚本来计算每个符号的大小。
使用“字符串”实用程序扫描 DLL 可能会发现意外或未使用的DLL可打印字符串(例如资源、RCS ID、
__FILE__
宏、调试消息、断言等)。另外,如果您尚未在启用 /Os 的情况下进行编译,则它是值得一试。
When you build your DLL, you can pass /MAP to the linker to have it generate a map file containing the addresses of all symbols in the resulting image. You will probably have to do some scripting to calculate the size of each symbol.
Using a "strings" utility to scan your DLL might reveal unexpected or unused printable strings (e.g. resources, RCS IDs,
__FILE__
macros, debugging messages, assertions, etc.).Also, if you're not already compiling with /Os enabled, it's worth a try.
如果您的最终目标只是修剪 DLL 的大小,那么在调整编译器设置后,您可能会通过 UPX。 UPX 是一款出色的 DLL 和 EXE 压缩实用程序;它也是具有非病毒许可证的开源产品,因此可以在商业/闭源产品中使用。
我只让它在最高压缩设置(暴力选项)上出现病毒警告,因此如果您使用低于该设置的设置,可能会没事。
If your end goal is only to trim the size of the DLL, then after tweaking compiler settings, you'll probably get the quickest results by running your DLL through UPX. UPX is an excellent compression utility for DLLs and EXEs; it's also open-source with a non-viral license, so it's okay to use in commercial/closed-source products.
I've only had it turn up a virus warning on the highest compression setting (the brute-force option), so you'll probably be fine if you use a lower setting than that.
虽然我不知道任何二进制大小分析器,但您也可以查找最大的目标文件 (.obj) - 这至少可以让您了解有问题的地方。
当然,这需要一个足够模块化的项目。
While i don't know about any binary size profilers, you could alternatively look for what object files (.obj) are the biggest - that gives you at least an idea of where your problematic spots are.
Of course this requires a sufficiently modularized project.
您还可以尝试静态链接而不是使用 dll。事实上,当库静态链接时,链接器会从最终的 exe 中删除所有未使用的函数。有时最终的 exe 只是稍微大一点,而您没有更多的 dll。
You can also try to link statically instead of using a dll. Indeed, when the library is linked statically the linker removes all unused functions from the final exe. Sometime the final exe is only slightly bigger and you don't have any more dll.
如果您的 DLL 这么大,因为它导出的 C++ 函数具有异常长的损坏名称,则另一种方法是使用
.DEF
文件按序数导出函数,不带名称(使用NONAME
代码> .DEF 文件中)。有点脆弱,但它减少了 DLL 大小、EXE 大小和加载时间。参见例如 http://home.hiwaay.net/~georgech/WhitePapers/导出/Exp.htm
If your DLL is this big because it's exporting C++ function with exceptionally long mangled names, an alternative is to use a
.DEF
file to export the functions by ordinal, without name (usingNONAME
in the .DEF file). Somewhat brittle, but it reduces the DLL size, EXE size and load times.See e.g. http://home.hiwaay.net/~georgech/WhitePapers/Exporting/Exp.htm
鉴于所有 .obj 文件的大小大致相同,假设您使用预编译标头,请尝试创建一个空的 obj 文件并查看它有多大。这将使您了解 PCH 编译导致的每个 .obj 的比例。顺便说一句,链接器将能够删除那里的所有重复项。或者,您可以尝试禁用 PCH,以便 obj 文件可以更好地指示罪魁祸首在哪里。
Given that all your .obj files are about the same size, assuming that you're using precompiled headers, try creating an empty obj file and see how large it is. That will give you an idea of the proportion of each .obj that's due to the PCH compilation. The linker will be able to remove all the duplicates there, incidentally. Alternatively you could try disabling PCH so that the obj files will give you a better indication of where the main culprits are.
都是好的建议。我所做的就是获取地图文件,然后观察它。我过去发现的一件事是,很大一部分空间被一个或多个类库占用,因为某个地方的某个变量被声明为具有一种听起来可以节省一些编码的类型努力但并不是真正必要的。
就像在 MFC 中一样(还记得吗?),它们有一个包装类来处理 Win32 提供的所有内容,例如控件、字体等。这些会占用大量空间,而且您并不总是需要它们。
另一件可能占用大量空间的事情是您可以在没有的情况下进行管理的集合类。另一个是您不使用的 cout I/O 例程。
All good suggestions. What I do is get the map file and then just eyeball it. The kind of thing I've found in the past is that a large part of the space is taken by one or more class libraries brought in by the fact that some variable somewhere was declared as having a type that sounded like it would save some coding effort but wasn't really necessary.
Like in MFC (remember that?) they have a wrapper class to go around every thing like controls, fonts, etc. that Win32 provides. Those take a ton of space and you don't always need them.
Another thing that can take a ton of space is collection classes you could manage without. Another is cout I/O routines you don't use.
我建议使用以下方法之一:
覆盖 - 您可以运行覆盖工具,希望检测到一些死代码
缓存 - 在初始时将 dll 缓存在客户端activatio
分割 - 将dll分割成几个较小的dll,使用bootstrap dll启动应用程序,并在应用程序启动后下载其他dll
编译和链接 - 使用较小的运行时库、使用大小优化进行编译等。请参阅此链接以获取更多建议。
压缩 - 如果您的dll中有数据或大量资源,您可以压缩它们,并仅在下载后或运行时解压缩。
i would recommend one of the following:
coverage - you can run a coverage tool in the hope of detecting some dead code
caching - cache the dll on the client side on the initial activatio
splitting - split the dll into several smaller dlls, start the application with the bootstrap dll and download the other dlls after the application starts
compilation and linking - use smaller run time library, compile with size optimization, etc. see this link for more suggestions.
compression - if you have data or large resources within the dll, you can compress them and decompress only after the download or at runtime.