FileStream.WriteFile的奇怪行为

时间:2011-02-02 13:36:35

标签: c# file-io filestream

我正在研究一个在大文件上进行大量读/写随机访问的程序(直到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;
}

不幸的是,这个问题似乎是不可预测的,所以有时候它“有效”,有时则不然。 但是,使用Process Monitor我发现了以下事件:

Operation   Result  Detail
WriteFile   SUCCESS Offset: 1.905.655.816, Length: 262.144
WriteFile   SUCCESS Offset: 1.905.917.960, Length: 262.144
WriteFile   SUCCESS Offset: 1.906.180.104, Length: 262.144
WriteFile   SUCCESS Offset: 1.906.442.248, Length: 262.144
WriteFile   SUCCESS Offset: 1.906.704.392, Length: 262.144
WriteFile   SUCCESS Offset: 1.906.966.536, Length: 262.144
ReadFile    SUCCESS Offset: 1.907.228.672, Length: 32.768, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
WriteFile   SUCCESS Offset: 1.907.228.680, Length: 262.144
ReadFile    SUCCESS Offset: 1.907.355.648, Length: 32.768, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
ReadFile    SUCCESS Offset: 1.907.490.816, Length: 32.768, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
WriteFile   SUCCESS Offset: 1.907.490.824, Length: 262.144
ReadFile    SUCCESS Offset: 1.907.617.792, Length: 32.768, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
ReadFile    SUCCESS Offset: 1.907.752.960, Length: 32.768, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
WriteFile   SUCCESS Offset: 1.907.752.968, Length: 262.144

也就是说,在覆盖了大约2 GB之后,FileStream.Write在每ReadFile之后开始调用WriteFile,此问题一直持续到流程结束;此外,问题开始的偏差似乎是随机的。 我已在FileStream.Write方法中逐步调试,并且我已经验证实际上是WriteFile(Win32 API),在内部调用ReadFile

最后注意;我不认为这是一个文件碎片问题:我已经用contig对我的文件进行了碎片整理!

2 个答案:

答案 0 :(得分:1)

我认为这与FileStream.Write / Read和2GB限制有关。你是在32位进程中运行它吗?我找不到任何具体的文档,但这里有一个MSDN forum问题听起来是一样的。您可以尝试在64位进程中运行它。

我同意使用内存映射文件可能是更好的方法。

答案 1 :(得分:1)

我是从MSDN找到的。它有关系吗?听起来我每个文件都有一个全局共享指针。

当FileStream对象的句柄没有独占保持时,另一个线程可以同时访问文件句柄并更改与文件句柄关联的操作系统文件指针的位置。在这种情况下,FileStream对象中的缓存位置和缓冲区中的缓存数据可能会受到影响。 FileStream对象通常对访问缓存缓冲区的方法执行检查,以确保操作系统的句柄位置与FileStream对象使用的缓存位置相同。

http://msdn.microsoft.com/en-us/library/system.io.filestream.aspx