我需要从3.7 GB文件中读取小数据序列。我需要阅读的位置不相邻,但我可以订购IO,以便从头到尾读取文件。
该文件存储在iSCSI SAN上,该SAN SAN应该能够处理/优化排队的IO。
问题是,如何一次性提出我需要的所有数据/位置的一次性请求?可能吗?我不认为异步IO是一个选项,因为读取非常小(20-200字节)
目前代码如下:
using (var fileStream = new FileStream(dataStorePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
for (int i = 0; i < internalIds.Count();i++ )
{
fileStream.Position = seekPositions[i].SeekPosition;
... = Serializer.DeserializeWithLengthPrefix<...>(fileStream, PrefixStyle.Base128);
}
...
}
我正在寻找改进此I / O的方法,因为我的读取性能有些低于标准。移动头部的所有寻道时间似乎都在增加。
答案 0 :(得分:1)
你有没有运行Performance Monitor(来自Microsoft Sysinternals)?
我不确定问题是什么,但我会猜一猜。如果您正在从SAN读取数据,我认为磁盘访问会导致网络请求。第一个读取发送寻找,读取和缓冲数据的请求,然后Serializer构造对象。当您的第二个请求被发送时,SAN磁盘继续旋转,因此您必须等待数据旋转到位。
你尝试过多线程吗?如果你设置一个你需要按顺序处理的文件部分队列,启动一些线程,让它们单独打开文件(FileSharing.Read,这样他们都可以一次访问文件),我对性能感到好奇然后让他们开始从队列中抓取工作。将结果输出到另一个集合中。如果订单对输出很重要,则按照排队对象的原始顺序对输出进行排序。
---编辑---
你试过ReadFileScatter API吗? Here's a P-invoke signature from pinvoke.net
答案 1 :(得分:0)
将单个后台线程设为磁盘代理。将所有读取操作发送给它,并对读取进行排序和合并。如果两个或多个区域接近,则读取包含它们的完整扇区并获取数据的子部分。异步返回数据。
答案 2 :(得分:0)
仅供记录:
在POSIX环境中,您可以使用readv函数请求一个(sys-)调用文件的多个区域。 POSIX环境中的另一个选择是非阻塞IO。