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

Is there a faster way to read data with a FileStream?

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

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 itteration: {times.Max()}ms");

它设法在 < 3 毫秒内读取和处理大约 9000 个字节。 这个想法是检查每个字节以查看它是 1 还是 0(真或假)并将其存储在数组中。

所以我的问题是,有没有更快的方法来实现这个目标?尝试快速处理数据时要记住哪些事项,是否要确保您使用的是较小的数据类型,以免分配不必要的内存?

数据是什么样的。

https://hatebin.com/dcldbvrbdm

好吧,我们正在使用缓冲 IO,因此按字节迭代并不 不好。 但是,一次(如果可以的话)将数据读入缓冲区总是更快——一次 IO。 所以在下面我使用了你的代码 - 必须在循环中添加一个 seek(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% 左右。