2012-05-14 7 views
5

Mi comprensión de cómo funcionan los archivos mapeados en C# es que cada solicitud de datos da como resultado una copia. Por ejemplo, si tuviera una gran estructura de datos persistida como un archivo, usar un archivo mapeado de memoria daría como resultado memoria para el archivo real mapeado en la RAM, y una copia que resida en un montón de GC una vez que se leyó desde el archivo.¿Es posible evitar copias de datos cuando se usan archivos mapeados en memoria en C#?

Supongo que esto se debe a que los punteros y el GC no se llevan bien juntos en general.

Entonces, ¿hay alguna forma de evitar esto?

  • ¿Quizás a través de algún modo mixto C++ que puede exponer una API administrada sobre la memoria de datos mapeados?
  • ¿Qué pasa con la manipulación directa del puntero con C# inseguro?

El problema general que estoy tratando de resolver es compartir una gran estructura de datos entre múltiples procesos. La estructura de datos se utiliza para responder a un pequeño conjunto de "preguntas" que se pueden exponer como una API simple (es decir, básicamente, un índice altamente especializado de muchos otros datos).

En una nota lateral, ¿esto no hace inútil la API de .NET para el escenario de "compartir grandes cantidades de datos"?

+1

http://code.msdn.microsoft.com/windowsdesktop/Inter-process-communication-e96e94e7 –

+0

¿Lees todo el archivo a la vez en la aplicación .NET? Si está leyendo porciones del archivo mapeado en memoria, según sea necesario, asigna una gran cantidad de pequeños búferes, pero esto no es tan caro como podría pensar. Puede ser posible evitar hacer copias, pero ¿es el problema de hacer copias realmente un problema? –

+0

Tengo aplicaciones .NET que de manera muy efectiva "comparten grandes cantidades de datos" de varias maneras, incluidos los archivos mapeados en memoria. En particular, una suite comparte más de 8 gigabytes, y el uso total de la memoria de esos programas sorprendentemente se acerca a los 8 gigabytes. –

Respuesta

4

Puede usar un código inseguro para acceder directamente a la memoria mapeada. Sugiero que busque en "estructuras blittables" que son tipos de estructuras que se pueden copiar en la memoria sin modificaciones. Aquí hay un ejemplo:

struct MyDataRecord { public int X, Y; } 

... 

for (var i = 0 .. 10) { 
((MyDataRecord*)pointerToUnmanagedMemory)[i] = new MyDataRecord() { X = i, Y = i * i }; 
} 

Esto es muy eficiente y conveniente.

+0

Hmm, saltó el mutex con nombre que necesita para asegurarse de que un proceso no lea los datos que se están escribiendo. Eso tiene una habilidad especial para arrojar "conveniente" fuera de la ventana. Y matar perf. –

+0

Parece que el código no seguro y las estructuras blittables serán el camino a seguir ... Gracias @usr. También encontré esto después de incluir "inseguro" en mi búsqueda: http://stackoverflow.com/questions/7956167/how-can-i-quickly-read-bytes-from-a-memory-mapped-file-in-net – David

Cuestiones relacionadas