问题标签 [large-object-heap]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - 在 32 位 .NET 进程中分配超过 1,000 MB 的内存
我想知道为什么我不能在我的 32 位 .NET 进程中分配超过 1,000 MB 的内存。以下迷你应用程序在分配 1,000 MB 后引发 OutOfMemoryException。为什么是 1,000 MB,而不是 1.8 GB?我可以更改整个流程的设置吗?
PS:垃圾收集没有帮助。
编辑,澄清我想要什么:我编写了一个服务器应用程序,它在写入数据库/磁盘之前处理大量数据。我没有为所有内容创建临时文件,而是编写了一个内存缓存,这使得整个事情变得超级快。但是内存是有限的,所以我试图找出限制是什么。并且想知道为什么我的小测试程序在恰好 1,000 MB 之后抛出 OutOfMemoryException。
.net - GC.Collect 仅在第 2 代和大对象堆上
在我的应用程序中,有一个特定时间会同时释放多个大型对象。那时我想专门对大对象堆(LOH)进行垃圾收集。
我知道您不能这样做,您必须调用,GC.Collect(2)
因为 GC 仅在执行第 2 代收集时在 LOH 上调用。但是,我在文档中读到调用GC.Collect(2)
仍会在第 1 代和第 0 代上运行 GC。
是否可以强制 GC只收集第 2 代,而不包括第 1 代或第 0 代?
如果不可能,是否有理由这样设计 GC?
.net - 我如何知道可以分配给定类型的 .net 数组的实际最大元素数?
我知道 .net 中的所有数组都限制为 2 GB,在此前提下,我尽量不在数组中分配更多的 n = ((2^31) - 1) / 8 双倍。尽管如此,这个数量的元素似乎仍然无效。任何人都知道如何在运行时确定给定 sizeof(T) 的最大元素数?
我知道接近这个数字的任何数量都只是很多元素,但是,出于所有意图和目的,假设我需要它。
注意:我在 64 位环境中,有一个用于我的 AnyCPU 应用程序的目标平台,并且 RAM 中至少有 3100 MB 可用空间。
更新: 谢谢大家的贡献,抱歉我太安静了。对于给您带来的不便,我深表歉意。我无法重新表述我的问题,但我可以补充一点,我正在寻找的是解决这样的问题:
我自己的答案中的结果有点令人满意,但还不够好。此外,我还没有在另一台机器上测试它(很难找到另一台超过 4 GB 的机器)。此外,我一直在自己做一些研究,似乎没有便宜的方法可以在运行时计算它。无论如何,这只是一个加分项,我正在尝试完成的事情的用户都不能期望在没有能力的情况下使用我正在尝试实现的功能。
所以,换句话说,我只是想了解为什么数组的最大元素数加起来不等于 2GB ceteris paribus。我现在只需要一个最高的最大值。
c# - 我应该在使用大对象堆后立即调用 GC.Collect 以防止碎片吗
我的应用程序对大对象进行了大量的二进制序列化和压缩。未压缩的序列化数据集约为 14 MB。压缩后约为 1.5 MB。我发现每当我在我的数据集上调用 serialize 方法时,我的大型对象堆性能计数器就会从 1 MB 以下跃升至大约 90 MB。我也知道,在一个负载相对较重的系统下,通常在运行一段时间(几天)后,这个序列化过程发生了几次,当调用这个序列化方法时,应用程序会抛出内存异常,即使有似乎是足够的内存。我猜碎片化是问题所在(虽然我不能说我 100% 确定,但我已经很接近了)
我能想到的最简单的短期修复(我想我正在寻找短期和长期答案)是在我完成序列化过程后立即调用 GC.Collect。在我看来,这将从 LOH 中垃圾收集对象,并且可能会在其他对象添加到它之前这样做。这将允许其他对象紧紧地贴在堆中的剩余对象上,而不会造成太多碎片。
除了这个荒谬的 90MB 分配之外,我认为我没有其他任何使用 LOH 丢失的东西。这种 90 MB 的分配也比较少见(大约每 4 小时一次)。当然,我们仍然会有 1.5 MB 的数组,可能还有一些其他更小的序列化对象。
有任何想法吗?
由于良好的反应而更新
这是我完成工作的代码。实际上,我已经尝试将其更改为压缩 WHILE 序列化,以便序列化同时序列化为流,但我没有得到更好的结果。我还尝试将内存流预分配到 100 MB,并尝试连续两次使用相同的流,无论如何 LOH 都会上升到 180 MB。我正在使用 Process Explorer 来监控它。这太疯狂了。我想接下来我会尝试 UnmanagedMemoryStream 的想法。
如果你不愿意,我会鼓励你们尝试一下。它不必是这个确切的代码。只需序列化一个大数据集,你就会得到令人惊讶的结果(我的有很多表,大约 15 和很多字符串和列)
尝试使用 UnmanagedMemoryStream 进行二进制序列化后更新
即使我序列化为 UnmanagedMemoryStream,LOH 也会跳到相同的大小。看来无论我做什么,调用 BinaryFormatter 来序列化这个大对象都会使用 LOH。至于预分配,它似乎没有多大帮助。说我预分配说我预分配 100MB,然后我序列化,它将使用 170MB。这是代码。比上面的代码还要简单
中间的 GC.Collect() 只是用来更新 LOH 性能计数器。您将看到它将分配正确的 100 MB。但是当您调用序列化时,您会注意到它似乎将它添加到您已经分配的 100 个之上。
.net - 为什么机器上没有分页内存时Process.PagedMemorySize64 > 0?
我在页面文件大小设置为零的机器上运行 .net 代码。我的应用程序记录 System.Diagnostics.Process.PagedMemorySize64 并显示值 > 0。
怎么会这样?
PagedMemorySize64 的文档内容如下:
此属性返回的值表示进程使用的虚拟内存分页文件中的当前内存大小。
我错过了什么?
背景:
我这样做是为了确定我是否有内存泄漏。我使用的配置文件没有显示任何增长,但 System.Diagnostics.Process 的内存值继续增加。
我想我可能正在处理大对象堆碎片。我的程序正在显示大图像的 WPF 幻灯片放映,图像之间带有淡入淡出动画。
欢迎任何解释。
谢谢。
c# - 大型阵列和 LOH 碎片。什么是公认的约定?
我有一个关于一些无望的内存问题的其他活跃问题,这些问题可能涉及 LOH 碎片以及可能的其他未知数。
我现在的问题是,公认的做事方式是什么?如果我的应用程序需要在 Visual C# 中完成,并且需要处理 int[4000000] 的大数组,我怎么能不被垃圾收集器拒绝处理 LOH 所注定呢?
似乎我被迫将任何大型数组设为全局,并且永远不要在其中任何一个周围使用“新”这个词。所以,我留下了带有“maxindex”变量的不优雅的全局数组,而不是由函数传递的大小整齐的数组。
我一直被告知这是不好的做法。有什么选择?
是否有某种功能System.GC.CollectLOH("Seriously")
?有没有办法将垃圾收集外包给 System.GC 以外的东西?
无论如何,处理大型(> 85Kb)变量的普遍接受的规则是什么?
.net - 我如何知道在 .NET 的大对象堆 (LOH) 中分配了结构数组?
在使用 CLR Profiler 进行一些实验后,我发现:
在运行时,我如何知道在大对象堆 (LOH) 中分配了结构数组(或任何数组)?
c# - 内存流和大对象堆
我必须使用 WCF 通过不可靠的连接在计算机之间传输大文件。
因为我希望能够恢复文件并且我不想被 WCF 限制在我的文件大小上,所以我将文件分块为 1MB 块。这些“块”作为流传输。到目前为止,效果很好。
我的步骤是:
- 打开文件流
- 将文件中的块读入 byte[] 并创建 memorystream
- 转移块
- 回到 2. 直到整个文件被发送
我的问题出在第 2 步。我假设当我从字节数组创建内存流时,它将最终出现在 LOH 上并最终导致内存不足异常。我实际上无法创建此错误,也许我的假设是错误的。
现在,我不想在消息中发送 byte[],因为 WCF 会告诉我数组大小太大。我可以更改允许的最大数组大小和/或我的块的大小,但我希望有另一种解决方案。
我的实际问题:
- 我当前的解决方案会在 LOH 上创建对象吗?这会给我带来问题吗?
- 有没有更好的方法来解决这个问题?
顺便说一句:在接收端,我简单地从到达的流中读取较小的块并将它们直接写入文件,因此不涉及大字节数组。
编辑:
当前解决方案:
c# - 为什么大对象堆会增长而不是抛出异常?
在上一个问题中,我询问了最大化 LOH 上可分配的最大块的可能编程方法。我仍然看到问题,但现在我试图弄清楚为什么 LOH 的大小似乎会增长和缩小,但我仍然看到 OutOfMemoryExceptions 与其他人报告的由于 LOH 碎片化的情况相符.
为什么一个调用,例如,StringBuilder.EnsureCapacity 会为我抛出一个 OutOfMemoryException,但是从其他地方调用另一个会导致 LOH 的大小扩大(根据性能计数器,它正在增长和缩小)?
.net - 以编程方式确定大对象堆的限制
既然建议对大对象使用 IDisposal 模式,我想知道为什么似乎没有可靠的方法来确定限制,从哪个对象被认为是“大”的?
在内部存在这样的区别:在 LOH 上分配的对象的下限。每当它以 85k 的形式公开传达时,就会同时阻止一个人依赖该数字。
特别是对于处理大量“更大”数组的应用程序,为了实现正确的内存管理和防止 LOH 碎片,必须需要该限制。另一方面,对于“较小”的数组,从内存消耗的角度来看,IDisposal 没有意义。在这里,压缩 GC 做得更好。
为什么没有这样的东西
甚至更好:
编辑:我知道,IDisposable 模式只是建议正确处理特殊对象(fe“大”或非托管对象)。我的问题不是假设,运行时会对这些对象进行任何特殊处理。我宁愿要求对模式的实现者(也可能是其他人)提供运行时支持,以了解对象何时应该遵循特殊的内存管理。