Escuché (lo leí en Internet en alguna parte) que mmap() es más rápido que IO secuencial. ¿Es esto correcto? Si es así, ¿por qué es más rápido?
Puede ser, hay pros y contras, que se enumeran a continuación. Cuando realmente tenga motivos para preocuparse, siempre compare ambos .
Aparte de la eficiencia real de E/S, hay implicaciones en la forma en que el código de la aplicación realiza un seguimiento de cuándo necesita realizar la E/S y realiza el procesamiento/generación de datos, que a veces puede afectar el rendimiento de manera bastante drástica.
- mmap() no lee secuencialmente.2) mmap() tiene que buscar desde el disco mismo como lo hace read()3) El área mapeada no es secuencial, por lo que no hay DMA (?).
¿Entonces mmap() debería ser más lento que read() de un archivo? ¿Cuáles de mis suposiciones anteriores son incorrectas?
-
está mal...
mmap()
asigna una región de espacio de direcciones virtuales correspondiente al contenido del archivo... cada vez que se accede a una página en ese espacio de direcciones, se encuentra RAM física para respaldar las direcciones virtuales y el contenido del disco correspondiente falla en esa RAM. Por lo tanto, el orden en que se realizan las lecturas desde el disco coincide con el orden de acceso. Es un mecanismo de E/S "perezoso". Si, por ejemplo, necesita indexar una tabla hash enorme que se va a leer desde el disco, entoncesmmap
abrir el archivo y comenzar a acceder significa que la E/S del disco no se realiza secuencialmente y, por lo tanto, puede resultar en un tiempo transcurrido más largo hasta que el archivo completo se lee en la memoria, pero mientras eso sucede, las búsquedas se realizan correctamente y se puede realizar un trabajo dependiente, y si nunca se necesitan partes del archivo, no se leen (tenga en cuenta la granularidad de las páginas del disco y de la memoria, y que incluso cuando se usa el mapeo de memoria, muchos sistemas operativos le permiten especificar algunos consejos para mejorar el rendimiento/eficiencia de la memoria sobre su planificación). acceder a patrones para que puedan leer de forma proactiva o liberar memoria de forma más agresiva sabiendo que es poco probable que vuelvas a ella). -
absolutamente cierto
-
"El área mapeada no es secuencial" es vago. Las regiones mapeadas en memoria son "contiguas" (secuenciales) en el espacio de direcciones virtuales. Hemos discutido que la E/S del disco es secuencial arriba. ¿O estás pensando en otra cosa? De todos modos, mientras las páginas están fallando, es posible que se transfieran usando DMA.
Además, hay otras razones por las que la asignación de memoria puede superar la E/S habitual:
- hay menos copias:
- a menudo, las rutinas de nivel de biblioteca y sistema operativo pasan datos a través de uno o más búferes antes de que lleguen a un búfer especificado por la aplicación, la aplicación luego asigna almacenamiento dinámicamente, luego copia del búfer de E/S a ese almacenamiento para que los datos se puedan usar después del archivo lectura completa
- la asignación de memoria permite (pero no fuerza) el uso en el lugar (solo puede registrar un puntero y posiblemente la longitud)
- continuar accediendo a los datos en el lugar corre el riesgo de aumentar las fallas de caché y/o el intercambio posterior:el archivo/mapa de memoria podría ser más detallado que las estructuras de datos en las que podría analizarse, por lo que los patrones de acceso a los datos podrían tener más demoras fallar en más páginas de memoria
- la asignación de memoria puede simplificar el trabajo de análisis de la aplicación al permitir que la aplicación trate todo el contenido del archivo como accesible, en lugar de preocuparse por cuándo leer otro búfer lleno
- la aplicación se remite más a la sabiduría del sistema operativo en cuanto a la cantidad de páginas que se encuentran en la memoria RAM física en cualquier momento, compartiendo efectivamente un caché de disco de acceso directo con la aplicación
- como los comentarios de los simpatizantes a continuación, "usando el mapeo de memoria, normalmente usa menos llamadas al sistema"
- si varios procesos acceden al mismo archivo, deberían poder compartir las páginas de respaldo físicas
También hay razones por las que mmap
puede ser más lento:lea la publicación de Linus Torvald aquí que dice de mmap
:
...juegos de mesa de página junto con la falla (e incluso la falla de TLB) la sobrecarga es fácilmente más que el costo de copiar una página de una manera agradable...
Y de otra de sus publicaciones:
- Costos de instalación y desmontaje bastante notables. Y me refiero a notable . Son cosas como seguir las tablas de la página para desasignar todo limpiamente. Es la contabilidad para mantener una lista de todas las asignaciones. Es el lavado de TLB necesario después de desmapear cosas.
- La falla de página es costosa. Así es como se completa el mapeo, y es bastante lento.
Linux tiene "páginas enormes" (una entrada TLB por 2 MB, en lugar de por 4 kb) e incluso páginas enormes transparentes, donde el sistema operativo intenta usarlas incluso si el código de la aplicación no se escribió para utilizarlas explícitamente.
FWIW, la última vez que me surgió esto en el trabajo, la entrada asignada a la memoria fue un 80 % más rápida que fread
et al para leer registros de bases de datos binarias en una base de datos propietaria, en Linux de 64 bits con archivos de ~170 GB.
mmap()
puede compartir entre procesos.- Se utilizará DMA siempre que sea posible. DMA no requiere memoria contigua:muchas tarjetas de gama alta admiten DMA de dispersión y recopilación.
- El área de la memoria se puede compartir con la memoria caché de bloques del kernel si es posible. Así que hay una copia del arrendador.
- Memoria para
mmap
está asignado por kernel, siempre está alineado.