2010-12-06 7 views
5

Motivado por this answer Me preguntaba qué está pasando debajo de la cortina si uno usa lotes de FileStream.Seek(-1).FileStream.Seek vs. Buffered Reading

Para mayor claridad voy a volver a publicar la respuesta:

using (var fs = File.OpenRead(filePath)) 
{ 
    fs.Seek(0, SeekOrigin.End); 

    int newLines = 0; 
    while (newLines < 3) 
    { 
     fs.Seek(-1, SeekOrigin.Current); 
     newLines += fs.ReadByte() == 13 ? 1 : 0; // look for \r 
     fs.Seek(-1, SeekOrigin.Current); 
    } 

    byte[] data = new byte[fs.Length - fs.Position]; 
    fs.Read(data, 0, data.Length); 
} 

Personalmente hubiera leído como 2048 bytes en un búfer y buscado ese búfer para el carbón.

Usando el reflector descubrí que internamente el método está usando SetFilePointer.

¿Hay alguna documentación sobre el almacenamiento en caché de Windows y la lectura de un archivo al revés? ¿Windows amortigua "hacia atrás" y consulta el búfer cuando usa Seek(-1) consecutivamente o lo leerá adelante comenzando desde la posición actual?

Es interesante que, por un lado, la mayoría de la gente está de acuerdo con que Windows tiene un buen almacenamiento en caché, pero por otro lado, cada respuesta al "archivo de lectura hacia atrás" implica leer fragmentos de bytes y operar en ese fragmento.

+1

Haciendo una revisión por pares seria ¿eh? – ChaosPandion

+0

@ ChaosPandion: No califiqué tu comentario, solo tenía curiosidad. – VVS

Respuesta

6

Adelante hacia atrás no suele hacer mucha diferencia. Los datos del archivo se leen en la memoria caché del sistema de archivos después de la primera lectura, se obtiene una copia de memoria a memoria en ReadByte(). Esa copia no es sensible al valor del puntero del archivo, siempre y cuando los datos estén en la caché. Sin embargo, el algoritmo de almacenamiento en caché funciona desde la suposición de que normalmente leería secuencialmente. Intenta leer adelante, siempre y cuando los sectores de archivos sigan en la misma pista. Usualmente lo son, a menos que el disco esté muy fragmentado.

Pero sí, es ineficiente. Recibirás dos llamadas pinvoke y API para cada byte individual. Hay una gran cantidad de gastos generales en eso, esas mismas dos llamadas también podrían leer, digamos, 65 kilobytes con la misma cantidad de gastos generales. Como de costumbre, corrige esto solo cuando lo encuentres como un cuello de botella perf.

+0

Ah, no tomó en cuenta el costo de p/invocación. Eso ya es motivo suficiente para leer en trozos. – VVS

1

Aquí es un puntero en File Caching in Windows

El comportamiento puede también depende de donde reside físicamente el archivo (disco duro, red, etc.), así como la configuración local/optimización.

An también importante fuente de información es la documentación de la API CreateFile: CreateFile Function

Hay una buena sección denominada "comportamiento de caché" que nos dice al menos cómo puede influir en el almacenamiento en caché de archivos, por lo menos en el mundo no administrado.

Cuestiones relacionadas