我有一个Windows控制台应用程序,应该在几天或几个月内不重新启动的情况下运行。该应用程序从MSMQ中检索“工作”并处理它。有30个线程同时处理工作块。来自队列的大对象堆和字符串对象
来自MSMQ的每个工作块约为200kb,其中大部分工作块分配在一个String对象中。
我注意到,在处理了大约3-4,000个这样的工作块之后,应用程序的内存消耗非常高,消耗1 - 1.5 GB的内存。
我通过探查器运行应用程序,并注意到大部分这种内存(可能是一个演出等)没有在大对象堆中使用,但结构是零散的。
我发现这些未使用(垃圾收集)字节中的90%是以前分配的字符串。然后我开始怀疑从MSMQ进入的字符串被分配,使用和解除分配,因此是碎片化的原因。
据我所知,像GC.Collect(2或GC.Max ...)这样的东西不会帮助,因为他们gc大对象堆但不压缩它(这是这里的问题)。所以我认为我需要的是缓存这些字符串并以某种方式重新使用它们,但由于字符串是不可变的,我必须使用StringBuilders。
我的问题是:无论如何不改变底层结构(即使用MSMQ,因为这是我不能改变的),并且仍然避免每次都初始化一个新的String以避免碎片化LOH?
感谢, 雅尼斯
UPDATE:关于这些 “作品” 块目前如何检索
目前,这些被存储为MSMQ WorkChunk对象。每个对象都包含一个名为Contents的字符串和另一个名为Headers的字符串。这些是实际的文本数据。如果需要,我可以将存储结构更改为其他的存储结构,如果需要,可以将潜在的存储机制更改为MSMQ以外的其他存储结构。
在工作节点侧目前我们做
WorkChunk块= _Queue.Receive();
所以在这个阶段我们没有什么可以缓存的。如果我们以某种方式改变了结构,那么我想我们可以取得一些进展。无论如何,我们必须解决这个问题,所以我们会尽一切努力避免抛出数月的工作。
更新:我继续尝试下面的一些建议,并注意到这个问题不能在我的本地机器上运行(运行Windows 7 x64和64位应用程序)。这使事情变得更加困难 - 如果有人知道为什么那么它真的有助于在本地重新解决这个问题。
你是如何收到这些字符串的?一旦他们是字符串,你就卡住了。我来自一个流或字节[]你可能有一些选择。 –
嗨亨克 - 看看更新以获取有关这些工作块的更多信息 – Yannis
但这是一个实际的问题?具有> = 8GB RAM的64位PC上的1.5GB应该可以继续。 –