首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >.NET可用内存使用率(如何防止向操作系统过度分配/释放内存)

.NET可用内存使用率(如何防止向操作系统过度分配/释放内存)
EN

Stack Overflow用户
提问于 2012-03-21 20:53:58
回答 6查看 7.7K关注 0票数 17

我目前正在开发一个网站,该网站大量使用缓存数据来避免往返。在启动时,我们会得到一个“大”图(数百个不同种类的对象)。这些对象是通过WCF检索并反序列化的(我们使用协议缓冲区进行序列化)我正在使用redgate的内存分析器来调试内存问题(内存似乎与我们在完成初始化后应该需要的内存量不符,最终得到了这个报告

现在我们可以从这份报告中收集到的是:

1)分配的大部分内存.NET是空闲的(它可能在反序列化过程中被正确分配,但现在它是空闲的,我希望它返回到操作系统)

2)内存是碎片化的(这很糟糕,因为每次我刷新现金都需要重做耗用内存的反序列化过程,这反过来又会创建一个大对象,它可能会因为碎片而抛出OutOfMemoryException )

3)我不知道为什么空间是碎片化的,因为当我查看大对象堆时,只有30个实例,15个object[]直接连接到GC,完全与我无关,1个是也直接连接到GC堆的字符数组,其余15个是我的,但不是导致这种情况的原因,因为如果我在代码中注释掉它们,我会得到相同的报告。

所以我的问题是,我能做些什么来更进一步呢?我真的不确定应该在调试/工具中寻找什么,因为我的内存似乎是碎片化的,但不是我的内存,而且.net分配了大量的空闲空间,我无法释放这些空闲空间。

另外,在回答之前请确保你很好地理解了这个问题,我不是在寻找一种在.net (GC.Collect)中释放内存的方法,而是在.net中释放已经释放的内存,到系统以及对所述内存进行碎片整理。

请注意,一个缓慢的解决方案很好,如果可以手动整理大堆的碎片,我会全力支持它,因为我可以在RefreshCache结束时调用它,如果它需要1到2秒的运行时间也没问题。

谢谢你的帮忙!

有几点我忘了: 1)这个项目是一个.net 2.0网站,我在.net 4池中运行它会得到相同的结果,如果我在.net 4池中运行它,并将其转换为.net 4并重新编译,我会得到同样的结果。

2)这些是发布构建的结果,所以调试构建不是问题。

3)这可能是非常重要的,我在webdev服务器中根本没有遇到这些问题,只有在IIS中,在webdev中,我得到的内存消耗相当接近我的实际消耗(好多,但不是5-10倍!)

EN

回答 6

Stack Overflow用户

发布于 2012-03-22 02:08:50

我知道这不是你想听到的答案,但是你不能强制释放内存给操作系统。然而,你想这么做的原因是什么呢?一旦你的物理内存不足,.NET会将它的堆释放回操作系统。但是,如果有足够的空闲物理内存,.NET将保留它的堆,以便将来更快地分配对象。如果你真的想强制.NET把它的堆释放回操作系统,我想你可以写一个C程序,它只是在内存耗尽之前执行错误锁定。这应该会导致操作系统向.NET发出信号,以释放堆中未使用的部分。

最好将未使用的内存重新分配给.NET,这样您的应用程序将具有更好的分配性能(因为运行时知道哪些内存是空闲的,哪些内存不是,分配可以只使用空闲内存,而不必调用操作系统来获得更多内存)。

垃圾收集器负责对堆进行碎片整理。有时(通常在收集运行期间),如果确定需要这样做,它会在堆中移动对象。(这就是为什么C++/CLI有“钉住”对象的pin_ptr构造的原因)。

碎片通常不是内存的大问题,因为它提供了快速的随机访问。

至于你的OutOfMemoryException,我没有一个好的答案。通常,我会怀疑您的旧对象图没有被收集(某个对象持有对它的引用,即“内存泄漏”)。但既然你用的是侧写器那我就不知道了。

票数 7
EN

Stack Overflow用户

发布于 2012-03-22 19:26:46

在大对象堆上分配的对象(对象>= 85,000字节,通常是数组)不会被垃圾收集器压缩。微软认为,移动这些物体的成本太高了。

建议尽可能重用大型对象,以避免在托管堆和VM空间上出现碎片。

http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

我假设您的大对象是由反序列化库创建的临时字节数组。如果库允许您提供自己的字节数组,则可以在程序开始时预先分配字节数组,然后重用它们。

票数 7
EN

Stack Overflow用户

发布于 2012-03-26 07:33:27

一些测试和一些C++之后,我已经找到了我获得如此多空闲内存的原因,这是因为IIS通过VM堆积实例化了CLR (提供一个动态链接库来实例化它,而不是VM堆积占用了同样多的初始内存,但随着时间的推移释放了大部分内存,这是我期望的行为)。所以这确实解决了我报告的内存问题,但是我仍然获得了大约100mb的空闲内存,我仍然认为这是由于碎片和碎片只被一次释放,因为分析器仍然报告内存碎片。所以,不要把我自己的答案标记为一个答案,希望有人能给我一些启发,或者告诉我可以修复这个问题或帮助我调试根本原因的工具。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9805058

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档