更好/更快的方式填补一个大数组在C#

前端之家收集整理的这篇文章主要介绍了更好/更快的方式填补一个大数组在C#前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有3 * .dat文件(346KB,725KB,1762KB),填充有一个“大”int数组的json字符串.

每次我的对象被创建(几次),我拿这三个文件,并使用JsonConvert.DeserializeObject来反序列化数组到对象.

我想到使用二进制文件而不是json-string,甚至可以直接保存这些数组?我不需要使用这些文件,它只是数据当前保存的位置.我会乐意切换到更快的东西.

加速这些对象的初始化有什么不同的方法

解决方法

最快的方法是手动序列化数据.

一个简单的方法是创建一个FileStream,然后将其包装在一个二进制文件/二进制阅读器中.

您可以访问函数来编写基本数据结构(数字,字符串,字符,字节[]和字符[]).

一个简单的方法来编写一个int [](如果它是固定的大小),这是通过使用int / long的前缀长度来取代数组(取决于大小,unsigned并不能给出任何优势,因为数组使用带符号的数据类型长度存储).然后写所有的ints.

写入所有内容的两种方式是:
简单地循环整个阵列.
2.将其转换为字节[],并使用BinaryWriter.Write(byte [])写入

这些是如何实现它们:

// Writing
BinaryWriter writer = new BinaryWriter(new FileStream(...));
int[] intArr = new int[1000];

writer.Write(intArr.Length);
for (int i = 0; i < intArr.Length; i++)
    writer.Write(intArr[i]);

// Reading
BinaryReader reader = new BinaryReader(new FileStream(...));
int[] intArr = new int[reader.ReadInt32()];

for (int i = 0; i < intArr.Length; i++)
    intArr[i] = reader.ReadInt32();

// Writing,method 2
BinaryWriter writer = new BinaryWriter(new FileStream(...));
int[] intArr = new int[1000];
byte[] byteArr = new byte[intArr.Length * sizeof(int)];
Buffer.BlockCopy(intArr,byteArr,intArr.Length * sizeof(int));

writer.Write(intArr.Length);
writer.Write(byteArr);

// Reading,method 2
BinaryReader reader = new BinaryReader(new FileStream(...));
int[] intArr = new int[reader.ReadInt32()];
byte[] byteArr = reader.ReadBytes(intArr.Length * sizeof(int));
Buffer.BlockCopy(byteArr,intArr,byteArr.Length);

我决定把这全部放在测试中,用10000个整数的数组,我经过10000次测试.

这导致方法在我的系统上平均消耗888200ns(约0.89ms).
虽然方法2仅在我的系统上平均消耗了568600ns(平均为0.57ms).

这两次都包括垃圾收集器所要做的工作.

显然方法2比方法1更快,尽管可读性更差.

方法1可以比方法2更好的另一个原因是因为方法2需要比您要编写的数据(原始int []和从[int]]转换的字节[]的两倍)当处理有限的RAM /超大文件(大约512MB)时,尽管如此,您可以随时制作混合解决方案,例如一次写入128MB.

请注意,方法1还需要这个额外的空间,但是因为它在int []的每个项目中被分解为1个操作,所以它可以更早地释放内存.

这样的东西,一次会写128MB的int []:

const int WRITECOUNT = 32 * 1024 * 1024; // 32 * sizeof(int)MB

int[] intArr = new int[140 * 1024 * 1024]; // 140 * sizeof(int)MB
for (int i = 0; i < intArr.Length; i++)
    intArr[i] = i;

byte[] byteArr = new byte[WRITECOUNT * sizeof(int)]; // 128MB

int dataDone = 0;

using (Stream fileStream = new FileStream("data.dat",FileMode.Create))
using (BinaryWriter writer = new BinaryWriter(fileStream))
{
    while (dataDone < intArr.Length)
    {
        int dataToWrite = intArr.Length - dataDone;
        if (dataToWrite > WRITECOUNT) dataToWrite = WRITECOUNT;
        Buffer.BlockCopy(intArr,dataDone,dataToWrite * sizeof(int));
        writer.Write(byteArr);
        dataDone += dataToWrite;
    }
}

请注意,这只是为了写作,阅读工作也不同:P.我希望这能给你一些处理非常大的数据文件的洞察力:).

猜你在找的C#相关文章