gpt4 book ai didi

c# - GZIP解压C# OutOfMemory

转载 作者:太空狗 更新时间:2023-10-29 21:46:12 39 4
gpt4 key购买 nike

我有许多从 ftp 下载的大型 gzip 文件(大约 10MB - 200MB)需要解压。

所以我尝试谷歌并找到一些 gzip 解压缩的解决方案。

    static byte[] Decompress(byte[] gzip)
{
using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
{
const int size = 4096;
byte[] buffer = new byte[size];
using (MemoryStream memory = new MemoryStream())
{
int count = 0;
do
{
count = stream.Read(buffer, 0, size);
if (count > 0)
{
memory.Write(buffer, 0, count);
}
}
while (count > 0);
return memory.ToArray();
}
}
}

它适用于任何低于 50mb 的文件,但一旦我输入超过 50mb,我就会遇到系统内存不足异常。异常前的最后一个位置和内存长度是 134217728。我不认为它与我的物理内存有关系,我知道我不能拥有超过 2GB 的对象,因为我使用 32 位。

我还需要在解压文件后处理数据。我不确定内存流是否是这里最好的方法,但我真的不喜欢写入文件然后再次读取文件。

我的问题

  • 为什么我得到 System.OutMemoryException?
  • 解压缩 gzip 文件并在之后进行一些文本处理的最佳解决方案是什么?

最佳答案

MemoryStream 的内存分配策略对于海量数据并不友好。

由于 MemoryStream 的契约(Contract)是将连续数组作为底层存储,因此它必须经常为大流重新分配数组(通常为 log2(size_of_stream))。这种重新分配的副作用是

  • 重新分配的长拷贝延迟
  • 新数组必须适合已被先前分配严重碎片化的空闲地址空间
  • 新数组将位于 LOH 堆上,它有其怪癖(没有压缩,GC2 上的收集)。

因此,通过 MemoryStream 处理大型 (100Mb+) 流可能会导致 x86 系统出现内存不足异常。此外,返回数据的最常见模式是调用 GetArray,这额外需要与用于 MemoryStream 的最后一个数组缓冲区大致相同的空间量。

解决方法:

  • 成本最低的方法是将 MemoryStream 预增长到您需要的近似大小(最好稍微大一点)。您可以预先计算读取不存储任何内容的假流所需的大小(浪费 CPU 资源,但您将能够读取它)。还可以考虑返回流而不是字节数组(或返回 MemoryStream 缓冲区的字节数组以及长度)。
  • 如果您需要整个流或字节数组,另一种处理方法是使用临时文件流而不是 MemoryStream 来存储大量数据。
  • 更复杂的方法是实现将基础数据分成更小(即 64K) block 的流,以避免在流需要增长时在 LOH 上进行分配和复制数据。

关于c# - GZIP解压C# OutOfMemory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10423776/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com