Tôi đang làm việc trên một chương trình truy cập ngẫu nhiên đọc/ghi nặng trên tệp lớn (cho đến 64 GB). Các tệp được cấu trúc cụ thể và để truy cập chúng, tôi đã tạo một khung công tác; sau một thời gian tôi đã cố gắng để kiểm tra hiệu suất trên nó và tôi đã nhận thấy rằng trên preallocated tập tin tuần tự viết hoạt động quá chậm để có thể chấp nhận được. Sau nhiều lần kiểm tra, tôi đã sao chép hành vi mà không có khung công tác của tôi (chỉ các phương thức FileStream); đây là phần mã (với phần cứng của tôi) sao chép vấn đề:Hành vi lạ với FileStream.WriteFile
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;
}
Thật không may vấn đề này dường như không thể đoán trước được, vì vậy đôi khi nó "hoạt động", đôi khi không. Tuy nhiên, sử dụng Process Monitor Tôi đã bắt gặp những sự kiện sau đây:
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
Đó là, sau hơn-viết gần 2 GB, FileStream.Write
bắt đầu gọi ReadFile
sau mỗi WriteFile
, và vấn đề này tiếp tục cho đến khi kết thúc quá trình; Ngoài ra, bù đắp mà tại đó vấn đề bắt đầu có vẻ là ngẫu nhiên. Tôi đã gỡ rối từng bước trong phương thức FileStream.Write
và tôi đã xác minh rằng thực tế là WriteFile
(Win32 API) mà, trong nội bộ, gọi ReadFile
.
Lưu ý cuối cùng; Tôi không nghĩ rằng đó là một vấn đề phân mảnh tập tin: Tôi đã chống phân mảnh các tập tin cá nhân với contig!
Cân nhắc nhớ chuyển [file ánh xạ] (http://msdn.microsoft.com/en-us/library/dd997372.aspx). – gor
Bạn có nghĩa là tôi nên tạo tài liệu tham khảo từ Win32 API hoặc sử dụng .NET4? Trong trường hợp đầu tiên, sẽ tốt hơn nếu bạn tạo toàn bộ khung trong C/C++ (và tôi thực sự xem xét khả năng này!); sau này tôi cũng nên nâng cấp lên VS2010 hoặc sử dụng SharpDevelop: Tôi thích sử dụng những gì tôi có! – Atropo
Nó có thể là một vấn đề đệm hệ điều hành, tôi không thể nhân rộng các lần đọc trên Win7 x64 và .Net 4.0. (Ngoài ra, hãy sử dụng các khối 'using', tôi không muốn khóc hôm nay) – user7116