Я работаю над программой, которая делает тяжелый произвольный доступ для чтения / записи для огромного файла (до 64 ГБ). Файлы специально структурированы, и для доступа к ним я создал фреймворк; Через некоторое время я попытался проверить производительность на нем и заметил, что в предварительно выделенных файлах операции последовательной записи выполняются слишком медленно, чтобы быть приемлемыми.
После многих тестов я повторил поведение без моей структуры (только методы 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 ГБ, FileStream.Write
начинает вызывать ReadFile
после каждого WriteFile
, и эта проблема продолжается до конца процесса; Кроме того, смещение, с которого начинается проблема, кажется случайным.
Я шаг за шагом отлаживал метод FileStream.Write
и убедился, что на самом деле это WriteFile
(Win32 API), который внутренне вызывает ReadFile
.
Последняя заметка; Я не думаю, что это проблема фрагментации файла: я лично дефрагментировал файл с помощью contig!