Ho un'app di console di Windows che dovrebbe funzionare senza riavvii per giorni e mesi. L'app recupera "lavoro" da un MSMQ e lo elabora. Ci sono 30 thread che elaborano un blocco di lavoro contemporaneamente.Oggetto heap e stringa di grandi dimensioni Oggetti provenienti da una coda
Ogni blocco di lavoro proveniente da MSMQ è di circa 200 kb, la maggior parte dei quali è allocata in un singolo oggetto String.
Ho notato che dopo l'elaborazione di circa 3-4 migliaia di questi blocchi di lavoro il consumo di memoria dell'applicazione è ridicolmente alto consumando 1 - 1,5 GB di memoria.
Eseguo l'app tramite un profiler e ho notato che la maggior parte di questa memoria (forse un ingaggio) non è in uso nell'heap di oggetti grandi ma la struttura è frammentata.
Ho trovato che il 90% di questi byte inutilizzati (garbage collection) sono stati assegnati in precedenza a String. Ho iniziato a sospettare che le stringhe provenienti da MSMQ siano state allocate, utilizzate e quindi deallocate e siano quindi la causa della frammentazione.
Capisco che cose come GC.Collect (2 o GC.Max ...) non siano d'aiuto dato che gc l'heap di oggetti grandi ma non lo compattano (che è il problema qui). Quindi penso che quello di cui ho bisogno è di mettere in cache queste stringhe e riutilizzarle in qualche modo ma, dal momento che le stringhe sono immutabili, dovrei usare StringBuilder.
La mia domanda è: è comunque necessario non modificare la struttura sottostante (ad esempio utilizzando MSMQ poiché questo è qualcosa che non posso cambiare) ed evitare comunque di inizializzare una nuova stringa ogni volta per evitare di frammentare il LOH?
Grazie, Yannis
UPDATE: A proposito di come questi pezzi "lavoro" sono attualmente recuperati
Attualmente questi sono memorizzati come oggetti WorkChunk nel MSMQ. Ciascuno di questi oggetti contiene una stringa denominata Contenuto e un'altra stringa denominata Intestazioni. Questi sono dati testuali reali. Posso cambiare la struttura di archiviazione in qualcos'altro se necessario e potenzialmente il meccanismo di archiviazione sottostante se necessario per qualcos'altro rispetto a un MSMQ.
Sul lato nodi lavoratori attualmente facciamo
WorkChunk pezzo = _Queue.Receive();
Quindi c'è poco che possiamo memorizzare in questa fase. Se abbiamo cambiato la struttura (s) in qualche modo, allora suppongo che potremmo fare un po 'di progressi. In ogni caso, dovremo risolvere questo problema, quindi faremo tutto il necessario per evitare di buttare fuori mesi di lavoro.
AGGIORNAMENTO: Ho continuato a provare alcuni dei suggerimenti riportati di seguito e ho notato che questo problema non può essere riprodotto sul mio computer locale (con l'app Windows 7 x64 e 64 bit). questo rende le cose molto più difficili - se qualcuno sa perché allora sarebbe davvero utile ripubblicare questo problema localmente.
Come si ricevono quelle stringhe? Quando sono archi sei bloccato. Vengo da un flusso o da un byte [] potresti avere alcune opzioni. –
Ciao Henk - Dai un'occhiata all'aggiornamento per avere più informazioni su questi pezzi di lavoro – Yannis
Ma è un problema reale? 1.5 GB su un PC a 64 bit con> = 8 GB di RAM dovrebbe essere in grado di continuare. –