Creo que la ventaja es realmente que reduce la cantidad de copia de datos requerida sobre los métodos tradicionales de lectura de un archivo.
Si su aplicación puede usar los datos "en su lugar" en un archivo mapeado en memoria, puede ingresar sin ser copiado; si usa una llamada al sistema (por ejemplo, pread () de Linux), entonces normalmente implica que el núcleo copie los datos de sus propios búferes en el espacio de usuario. Esta copia adicional no solo lleva tiempo, sino que disminuye la efectividad de las cachés de la CPU al acceder a esta copia adicional de los datos.
Si los datos realmente tienen que leerse desde el disco (como en E / S físicas), entonces el sistema operativo aún tiene que leerlos, una falla de página probablemente no sea mejor en cuanto a rendimiento que una llamada al sistema, pero si no lo haga (es decir, ya está en la caché del sistema operativo), el rendimiento debería, en teoría, ser mucho mejor.
En el lado negativo, no hay una interfaz asincrónica para los archivos asignados en memoria: si intenta acceder a una página que no está asignada, genera una falla de página y luego hace que el hilo espere la E / S.
La desventaja obvia de los archivos asignados en memoria está en un sistema operativo de 32 bits: puede quedarse sin espacio de direcciones fácilmente.
He utilizado un archivo mapeado en memoria para implementar una función de 'autocompletar' mientras el usuario está escribiendo. Tengo más de 1 millón de números de pieza de productos almacenados en un solo archivo de índice. El archivo tiene información de encabezado típica, pero la mayor parte del archivo es una matriz gigante de registros de tamaño fijo ordenados en el campo clave.
En tiempo de ejecución, el archivo se asigna en memoria, se convierte en una matriz de
C
estilostruct
y hacemos una búsqueda binaria para encontrar números de pieza coincidentes a medida que el usuario escribe. Solo unas pocas páginas de memoria del archivo se leen realmente desde el disco, las páginas que se acceden durante la búsqueda binaria.fuente
Los archivos asignados en memoria se pueden usar para reemplazar el acceso de lectura / escritura o para admitir el uso compartido simultáneo. Cuando los usa para un mecanismo, obtiene el otro también.
En lugar de buscar, escribir y leer en un archivo, lo asigna a la memoria y simplemente accede a los bits donde espera que estén.
Esto puede ser muy útil y, dependiendo de la interfaz de memoria virtual, puede mejorar el rendimiento. La mejora del rendimiento puede ocurrir porque el sistema operativo ahora puede administrar esta "E / S de archivo" anterior junto con todos sus otros accesos de memoria programáticos, y puede (en teoría) aprovechar los algoritmos de paginación y demás que ya está usando para admitir memoria virtual para el resto de su programa. Sin embargo, depende de la calidad de su sistema de memoria virtual subyacente. Anécdotas He escuchado decir que los sistemas de memoria virtual Solaris y * BSD pueden mostrar mejores mejoras de rendimiento que el sistema VM de Linux, pero no tengo datos empíricos para respaldar esto. YMMV.
La simultaneidad entra en escena cuando se considera la posibilidad de que múltiples procesos utilicen el mismo "archivo" a través de la memoria asignada. En el modelo de lectura / escritura, si dos procesos escribieron en la misma área del archivo, podría estar bastante seguro de que uno de los datos del proceso llegaría al archivo, sobrescribiendo los datos del otro proceso. Obtendría uno u otro, pero no una mezcla extraña. Debo admitir que no estoy seguro de si este es un comportamiento exigido por algún estándar, pero es algo en lo que puede confiar. (¡En realidad es una buena pregunta de seguimiento!)
En el mundo cartografiado, por el contrario, imagine dos procesos que "escriben". Lo hacen haciendo "almacenes de memoria", lo que da como resultado que el O / S pague los datos en el disco, eventualmente. Pero mientras tanto, se puede esperar que ocurran escrituras superpuestas.
He aquí un ejemplo. Digamos que tengo dos procesos que escriben 8 bytes en el desplazamiento 1024. El proceso 1 está escribiendo '11111111' y el proceso 2 está escribiendo '22222222'. Si usan E / S de archivo, entonces puede imaginarse, en el fondo del O / S, hay un búfer lleno de 1 y un búfer lleno de 2, ambos dirigidos al mismo lugar en el disco. Uno de ellos va a llegar primero y el otro un segundo. En este caso, gana el segundo. Sin embargo , si estoy usando el enfoque de archivo mapeado en memoria, el proceso 1 irá a un almacenamiento de memoria de 4 bytes, seguido de otro almacenamiento de memoria de 4 bytes (supongamos que ese no es el tamaño máximo de almacenamiento de memoria). El proceso 2 hará lo mismo. Según cuándo se ejecutan los procesos, puede esperar ver cualquiera de los siguientes:
La solución a esto es utilizar la exclusión mutua explícita, lo que probablemente sea una buena idea en cualquier caso. De todos modos, confiaba en el SO para hacer "lo correcto" en el caso de E / S de archivo de lectura / escritura.
La primitiva de exclusión mutua de clasificación es el mutex. Para archivos mapeados en memoria, le sugiero que busque un mutex mapeado en memoria, disponible usando (por ejemplo) pthread_mutex_init ().
Edite con un error: cuando está utilizando archivos mapeados, existe la tentación de incrustar punteros a los datos en el archivo, en el propio archivo (piense en la lista vinculada almacenada en el archivo mapeado). No desea hacer eso, ya que el archivo puede estar mapeado en diferentes direcciones absolutas en diferentes momentos o en diferentes procesos. En su lugar, utilice compensaciones dentro del archivo mapeado.
fuente
La concurrencia sería un problema. El acceso aleatorio es más fácil El rendimiento va de bueno a excelente. Facilidad de uso. No tan bueno. Portabilidad - no tan caliente.
Los he usado en un sistema solar hace mucho tiempo, y esos son mis pensamientos.
fuente