Tag: 大对象堆

来自队列的大对象堆和字符串对象

我有一个Windows控制台应用程序应该运行几天和几个月没有重新启动。 该应用程序从MSMQ检索“工作”并处理它。 有30个线程同时处理工作块。 来自MSMQ的每个工作块大约为200kb,其中大部分工作块分配在单个String对象中。 我注意到,在处理了大约3-4千个这些工作块之后,应用程序的内存消耗非常高,消耗了1到1.5 GB的内存。 我通过分析器运行应用程序并注意到大部分内存(可能是一个演出)在大对象堆中未使用但结构是分段的。 我发现这些未使用的(垃圾收集)字节中有90%是先前分配的字符串。 我开始怀疑从MSMQ进来的字符串是分配,使用然后解除分配,因此是碎片的原因。 我明白像GC.Collect(2或GC.Max …)这样的东西不会有用,因为它们是gc大对象堆但不压缩它(这是问题)。 所以我认为我需要的是缓存这些字符串并以某种方式重用它们,但由于字符串是不可变的,我将不得不使用StringBuilders。 我的问题是:无论如何不改变底层结构(即使用MSMQ,因为这是我无法改变的),并且仍然避免每次初始化一个新的String以避免分裂LOH? 谢谢,雅尼斯 更新:关于如何检索这些“工作”块 目前,它们作为WorkChunk对象存储在MSMQ中。 这些对象中的每一个都包含一个名为Contents的String和另一个名为Headers的String。 这些是实际的文本数据。 如果需要,我可以将存储结构更改为其他内容,如果需要,可以将底层存储机制更改为MSMQ以外的其他内容。 目前我们在工作节点方面 WorkChunk chunk = _Queue.Receive(); 所以在这个阶段我们几乎无法缓存。 如果我们以某种方式改变了结构,那么我想我们可以做一些进步。 在任何情况下,我们都必须解决这个问题,以便我们尽一切可能避免浪费数月的工作。 更新:我继续尝试下面的一些建议并注意到这个问题无法在我的本地计算机上运行(运行Windows 7 x64和64位应用程序)。 这使得事情变得更加困难 – 如果有人知道为什么那么它真的有助于在本地重新调整这个问题。

使用字节数组时堆积碎片

我有一个C#4.0应用程序(单个生产者/单个消费者),它以块的forms传输大量数据。 虽然没有新的内存分配,但一段时间后内存不足。 我使用Redgate内存分析器分析内存,那里有很多可用内存。 它说由于碎片化而无法使用空闲内存。 我使用阻塞集合作为缓冲区和字节数组作为成员: BlockingCollection segments = new BlockingCollection(8); // producer: segments.Add(buffer); // consumer: byte[] buffer = _segments.Take(); 如何避免托管内存碎片?

大arrays和LOH碎片。 什么是公认的惯例?

关于一些可能涉及LOH碎片的可能还有其他未知因素的无望记忆问题,我在这里还有另一个活跃的问题。 我现在的问题是,接受的做事方式是什么? 如果我的应用程序需要在Visual C#中完成,并且需要处理大型数组到int [4000000]的调整,我怎么能不注意垃圾收集器拒绝处理LOH? 似乎我被迫将任何大型数组全局化,并且从不在它们周围使用“new”这个词。 所以,我留下了带有“maxindex”变量的不合适的全局数组,而不是由函数传递的整齐大小的数组。 我总是被告知这是不好的做法。 还有什么选择? System.GC.CollectLOH(“Seriously”)是否有某种function? 是否有可能将垃圾收集外包给System.GC以外的其他方式? 无论如何,处理大型(> 85Kb)变量的普遍接受的规则是什么?

记忆流和大对象堆

我必须使用WCF通过不可靠的连接在计算机之间传输大文件。 因为我希望能够恢复文件并且我不希望受到WCF的文件大小限制,所以我将这些文件分块为1MB。 这些“块”以流的forms传输。 到目前为止哪个方面效果很好。 我的步骤是: 打开文件流 从文件中读取块到byte []并创建内存流 转移块 返回2.直到整个文件发送 我的问题在第2步。我假设当我从字节数组创建一个内存流时,它将最终在LOH上并最终导致一个outofmemoryexception。 我实际上无法创建此错误,也许我的假设是错误的。 现在,我不想在消息中发送byte [],因为WCF会告诉我数组大小太大。 我可以更改允许的最大数组大小和/或我的块的大小,但我希望有另一种解决方案。 我的实际问题: 我目前的解决方案是否会在LOH上创建对象,这会导致我的问题吗? 有没有更好的方法来解决这个问题? 顺便说一句:在接收端,我简单地从到达的流中读取较小的块并将它们直接写入文件,因此不涉及大字节数组。 编辑: 当前解决方案 for (int i = resumeChunk; i < chunks; i++) { byte[] buffer = new byte[chunkSize]; fileStream.Position = i * chunkSize; int actualLength = fileStream.Read(buffer, 0, (int)chunkSize); Array.Resize(ref buffer, actualLength); using (MemoryStream stream = new […]

在32位.NET进程中分配超过1,000 MB的内存

我想知道为什么我无法在32位.NET进程中分配超过1,000 MB的内存。 以下迷你应用程序在分配1,000 MB后抛出OutOfMemoryException。 为什么1,000 MB,而不是说1.8 GB? 我可以改变流程范围的设置吗? static void Main(string[] args) { ArrayList list = new ArrayList(); int i = 0; while (true) { list.Add(new byte[1024 * 1024 * 10]); // 10 MB i += 10; Console.WriteLine(i); } } PS:垃圾收集没有帮助。 编辑,澄清我想要的:我编写了一个服务器应用程序,在写入数据库/磁盘之前处理大量数据。 我没有为所有内容创建临时文件,而是编写了一个内存缓存,这使得整个过程非常快。 但记忆是有限的,所以我试图找出限制是什么。 并且想知道为什么我的小测试程序在1,000 MB之后抛出了OutOfMemoryException。