有没有更快的方法使用FileStream读取数据?

问题描述 投票:0回答:1

我正在尝试尽可能快地读取数据并将其存储在数组中,我发现这样做的最快方法就是这个。

var filePath = "data.dat";
FileStream fs = new FileStream(filePath, FileMode.Open);
bool[] buffer = new bool[fs.Length];

TimeSpan[] times = new TimeSpan[500000];
Stopwatch sw = new Stopwatch();

for (int r = 0; r < 500000; r++)
{
    sw.Start();

    int stackable = 0;
    int counter = 0;

    while ((stackable = fs.ReadByte()) != -1)
    {
        buffer[counter] = (stackable == 1);
        counter++;
    }

    sw.Stop();
    Console.WriteLine($"Elapsed: {sw.Elapsed}ms");
    times[r] = sw.Elapsed;
    sw.Reset();
}

Console.WriteLine($"Longest iteration: {times.Max()}ms");

它成功地读取并处理了 < 3ms. The idea is to check each byte to see if it's either 1 or 0 (true or false) and store that in an array.

中的大约 9000 个字节

所以我的问题是,有没有更快的方法来实现这一目标?在尝试快速处理数据时需要记住哪些事情,是为了确保您使用较小的数据类型,这样就不会分配不必要的内存?

数据是什么样的:

https://hatebin.com/dcldbvrbdm

c# arrays boolean filestream microbenchmark
1个回答
1
投票

嗯,我们正在使用缓冲 IO,因此按字节迭代并不是那么糟糕。 但是,将数据读入缓冲区一次(如果可以的话)总是更快 - 一次 IO。 所以下面我使用了你的代码 - 必须在循环中添加一个eek(0)来重置迭代。 在下一个块中,我读取所有数据并使用新的 .AsSpan<>() 进行迭代 - 这是迭代数组的新快速方法。

using System; using System.Diagnostics; using System.IO; namespace test_con { class Program { static void Main(string[] args) { makedata(); var filePath = "data.dat"; var loop_cnt = 5000; using FileStream fs = new FileStream(filePath, FileMode.Open); bool[] buffer = new bool[fs.Length]; Stopwatch sw = new Stopwatch(); sw.Start(); for (int r = 0; r < loop_cnt; r++) { int stackable = 0; int counter = 0; while ((stackable = fs.ReadByte()) != -1) { buffer[counter] = (stackable == 1); counter++; } fs.Seek(0, SeekOrigin.Begin); } Console.WriteLine($"avg iteration: {sw.Elapsed.TotalMilliseconds/loop_cnt}"); var byte_buf = new byte[fs.Length]; sw.Restart(); for (int r = 0; r < loop_cnt; r++) { fs.Seek(0, SeekOrigin.Begin); fs.Read(byte_buf); int counter = 0; foreach(var b in byte_buf.AsSpan()) { buffer[counter] = (b == 1); counter++; } } Console.WriteLine($"buf avg iteration: {sw.Elapsed.TotalMilliseconds / loop_cnt}"); } static void makedata() { var filePath = "data.dat"; if (!File.Exists(filePath)) { Random rnd = new Random(); using FileStream fs = new FileStream(filePath, FileMode.CreateNew); for (int n = 0; n < 100000; n++) { if (rnd.Next() % 1 == 1) fs.WriteByte(0); else fs.WriteByte(1); } } } } }

我的 2012 MacBook 上的输出是:

avg iteration: 1.01832286 buf avg iteration: 0.6913623999999999

因此缓冲区迭代仅占流迭代的 70% 左右。

© www.soinside.com 2019 - 2024. All rights reserved.