2

我需要从 3.7 GB 文件中读取小数据序列。我需要读取的位置不是相邻的,但我可以订购 IO 以便从头到尾读取文件。

该文件存储在 iSCSI 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 的方法,因为我的读取性能有些低于标准。移动头部的所有寻道时间似乎都在增加。

4

3 回答 3

1

您是否对此运行过性能监视器(来自 Microsoft Sysinternals)?

我不确定问题是什么,但我会猜测一下。如果您正在从 SAN 读取数据,我认为磁盘访问会在后台导致网络请求。第一次读取发送请求以查找、读取和缓冲数据,然后由 Serializer 构造对象。当您的第二个请求被发送时,SAN 磁盘继续旋转,因此您必须等待数据旋转到位。

你试过多线程吗?如果您设置一个需要按顺序处理的文件部分队列,启动一些线程,让它们分别打开文件(FileSharing.Read,以便他们都可以同时访问文件)和然后让他们开始从队列中获取工作。将结果输出到另一个集合中。如果顺序对输出很重要,您可以按照将它们排入队列的原始顺序对输出进行排序。

- - 编辑 - -

您是否尝试过ReadFileScatter API这是来自 pinvoke.net 的 P-invoke 签名

于 2009-08-21T02:54:44.670 回答
0

单个后台线程作为磁盘代理。将所有读取操作发送给它,并让它对读取进行排序和合并。如果两个或更多区域靠近,则读取包含它们的整个扇区并获取数据的子部分。异步返回数据。

于 2009-08-20T23:08:58.053 回答
0

仅作记录:

在 POSIX 环境中,您可以使用readv函数通过一次 (sys-) 调用请求文件的多个区域。POSIX 环境中的另一个选项是非阻塞 IO。

于 2009-09-03T06:31:31.343 回答