【问题标题】:Avoiding the LOH when reading a binary读取二进制文件时避免 LOH
【发布时间】:2013-03-24 18:36:05
【问题描述】:

这个问题是对 Efficient way to transfer many binary files into SQL Server database

我最初问为什么使用File.ReadAllBytes 会导致快速的内存使用,并得出结论使用该方法将数据放在大型对象堆上,在运行时不容易回收。

我现在的问题是如何避免这种情况?

using (var fs = new FileStream(path, FileMode.Open))
{
    using (var ms = new MemoryStream())
    {
        byte[] buffer = new byte[2048];
        int bytesRead;
        while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
        {
            ms.Write(buffer, 0, bytesRead);
        }
        return new CustomFile { FileValue = ms.ToArray() };
   }
}

以下代码旨在通过分块读取文件而不是一次读取文件来解决此问题,但它似乎存在相同的问题。

【问题讨论】:

    标签: c# memory-management io large-object-heap


    【解决方案1】:

    内存流保存整个数据的内部数组(最终返回)。只要您继续连接到内存流,您读取 2048 字节的块并不重要。如果您需要将数据作为包含整个文件的数组返回,那么您最终会经常在大对象堆中创建该数组。

    如果目标(BLOB 字段或类似字段)不允许您以除单字节数组之外的任何其他方式传入数据,那么您无法绕过分配包含所有数据的字节数组。

    将数据传输到目的地的最佳方式当然是目的地也支持流语义。

    int Transfer(Stream source, Stream target)
    {
       byte buffer = new byte[BufSize];
       int totalBytesTransferred = 0;
       while ((bytesRead = source.Read(buffer, 0, BufSize)) > 0)
       {
          target.Write(buffer, 0, bytesRead);
          totalBytesTransferred += bytesRead;       
       }
       return totalBytesTransferred;
    }
    

    这是否可能取决于目标(例如数据库 BLOB)是否支持向目标打开流。

    【讨论】:

    • 我们在 SQL 2008 R2 中使用 Nhibernate,我不确定是否可以直接保存流。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    • 2017-10-01
    • 2011-09-03
    • 2016-01-15
    相关资源
    最近更新 更多