Strategia per evitare l'esaurimento della memoria in un'applicazione intensiva della memoria

3

La mia applicazione C # .NET deve leggere molti file con letture elettriche. Ci sono diversi calcoli da fare e i file di output devono essere generati. A causa della natura dell'input sarebbe molto inefficiente da produrre dopo ogni riga di input o anche dopo un file, quindi sarebbe meglio farlo dopo un blocco di file.

Il motivo è che ogni file contiene un elenco di letture / unità elettriche per un timestamp, ma l'output deve essere costituito da file per ogni unità.
Quindi, per esempio, l'input sarebbe di 100 file ciascuno contenente per es. volt, ampere, watt, codice di stato per un timestamp (2015_08_31_00_00_00.txt, 2015_08_31_00_00_05.txt ...).
L'uscita dovrebbe essere per unità elettrica e ad es. un file al giorno
(c: //ampere/2015_08_31.txt, c: //volt/2015_08_31.txt ...).

Si noti che questa è un'immagine semplificata dell'applicazione. In realtà ci sono diversi formati di input e output, strutture di directory ecc.

Quello che voglio fare è, mantenere la calcolata e pronta per i valori di uscita in memoria e stamparli secondo strategie diverse. Questo potrebbe essere ad es. fino a quando non vengono elaborati tutti i file di input.

Dato che alcune strategie come questa possono comportare troppi dati in memoria, vorrei monitorare l'utilizzo della memoria e decidere se ho bisogno di produrre prima.

So come ottenere la memoria utilizzata del mio programma , ma come faccio a ottenere una stima sicura sulla memoria disponibile?

Per quanto ho capito, questo non è un compito semplice a causa della frammentazione della memoria, del paging, del cestino e così via. In questo caso, so che ho ottenuto il limite di memoria indotta a 32 bit con le impostazioni di generazione correnti, ma vorrei ottenere una risposta generale che potrebbe essere applicata anche a un programma a 64 bit.

Come faccio a stimare quando è ancora disponibile memoria sufficiente per scrivere su disco, ma utilizzare una buona quantità di RAM per ottimizzare l'I / O?

Aggiornamento
Non ho ancora implementato questa funzione, quindi non posso dire se i problemi di memoria si verifichino in circostanze normali. Grazie a tutti i tuoi commenti e risposte, vedo che non è facilmente realizzabile.

La mia idea attuale è quella di utilizzare un limite di input fisso in base alla dimensione dei file di input. Ciò non proteggerebbe ancora dai problemi se altri programmi creano un carico pesante. Ogni file è sempre di pochi KB.

Terrò a mente l'idea di SQLite ma dovrò controllare se ottengo un OK

    
posta John 01.09.2015 - 02:36
fonte

3 risposte

6

Sfortunatamente, non c'è davvero un buon modo per rispondere alla domanda "quanto RAM usa il mio programma?" o "quanto sono vicino a colpire il OutOfMemoryException muro?", per una serie di motivi. È molto più complicato di quanto dovrebbe essere.

Una cosa che potresti voler fare, però, è assicurarti che non stai tenendo i dati di input inutilmente. Ad esempio, a seconda di come si elaborano i dati, potrebbe essere possibile leggere il file ed eseguire i calcoli pertinenti, una riga alla volta o una piccola serie di righe alla volta. Se continui ad aggregare i risultati, ma non conservare i dati di input, è necessario che l'utilizzo della memoria venga interrotto.

Se ciò non aiuta, perché i risultati continuano ad accumularsi, il modo migliore per gestire che è di scaricarli dalla memoria. Inseriscili in un database relazionale, ad esempio, alla stessa velocità con cui entrano e poi finiscono sul disco. E poi alla fine della giornata, esegui una query che inserirà i risultati del giorno (SUGGERIMENTO: questo è molto più semplice se hai un campo data / ora che viene impostato quando inserisci i record) e salvali nella loro versione finale nei file di output.

    
risposta data 01.09.2015 - 02:52
fonte
1

puoi utilizzare un contatore delle prestazioni dal namespace System.Diagnostics.
Utilizza il costruttore di due stringhe con categoryName di "Memoria" e counterName di "Byte disponibili". Puoi quindi usare qualcosa come
long availableBytes = Convert.ToInt64(myPerformanceCounter.NextValue()) per ottenere una lettura.
Se hai bisogno di più informazioni di quelle fornite, puoi giocare con diverse categorie e contatori.
Nota importante: la classe PerformanceCounter utilizza l'interfaccia IDisposable , quindi assicurati di avvolgerla in una dichiarazione using o chiama il metodo Dispose() quando hai terminato.

    
risposta data 22.01.2018 - 19:11
fonte
0

Se si conosce la quantità massima di spazio necessaria per l'output e si adatta allo spazio degli indirizzi, è possibile utilizzare una funzione come VirtualAlloc () per riservare un intervallo di indirizzi di memoria, con o senza l'esecuzione di pagine. Questo non assegnerà alcuna pagina fisica finché non proverai effettivamente a scrivere su di loro. Pertanto, non riceverai alcun errore di memoria esaurita solo per riservare la regione di memoria. Puoi anche aprire i file di input come file mappati in memoria, in modo che il sistema operativo copi solo le pagine fisiche dal disco quando le leggi.

A quel punto, non sarà necessario effettuare chiamate aggiuntive per allocare la memoria: quando si esaurisce la memoria fisica, il sistema operativo deve solo sfogliare le pagine che non si utilizzano nella memoria virtuale, oppure è possibile VirtualFree () le pagine dopo che sono state scritte.

    
risposta data 01.09.2015 - 07:26
fonte

Leggi altre domande sui tag