减少大型陌生代码库的内存占用面积


4

假设您在C/C++中有相当大的(〜2.2 MLOC)Windows相当老的(从10多年前开始的)Windows桌面应用程序。大约10%的模块是外部的,没有源代码,只有调试符号。

你会如何将应用程序的内存占用减少一半?至少,你会怎么做才能找出内存消耗的位置?

0

我不认为你的问题是好的。

源代码的大小与内存占用不直接相关。当然,编译后的代码会占用一些内存,但是应用程序可能会自己拥有内存需求。静态(在代码中声明的变量)和动态(应用程序创建的对象)。

我建议你简介程序执行并仔细研究代码。

  0

源代码提示的大小,在项目的整体复杂性。您认为需要多长时间“仔细研究”400 KLOC? :) 23 9月. 082008-09-23 19:01:56

  0

它应该很容易。 400k不是我所谓的大:)因为你只需要检查堆分配,找到所有的malloc和新的调用,你几乎在那里。 23 9月. 082008-09-23 19:06:57

  0

gbjbaanb,我希望我可以告诉你*只是*模块依赖关系图:)和有关“找到所有的malloc和新的”,还有至少SysAllocString(经常埋在CComBSTRs内) 23 9月. 082008-09-23 19:45:05


2

这不是一件容易的事。首先追查你找到的任何内存泄漏(一个好的工具是Rational Purify)。浏览源代码并尝试优化数据结构和/或算法。
对不起,如果这听起来很悲观,但是将内存使用量减少50%听起来不太现实。


7

使用包装函数覆盖malloc()/ free()和new()/ delete(),它们跟踪分配的大小和(通过记录调用堆栈并稍后在符号表中进行解析)从。关闭时,让包装显示仍分配的内存。

这应该使您能够计算出最大分配的位置并捕获任何泄漏。

  0

您可以详细说明覆盖分配函数的最佳方法应用程序范围内,最好是有限的源代码更改?另外,还有很多COM/BSTR处理;我相信他们的分配者不能被排除在分析之外。 23 9月. 082008-09-23 19:39:20


3

this is description/skeleton内存跟踪应用程序我用来减少我们游戏的内存消耗20%。它帮助我追踪由外部模块完成的许多分配。

  0

之前没有听说过调试接口访问 - upvoted。 23 9月. 082008-09-23 20:33:56


0

一是地方开始对我来说将是:

应用程序做了很多预分配内存以供以后使用?这种记忆是否经常坐在未使用的地方,从未分发过?考虑根据需要切换到新建/删除(或更好地使用smart_ptr)。

是否代码使用作为

Object arrayOfObjs[MAX_THAT_WILL_EVER_BE_USED]; 

一个静态数组,例如,该阵列中分发的OBJ?如果是这样,请考虑手动管理此内存。


1

有一个机会是你可以非常快地发现一些显着的低效率。首先,你应该检查什么是内存使用。我发现一个非常方便的工具是Memory Validator

一旦你有这个“内存使用情况地图”,你可以检查低挂水果。是否有任何数据结构消耗大量内存,可以用更紧凑的形式表示?这通常是可能的,尤其是,当数据访问得到很好的封装,并且当你有一个可用的CPU电源时,你可以专门在每次访问时对它们进行压缩/解压缩。

  0

这取决于他的意思是“10年前创建,自始不变”,或“在过去的10年中已经有机地生长并积累了残余物”。第二类应用程序绝对可以成为内存猪。 23 9月. 082008-09-23 19:08:28

  0

它一直在增长。并积累。一如既往,减少资源消耗的要求从上面传递下来。 23 9月. 082008-09-23 19:31:54


0

内存使用分析工具之一是LeakDiag,可用于free download from Microsoft。它显然允许将所有用户模式分配器挂接到VirtualAlloc,并随时将进程分配快照转储为XML。这些快照可用于确定哪些调用堆栈分配大部分内存以及哪些调用堆栈正在泄漏。它缺乏用于快照分析的漂亮前端(除非通过Microsoft Premier支持获得LDParser/LDGrapher),但所有数据都在那里。需要注意的

一件事是,你可能有从BSTR分配假阳性泄漏由于缓存,看"Hey, why am I leaking all my BSTR's?"