La mia applicazione richiede molta memoria e una grande struttura di dati per poter funzionare. Spesso l'applicazione richiede più di 1 GB di memoria e in alcuni casi i miei clienti hanno davvero bisogno di utilizzare la versione a 64 bit dell'applicazione perché hanno diversi gigabyte di memoria.Forzare Windows per caricare le DLL in modo che la memoria sia minimamente frammentata
In passato, potevo facilmente spiegare all'utente che se la memoria raggiungeva da 1,6 a 1,7 GB di utilizzo della memoria, era "a memoria insufficiente" o realmente vicino a una situazione di "esaurimento della memoria", e di cui avevano bisogno per ridurre la memoria o passare a una versione a 64 bit.
L'anno scorso ho notato che spesso l'applicazione utilizza solo circa 1 GB prima che finisca la memoria. Dopo alcune indagini sembrava che la causa di questo problema fosse la frammentazione della memoria. Ho usato VMMAP (un'utilità SysInternals) per esaminare l'utilizzo della memoria della mia applicazione e ho visto qualcosa del genere:
Le aree arancioni sono memoria allocata dalla mia applicazione. Le aree viola sono codice eseguibile.
Come si può vedere nella metà inferiore dell'immagine, le aree viola (che sono le DLL) sono caricate in molti diversi indirizzi, causando la frammentazione della memoria. Questo non è un problema se il mio cliente non ha molti dati, ma se il mio cliente ha set di dati che richiedono più di 1 GB e una parte dell'applicazione richiede un grande blocco di memoria (ad esempio 50 MB), può causare un errore di allocazione della memoria, causando l'arresto anomalo dell'applicazione.
La maggior parte delle mie strutture dati sono basate su STL e spesso non richiedono grossi blocchi di memoria contigua, ma in alcuni casi (ad esempio stringhe molto grandi), è davvero necessario avere un blocco di memoria contiguo. Sfortunatamente, non è sempre possibile modificare il codice in modo che non abbia bisogno di un blocco di memoria contiguo.
Le domande sono:
- Come posso influenzare la posizione in cui DLL vengono caricati in memoria, senza esplicito utilizzando REBASE su tutto il DLL sul computer del cliente, o senza caricare tutti i DLL in modo esplicito.
- C'è un modo per specificare gli indirizzi di carico delle DLL nel file manifest dell'applicazione?
- Oppure c'è un modo per dire a Windows (tramite il file manifest?) Di non disperdere le DLL (penso che questa diffusione sia chiamata ASLR).
Naturalmente la soluzione migliore è quella che posso influenzare dal file manifest della mia applicazione, poiché mi affido al caricamento automatico/dinamico delle DLL da parte di Windows.
La mia applicazione è un'applicazione in modalità mista (gestita + non gestita), sebbene la maggior parte dell'applicazione non sia gestita.
Qualche suggerimento?
È qualcosa che potrebbe aiutarti? http://msdn.microsoft.com/en-us/library/f7f5138s.aspx – detunized
mmm, hai davvero bisogno di molta memoria allo stesso tempo? Process Monitor memorizza i suoi registri nella memoria virtuale e porta i dati nello spazio degli indirizzi di memoria del processo solo quando necessario, controlla http://blogs.msdn.com/b/oldnewthing/archive/2004/08/10/211890.aspx per un codice esempio –
Non sono sicuro che tutti lascino una risposta per capire le ramificazioni di ASLR: http://en.wikipedia.org/wiki/ASLR –