【发布时间】:2011-10-14 10:08:24
【问题描述】:
我有一个 Windows 控制台应用程序,它应该可以运行数天和数月而无需重新启动。该应用程序从 MSMQ 检索“工作”并对其进行处理。有 30 个线程同时处理一个工作块。
来自 MSMQ 的每个工作块大约 200kb,其中大部分分配在单个 String 对象中。
我注意到,在处理了大约 3-4 千个这样的工作块之后,应用程序的内存消耗非常高,消耗了 1-1.5 GB 的内存。
我通过分析器运行应用程序并注意到大部分内存(可能是 gig 左右)在大型对象堆中未使用,但结构是碎片化的。
我发现这些未使用的(垃圾收集)字节中有 90% 是以前分配的字符串。我开始怀疑来自 MSMQ 的字符串被分配、使用然后解除分配,因此是碎片的原因。
我知道像 GC.Collect(2 or GC.Max...) 这样的东西不会有帮助,因为它们 gc 大对象堆但不压缩它(这是这里的问题)。所以我认为我需要缓存这些字符串并以某种方式重新使用它们,但由于字符串是不可变的,我将不得不使用 StringBuilders。
我的问题是:是否无论如何不改变底层结构(即使用 MSMQ,因为这是我无法改变的)并且仍然避免每次都初始化一个新字符串以避免分割 LOH?
谢谢, 雅尼斯
更新:关于当前如何检索这些“工作”块
目前这些在 MSMQ 中存储为 WorkChunk 对象。这些对象中的每一个都包含一个名为 Contents 的字符串和另一个名为 Headers 的字符串。这些是实际的文本数据。如果需要,我可以将存储结构更改为其他内容,如果需要,我可以将底层存储机制更改为 MSMQ 以外的其他内容。
目前我们在工作节点方面
WorkChunk 块 = _Queue.Receive();
所以在这个阶段我们可以缓存的东西很少。如果我们以某种方式改变结构,那么我想我们可以取得一些进展。无论如何,我们都必须解决这个问题,所以我们将尽一切努力避免浪费数月的工作。
更新:我继续尝试以下一些建议,并注意到无法在我的本地计算机上重现此问题(运行 Windows 7 x64 和 64 位应用程序)。这让事情变得更加困难 - 如果有人知道原因,那么它真的会帮助在本地重新解决这个问题。
【问题讨论】:
-
您如何接收这些字符串?一旦它们成为字符串,您就会被卡住。如果它们来自流或字节 [],您可能有一些选择。
-
嗨 Henk - 查看更新以获取有关这些工作块的更多信息
-
但这是一个实际问题吗?在具有 >= 8GB RAM 的 64 位 PC 上 1.5GB 应该能够继续。
-
但最终会由于分页过多而缓慢爬行...这不是哲学问题 - 它每天都会发生!
-
您能否偶尔停止接受作业,完成您正在运行的所有作业(释放所有对象),运行 GC.Collect(),然后再次开始接受作业?
标签: c# .net memory-management memory-leaks large-object-heap