LOH(Large Object Heap)是.NET中存放≥85,000字节对象的内存区域,因不参与GC压缩而易碎片化;高并发下频繁分配大对象会触发full GC,导致线程暂停、吞吐下降。

LOH 是什么,为什么高并发下它会成为瓶颈
LOH(Large Object Heap)是 .NET 中专门存放 ≥ 85,000 字节对象的内存区域。它不参与常规 GC 的 compact 阶段,意味着一旦分配,即使后续被回收,留下的碎片也不会被自动整理。在高并发场景下,频繁创建大对象(如 byte[]、string、大型 DTO 序列化结果)会导致 LOH 快速膨胀、碎片加剧,最终触发 full GC(即 blocking GC),暂停所有线程 —— 这就是吞吐骤降、延迟毛刺的常见根源。
哪些操作会在高并发中意外触发 LOH 分配
很多看似“轻量”的操作,在高并发放大后会悄悄落入 LOH。关键不是“你写了 new byte[100000]”,而是框架/库在背后替你干了这事:
-
HttpClient.GetStringAsync()返回的string如果响应体超 85KB,字符串本身进 LOH(UTF-16 编码,实际阈值 ≈ 42,500 字符) -
JsonSerializer.Serialize(obj)输出的string或byte[]容易越界,尤其嵌套深、字段多的对象 -
MemoryStream.ToArray()—— 每次调用都复制整个缓冲区到新byte[],极易命中 LOH - ASP.NET Core 中
ActionResult自动序列化返回值,T 若含大集合或长文本,风险极高
怎么查证你的服务正在被 LOH 拖累
别猜,用工具看真实行为。最直接的方式是启用 .NET 运行时事件追踪:
dotnet-trace collect --process-id--providers Microsoft-DotNETCore-EventPipe::0x1000000000000000:4
然后用 dotnet-counters monitor -p 观察关键指标:
ShopWind网店系统是国内最专业的网店程序之一,采用ASP语言设计开发,速度快、性能好、安全性高。ShopWind网店购物系统提供性化的后台管理界面,标准的网上商店管理模式和强大的网店软件后台管理功能。ShopWind网店系统提供了灵活强大的模板机制,内置多套免费精美模板,同时可在后台任意更换,让您即刻快速建立不同的网店外观。同时您可以对网模板自定义设计,建立个性化网店形象。ShopWind网
-
LOH Size:持续增长且不回落 → 内存泄漏或碎片堆积 -
% Time in GC> 5% 且伴随Gen 2 GC Count频繁上升 → LOH 触发 full GC -
Alloc Rate / sec突增时,若LOH Alloc Rate / sec同步飙升 → 确认是大对象主导分配
注意:.NET 6+ 默认启用 GCHeapHardLimit 和 LOH 压缩(需显式开启),但压缩本身有开销,不能无脑打开。
真正有效的缓解策略,不是避免大对象,而是绕过它
高并发服务的关键不是“不分配大对象”,而是“不让大对象生命周期和请求强绑定”。实操上优先考虑流式处理与池化:
- 用
Stream替代byte[]:比如JsonSerializer.SerializeAsync(stream, obj)直接写入响应流,不缓存完整 payload - 复用
ArrayPool分配缓冲区,严格.Shared.Rent() .Return(),避免每次 new - 对高频大字符串场景,改用
ReadOnlyMemory+Span解析,跳过 string 实例化 - ASP.NET Core 中启用
ResponseCompression可显著减小传输体积,间接降低序列化后对象大小
LOH 问题从来不是孤立的内存问题,它是并发模型、序列化方式、IO 路径共同作用的结果。最危险的不是某次分配,而是把 LOH 分配藏在中间件、过滤器或通用泛型方法里 —— 看似安全,压测一跑就崩。










