.NET 性能最佳做法:避免将大型请求正文或响应正文读取到内存中

在 .NET 中,每个大于 85 KB 的对象分配都最终处于大型对象堆 (LOH) 中。大型对象在两方面的成本十分高昂:
  • 分配成本较高,因为必须清除新分配的大型对象的内存。CLR 可保证清除所有新分配的对象的内存。

  • LOH 与堆的其余部分一起收集。LOH 需要完整垃圾回收或第 2 代收集。.

此博客文章简洁地描述了问题:

分配大型对象时,它标记为第 2 代对象。 而不是与小型对象一样标记为第 0 代。 后果是,如果在 LOH 中内存不足,GC 会清理整个托管堆,而不仅是 LOH。 因此它会清理第 0 代、第 1 代和第 2 代,包括 LOH。 这称为完整垃圾回收,是最耗时的垃圾回收。 对于许多应用程序,这可以接受。 但肯定不适用于高性能 Web 服务器,在这类服务器中,需要极少的大内存缓冲区来处理普通 Web 请求(从套接字读取、解压缩和解码 JSON 等)。

以本机方式将大型请求或响应正文存储到单个 byte[] 或 string 中:

  • 可能会导致 LOH 中的空间快速用尽。

  • 由于运行完整 GC,可能会导致应用出现性能问题。