【发布时间】:2021-12-29 18:37:06
【问题描述】:
我有一种情况,我分配了大量内存,但在许多较小的子阵列中。我注意到,一旦我通过每个数组大约 85,000 字节的阈值,性能就会明显变差。我假设性能下降是因为较小的数组被分配在“小对象堆”(SOH)而不是“大对象堆”(LOH)上。
| # of Arrays | Size of Each Array (bytes) | Allocation Time |
|---|---|---|
| 1,154 | 532,480 | 377ms |
| 1,319 | 465,920 | 412ms |
| 1,539 | 339,360 | 439ms |
| 1,847 | 332,800 | 435ms |
| 2,308 | 266,240 | 446ms |
| 3,077 | 199,680 | 491ms |
| 4,616 | 133,120 | 514ms |
| 9,231 | 66,560 | 4420ms |
请注意,在所有情况下,分配的总内存约为 586MB,但在最后一种情况下,分配所需的时间要长一个数量级。
我想快速解决这个性能问题的第一个想法是以某种方式告诉 C# 运行时我想要大型对象堆中的这些数组即使它们小于阈值。我认为这将使分配时间与其他情况保持一致。
但是,我似乎无法找到是否有办法做到这一点。看起来以前没有人想要一个对象进入大对象堆。所以,我问:是否有可能以某种方式标记这些数组以强制它们进入大型对象堆,即使它们小于 85,000 字节的阈值?
(将 85,000 字节阈值降低到 65,000 字节的方法也可以解决我的问题,但我也找不到解决方法!)
【问题讨论】:
-
这就像逃离马戏团加入孤儿院(又名对面土地)。分配问题、GC 压力和收集时间有很多解决方案。没有一个通常涉及射击你试图拯救的人质。
-
你有没有尝试分配 9231 个更大的数组?可能不是大小而是触发某些事情的对象计数(例如垃圾收集或其他内务处理)。
-
@Peter-ReinstateMonica 是的,分配 9231 个长度为 85000 的数组需要大约 670 毫秒。
-
我从未见过降低 LOH 截止限制的设置。但是,我更关心这是一个 X/Y 问题。如果这些是短暂的数组,您是否考虑过 ArrayPool ?如果您确实走上了 LOH 路径,迟早您可能会遇到更多问题,例如内存碎片等
-
您能说明一下您是如何测量分配时间的吗? (和分配代码)。我会说,如果测试写得不好,你最终不仅可以测量分配,还可以测量 SOH 案例的 GC。
标签: c# .net large-object-heap