.NET 4.5 文件读取性能同步与异步 [英] .NET 4.5 file read performance sync vs async

查看:20
本文介绍了.NET 4.5 文件读取性能同步与异步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在尝试衡量使用同步方法与异步方法读取一系列文件之间的性能.原以为两者的时间差不多,但结果证明使用 async 会慢 5.5 倍.

We're trying to measure the performance between reading a series of files using sync methods vs async. Was expecting to have about the same time between the two but turns out using async is about 5.5x slower.

这可能是由于管理线程的开销,但只是想知道您的意见.也许我们只是测量了错误的时间.

This might be due to the overhead of managing the threads but just wanted to know your opinion. Maybe we're just measuring the timings wrong.

这些是正在测试的方法:

These are the methods being tested:

    static void ReadAllFile(string filename)
    {
        var content = File.ReadAllBytes(filename);
    }

    static async Task ReadAllFileAsync(string filename)
    {
        using (var file = File.OpenRead(filename))
        {
            using (var ms = new MemoryStream())
            {
                byte[] buff = new byte[file.Length];
                await file.ReadAsync(buff, 0, (int)file.Length);
            }
        }
    }

这是运行它们并启动秒表的方法:

And this is the method that runs them and starts the stopwatch:

    static void Test(string name, Func<string, Task> gettask, int count)
    {
        Stopwatch sw = new Stopwatch();

        Task[] tasks = new Task[count];
        sw.Start();
        for (int i = 0; i < count; i++)
        {
            string filename = "file" + i + ".bin";
            tasks[i] = gettask(filename);
        }
        Task.WaitAll(tasks);
        sw.Stop();
        Console.WriteLine(name + " {0} ms", sw.ElapsedMilliseconds);

    }

从这里开始:

    static void Main(string[] args)
    {
        int count = 10000;

        for (int i = 0; i < count; i++)
        {
            Write("file" + i + ".bin");
        }

        Console.WriteLine("Testing read...!");            

        Test("Read Contents", (filename) => Task.Run(() => ReadAllFile(filename)), count);
        Test("Read Contents Async", (filename) => ReadAllFileAsync(filename), count);

        Console.ReadKey();
    }

以及辅助写方法:

    static void Write(string filename)
    {
        Data obj = new Data()
        {
            Header = "random string size here"
        };
        int size = 1024 * 20; // 1024 * 256;

        obj.Body = new byte[size];

        for (var i = 0; i < size; i++)
        {
            obj.Body[i] = (byte)(i % 256);
        }

        Stopwatch sw = new Stopwatch();
        sw.Start();

        MemoryStream ms = new MemoryStream();
        Serializer.Serialize(ms, obj);
        ms.Position = 0;

        using (var file = File.Create(filename))
        {
            ms.CopyToAsync(file).Wait();
        }

        sw.Stop();
        //Console.WriteLine("Writing file {0}", sw.ElapsedMilliseconds); 
    }

结果:

-Read Contents 574 ms
-Read Contents Async 3160 ms

如果有人能在我们搜索堆栈和网络但找不到正确解释时对此有所了解,我们将不胜感激.

Will really appreciate if anyone can shed some light on this as we searched the stack and the web but can't really find a proper explanation.

推荐答案

测试代码有很多问题.最值得注意的是,您的异步"测试不使用异步 I/O;对于文件流,您必须以异步方式显式打开它们,否则您只是在后台线程上执行同步操作.此外,您的文件非常小,可以轻松缓存.

There are lots of things wrong with the testing code. Most notably, your "async" test does not use async I/O; with file streams, you have to explicitly open them as asynchronous or else you're just doing synchronous operations on a background thread. Also, your file sizes are very small and can be easily cached.

我修改了测试代码以写出更大的文件,具有可比较的同步代码与异步代码,并使异步代码异步:

I modified the test code to write out much larger files, to have comparable sync vs async code, and to make the async code asynchronous:

static void Main(string[] args)
{
    Write("0.bin");
    Write("1.bin");
    Write("2.bin");

    ReadAllFile("2.bin"); // warmup

    var sw = new Stopwatch();
    sw.Start();
    ReadAllFile("0.bin");
    ReadAllFile("1.bin");
    ReadAllFile("2.bin");
    sw.Stop();

    Console.WriteLine("Sync: " + sw.Elapsed);

    ReadAllFileAsync("2.bin").Wait(); // warmup

    sw.Restart();
    ReadAllFileAsync("0.bin").Wait();
    ReadAllFileAsync("1.bin").Wait();
    ReadAllFileAsync("2.bin").Wait();
    sw.Stop();

    Console.WriteLine("Async: " + sw.Elapsed);

    Console.ReadKey();
}

static void ReadAllFile(string filename)
{
    using (var file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false))
    {
        byte[] buff = new byte[file.Length];
        file.Read(buff, 0, (int)file.Length);
    }
}

static async Task ReadAllFileAsync(string filename)
{
    using (var file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))
    {
        byte[] buff = new byte[file.Length];
        await file.ReadAsync(buff, 0, (int)file.Length);
    }
}

static void Write(string filename)
{
    int size = 1024 * 1024 * 256;
    var data = new byte[size];
    var random = new Random();
    random.NextBytes(data);
    File.WriteAllBytes(filename, data);
}

在我的机器上,这个测试(内置于 Release,在调试器外运行)产生以下数字:

On my machine, this test (built in Release, run outside the debugger) yields these numbers:

Sync: 00:00:00.4461936
Async: 00:00:00.4429566

这篇关于.NET 4.5 文件读取性能同步与异步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆