【发布时间】:2013-08-20 09:18:26
【问题描述】:
我们正在尝试衡量使用同步方法与异步读取一系列文件之间的性能。预计两者之间的时间大致相同,但结果使用异步速度慢了大约 5.5 倍。
这可能是由于管理线程的开销,但只是想知道您的意见。也许我们只是测量了错误的时间。
这些是正在测试的方法:
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);
}
}
}
这是运行它们并启动秒表的方法:
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
如果有人能在我们搜索堆栈和网络但无法真正找到正确解释时对此有所了解,我们将不胜感激。
【问题讨论】:
-
您的测试可能存在缺陷,因为您正在生成线程以同时进行读取。更好的测试是先测试一个东西,然后再测试另一个。
-
另一方面,Stopwatch 上有一个漂亮的静态方法称为
StartNew,它基本上是var s = new Stopwatch(); s.Start(); return s;,所以你不必这样做。 :-) -
我认为这个测试有缺陷。您是否测量了 ReadAllBytes 和 Read 之间的差异?这可能是第一件事,ReadAllBytes 更有效 - 也许它是一个“原子”操作?
-
你是否在发布模式下测试这个,没有附加调试器?对调试构建进行计时,或在附加调试器的情况下计时将产生不可靠的结果。请务必在 Release 模式下编译并使用 Ctrl+F5 运行(无需调试即可运行)。
-
为什么会有这行:
using (var ms = new MemoryStream())?您似乎没有在任何地方使用ms。
标签: c# file asynchronous .net-4.5