我正在开发一个程序,对巨大文件(最高达64 GB)进行大量随机读写操作。这些文件是特定结构的,为了访问它们,我创建了一个框架;一段时间后,我试图测试其性能,发现在预分配的文件上,顺序写入操作太慢而无法接受。 经过多次测试,我没有使用我的框架(仅使用FileStream方法)复制了该行为;以下是代码部分(使用我的硬件)可复制该问题:
FileStream fs = new FileStream("test1.vhd", FileMode.Open);
byte[] buffer = new byte[256 * 1024];
Random rand = new Random();
rand.NextBytes(buffer);
DateTime start, end;
double ellapsed = 0.0;
long startPos, endPos;
BinaryReader br = new BinaryReader(fs);
br.ReadUInt32();
br.ReadUInt32();
for (int i = 0; i < 65536; i++)
br.ReadUInt16();
br = null;
startPos = 0; // 0
endPos = 4294967296; // 4GB
for (long index = startPos; index < endPos; index += buffer.Length)
{
start = DateTime.Now;
fs.Write(buffer, 0, buffer.Length);
end = DateTime.Now;
ellapsed += (end - start).TotalMilliseconds;
}
很不幸,这个问题似乎是不可预测的,所以有时它“工作”,有时则不然。但是,使用进程监视器,我捕获了以下事件:
操作 结果 详细信息 WriteFile 成功 偏移量:1.905.655.816,长度:262.144 WriteFile 成功 偏移量:1.905.917.960,长度:262.144 WriteFile 成功 偏移量:1.906.180.104,长度:262.144 WriteFile 成功 偏移量:1.906.442.248,长度:262.144 WriteFile 成功 偏移量:1.906.704.392,长度:262.144 WriteFile 成功 偏移量:1.906.966.536,长度:262.144 ReadFile 成功 偏移量:1.907.228.672,长度:32.768,I/O标志:非缓存,分页I/O,同步分页I/O,优先级:普通 WriteFile 成功 偏移量:1.907.228.680,长度:262.144 ReadFile 成功 偏移量:1.907.355.648,长度:32.768,I/O标志:非缓存,分页I/O,同步分页I/O,优先级:普通 ReadFile 成功 偏移量:1.907.490.816,长度:32.768,I/O标志:非缓存,分页I/O,同步分页I/O,优先级:普通 WriteFile 成功 偏移量:1.907.490.824,长度:262.144 ReadFile 成功 偏移量:1.907.617.792,长度:32.768,I/O标志:非缓存,分页I/O,同步分页I/O,优先级:普通 ReadFile 成功 偏移量:1.907.752.960,长度:32.768,I/O标志:非缓存,分页I/O,同步分页I/O,优先级:普通 WriteFile 成功 偏移量:1.907.752.968,长度:262.144
也就是说,在覆盖了将近2GB后,FileStream.Write开始在每次WriteFile之后调用ReadFile,并且这个问题会持续到进程结束;此外,问题开始的偏移量似乎是随机的。我已经逐步调试了FileStream.Write方法,并验证了实际上是WriteFile(Win32 API)在内部调用了ReadFile。
最后注意一点:我不认为这是文件碎片问题:我已经使用contig自己对文件进行了碎片整理!