c++ - mindmanager - .mmap viewer
Acelerando la E/S del archivo: mmap() vs. read() (3)
El problema aquí no parece ser qué api se usa. No importa si usa mmap () o read (), el disco aún tiene que buscar el punto especificado y leer los datos (aunque el sistema operativo ayuda a optimizar el acceso).
mmap () tiene ventajas sobre read () si lee fragmentos muy pequeños (un par de bytes) porque no tiene que llamar al sistema operativo para cada fragmento, que se vuelve muy lento.
También aconsejaría que Basile lo hiciera para leer más de 2kb consecutivos, por lo que el disco no tiene que buscarlo tan seguido.
Tengo una aplicación Linux que lee 150-200 archivos (4-10GB) en paralelo. Cada archivo se lee a su vez en bloques pequeños de tamaño variable, generalmente menos de 2K cada uno.
Actualmente necesito mantener una velocidad de lectura de más de 200 MB / s combinada del conjunto de archivos. Los discos manejan esto muy bien. Existe un requisito proyectado de más de 1 GB / s (que está fuera del alcance del disco en este momento).
Hemos implementado dos sistemas de lectura diferentes, ambos hacen un uso intensivo de posix_advise
: primero, es una lectura de mmap
ed en la cual posix_advise
la totalidad del conjunto de datos y leemos bajo demanda. El segundo es un sistema basado en read()
/ seek()
.
Ambos funcionan bien, pero solo para casos moderados, el método read()
administra mucho mejor nuestro caché de archivos en general y puede manejar cientos de GB de archivos, pero tiene una tasa muy limitada, mmap
puede almacenar datos previamente velocidad de datos de más de 200 MB / s fácil de mantener, pero no puede tratar con grandes tamaños de conjunto de datos.
Entonces mi pregunta viene a estos:
R: ¿Puede read()
archivo i / o se optimice más allá de las llamadas a posix_advise
en Linux, o que haya sintonizado el programador del disco, VMM y posix_advise calls es tan bueno como podemos esperar?
B: ¿Hay formas sistemáticas para que mmap trate mejor con datos mapeados muy grandes?
Mmap-vs-reading-blocks es un problema similar al que estoy trabajando y proporciona un buen punto de partida sobre este problema, junto con las discusiones en mmap-vs-read .
Lee de nuevo a qué? ¿Cuál es el destino final de esta información?
Como parece que estás completamente vinculado a IO, mmap
y read
deberían hacer ninguna diferencia. La parte interesante es cómo obtienes los datos en tu receptor.
Suponiendo que está poniendo esta información en una tubería, le recomiendo que simplemente descargue el contenido de cada archivo en su totalidad en la tubería. Para hacer esto usando copia cero, pruebe la llamada al sistema de splice
. También puede intentar copiar el archivo manualmente, o bifurcar una instancia de cat
o alguna otra herramienta que pueda almacenar en búfer con el archivo actual como stdin, y la tubería como stdout.
if (pid = fork()) {
waitpid(pid, ...);
} else {
dup2(dest, 1);
dup2(source, 0);
execlp("cat", "cat");
}
Update0
Si su procesamiento es independiente del archivo y no requiere acceso aleatorio, desea crear una interconexión utilizando las opciones descritas anteriormente. Su paso de procesamiento debe aceptar datos de stdin o un conducto.
Para responder a sus preguntas más específicas:
R: ¿Puede leer () que el archivo i / o se optimice más allá de las llamadas a posix_advise en Linux, o que haya sintonizado el programador del disco, VMM y posix_advise calls es tan bueno como podemos esperar?
Eso es lo mejor que se puede decir con respecto a decirle al kernel qué hacer desde el espacio de usuario. El resto depende de usted: almacenamiento en búfer, enhebrado, etc., pero es peligroso y probablemente improductivo. Yo solo iría empalmando los archivos en una tubería.
B: ¿Hay formas sistemáticas para que mmap trate mejor con datos mapeados muy grandes?
Sí. Las siguientes opciones pueden brindarle increíbles beneficios de rendimiento (y pueden hacer que mmap valga la pena usarlo sobre la lectura, con las pruebas):
MAP_HUGETLB
Asigne la asignación mediante "páginas grandes".Esto reducirá la sobrecarga de paginación en el núcleo, lo cual es excelente si va a mapear archivos de tamaño de gigabyte.
MAP_NORESERVE
No reserve espacio de intercambio para esta asignación. Cuando el espacio de intercambio está reservado, uno tiene la garantía de que es posible modificar el mapeo. Cuando el espacio de intercambio no está reservado, se puede obtener SIGSEGV al escribir si no hay memoria física disponible.Esto evitará que se quede sin memoria mientras mantiene su implementación simple si no tiene suficiente memoria física + intercambio para toda la asignación. **
MAP_POPULATE
tablas de páginas (predeterminadas) para una asignación. Para una asignación de archivos, esto provoca la lectura anticipada en el archivo. Los accesos posteriores a la asignación no serán bloqueados por fallas de página.Esto puede darle aceleraciones con suficientes recursos de hardware, y si la captación previa está ordenada y es floja. Sospecho que este indicador es redundante, el VFS probablemente lo haga mejor por defecto.
Quizás el uso de la readahead sistema readahead podría ayudar, si su programa puede predecir con antelación los fragmentos del archivo que quiere leer (pero esto es solo una suposición, podría estar equivocado).
Y creo que debería ajustar su aplicación, y tal vez incluso sus algoritmos, para leer datos en partes mucho mayores que unos pocos kilobytes. ¿No puede ser medio megabyte en su lugar?