Estoy trabajando en un programa que realiza un acceso aleatorio pesado de lectura/escritura en un archivo enorme (hasta 64 GB). Los archivos están estructurados específicamente y para hacer que accedan a ellos. He creado un marco; después de un rato intenté probar el rendimiento en él y me di cuenta de que en el archivo preasignado las operaciones de escritura secuencial son demasiado lentas para ser aceptables. Después de muchas pruebas repliqué el comportamiento sin mi framework (solo métodos FileStream); aquí está la parte del código que (con mi hardware) replica el tema:Comportamiento extraño con 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;
}
Por desgracia, la cuestión parece ser impredecible, así que a veces "obras", a veces no lo hace. Sin embargo, utilizando el monitor de procesos que he cogido los siguientes eventos:
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
Eso es, después de sobre-escritura casi 2 GB, FileStream.Write
aperturas para llamar ReadFile
después de cada WriteFile
, y este tema continuará hasta el final de la proceso; Además, el desplazamiento en el que comienza el problema parece ser aleatorio. He depurado paso a paso dentro del método FileStream.Write
y he verificado que en realidad es el WriteFile
(API de Win32) que, internamente, llama al ReadFile
.
Última nota; No creo que sea un problema de fragmentación de archivos: ¡he desfragmentado el archivo personalmente con contig!
Considerar la memoria de conmutación [archivos mapeados] (http://msdn.microsoft.com/en-us/library/dd997372.aspx). – gor
¿Quiere decir que debería crear referencias desde Win32 API o utilizar .NET4? En el primer caso, será mejor crear todo el framework en C/C++ (¡y realmente estoy considerando esta posibilidad!); en este último también debería actualizar a VS2010 o usar SharpDevelop: ¡prefiero usar lo que tengo! – Atropo
Podría ser un problema de almacenamiento en el sistema operativo, no puedo replicar las lecturas en Win7 x64 y .Net 4.0. (Además, utilice bloques 'using', no quiero llorar hoy) – user7116