将巨大的long数组写入磁盘

有里

我需要将大量的long(最大5GB)数组写入磁盘。我尝试使用,BinaryFormatter但似乎只能写入小于2GB的数组:

long[] array = data.ToArray();
FileStream fs = new FileStream(dst, FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
try
{
    formatter.Serialize(fs, array);
}
catch (SerializationException e)
{
    Console.WriteLine("Failed to serialize. Reason: " + e.Message);
    throw;
}
finally
{
    fs.Close();
}

此代码抛出IndexOutOfRangeException较大的数组。

我不想为每个元素保存元素,因为这会花费太多时间。有什么适当的方法可以保存这么大的数组吗?

每个元素的书写元素:

using (BinaryWriter writer = new BinaryWriter(File.Open(dst, FileMode.Create)))
{
    foreach(long v in array)
    {
        writer.Write(v);
    }
} 

这很慢。

马塞尔·N。

好的,所以我可能对MMF有点过头了。这是一个更简单的版本,仅具有文件流(我认为这是Scott Chamberlain在评论中建议的内容)。

3Gb阵列的时间(在新系统上):

  1. MMF:〜50秒。
  2. FilStream:约30秒。

码:

long dataLen = 402653184; //3gb represented in 8 byte chunks
long[] data = new long[dataLen];
int elementSize = sizeof(long);

Stopwatch sw = Stopwatch.StartNew();
using (FileStream f = new FileStream(@"D:\Test.bin", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read, 32768))
{
    int offset = 0;
    int workBufferSize = 32768;
    byte[] workBuffer = new byte[workBufferSize];
    while (offset < dataLen)
    {
        Buffer.BlockCopy(data, offset, workBuffer, 0, workBufferSize);
        f.Write(workBuffer, 0, workBufferSize);

        //advance in the source array
        offset += workBufferSize / elementSize;
    }
}

Console.WriteLine(sw.Elapsed);

旧解决方案,MMF

我认为您可以尝试使用MemoryMappedFile〜2至〜2.5分钟对于相对较慢的外部驱动器上的的3Gb阵列。

该解决方案意味着:

  1. 首先,创建一个空文件。
  2. 在其上创建一个内存映射文件,默认容量为X字节,其中X是数组长度(以字节为单位)。这会自动将磁盘上文件的物理长度设置为该值。
  3. 通过一个32kx8字节宽的访问器将数组转储到文件中(您可以更改它,这只是我测试过的东西)。因此,我正在以32k元素的块形式编写数组。

请注意,您需要考虑数组长度不是的倍数的情况chunkLength出于测试目的,在我的示例中为:)。

见下文:

//Just create an empty file
FileStream f = File.Create(@"D:\Test.bin");
f.Close();

long dataLen = 402653184; //3gb represented in 8 byte chunks
long[] data = new long[dataLen];
int elementSize = sizeof (long);

Stopwatch sw = Stopwatch.StartNew();

//Open the file, with a default capacity. This allows you to write over the initial capacity of the file
using (var mmf = MemoryMappedFile.CreateFromFile(@"D:\Test.bin", FileMode.Open, "longarray", data.LongLength * elementSize))
{
    long offset = 0;
    int chunkLength = 32768; 

    while (offset < dataLen)
    {
        using (var accessor = mmf.CreateViewAccessor(offset * elementSize, chunkLength * elementSize))
        {
            for (long i = offset; i != offset + chunkLength; ++i)
            {
                accessor.Write(i - offset, data[i]);
            }
        }

        offset += chunkLength;
    }
}

Console.WriteLine(sw.Elapsed);

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章