Mi aplicación necesita mucha memoria y estructura de big data para realizar su trabajo. A menudo, la aplicación necesita más de 1 GB de memoria y, en algunos casos, mis clientes realmente necesitan usar la versión de 64 bits de la aplicación porque tienen varios gigabytes de memoria.Obligar a Windows a cargar DLL en lugares para que la memoria esté mínimamente fragmentada
En el pasado, podía explicar fácilmente al usuario que si la memoria alcanzaba de 1.6 a 1.7 GB de uso de memoria, estaba "sin memoria" o realmente cerca de una situación de "falta de memoria", y que necesitaban para reducir su memoria o pasar a una versión de 64 bits.
El año pasado noté que a menudo la aplicación solo usa aproximadamente 1 GB antes de que ya se quede sin memoria. Después de algunas investigaciones, parece que la causa de este problema es la fragmentación de la memoria. Utilicé VMMAP (una utilidad SysInternals) para ver el uso de la memoria de mi aplicación y vi algo como esto:
Las zonas de color naranja son asignadas por memoria por mi aplicación. Las áreas púrpuras son código ejecutable.
Como puede ver en la mitad inferior de la imagen, las áreas púrpuras (que son las DLL) se cargan en muchas direcciones diferentes, causando que mi memoria se fragmente. Esto no es realmente un problema si mi cliente no tiene una gran cantidad de datos, pero si mi cliente tiene conjuntos de datos que ocupan más de 1 GB, y una parte de la aplicación necesita un gran bloque de memoria (por ejemplo, 50 MB), puede dar como resultado una falla de asignación de memoria, causando que la aplicación se cuelgue.
La mayoría de mis estructuras de datos están basadas en STL ya menudo no requieren grandes porciones de memoria contigua, pero en algunos casos (por ejemplo, cadenas muy grandes), es realmente necesario tener un bloque contiguo de memoria. Desafortunadamente, no siempre es posible cambiar el código para que no necesite un bloque de memoria contiguo.
Las preguntas son:
- Cómo puedo influir en la ubicación en la DLL se cargan en la memoria, sin necesidad de utilizar de manera explícita REBASE en toda la DLL en el equipo del cliente, o sin cargar todo el archivo DLL de forma explícita.
- ¿Hay alguna manera de especificar las direcciones de carga de las DLL en su propio archivo de manifiesto de la aplicación?
- ¿O hay una manera de decirle a Windows (a través del archivo de manifiesto?) Que no distribuya la DLL (creo que esta dispersión se llama ASLR).
Por supuesto, la mejor solución es a la que puedo influir desde el archivo de manifiesto de mi aplicación, ya que dependo de la carga automática/dinámica de las DLL por parte de Windows.
Mi aplicación es una aplicación de modo mixto (administrado + no administrado), aunque la mayor parte de la aplicación no está administrada.
¿Alguna sugerencia?
¿Esto es algo que podría ayudarlo? http://msdn.microsoft.com/en-us/library/f7f5138s.aspx – detunized
mmm, ¿realmente necesita tanta memoria al mismo tiempo? Process Monitor almacena sus registros en la memoria virtual y solo lleva los datos al espacio de direcciones de memoria del proceso cuando es necesario. Consulte http://blogs.msdn.com/b/oldnewthing/archive/2004/08/10/211890.aspx para obtener un código ejemplo –
No estoy seguro de que todos los que dejan una respuesta comprendan las ramificaciones de ASLR: http://en.wikipedia.org/wiki/ASLR –