2010-05-06 18 views
18

Ho bisogno di rifattorizzare il mio progetto per renderlo immune all'eccezione OutOfMemory.Come simulare l'eccezione OutOfMemory

ci sono enormi collezioni utilizzati nel mio progetto e modificando un parametro posso fare il mio programma per essere più precisi o utilizzare meno della memoria ...

OK, questo è lo sfondo. Quello che mi piacerebbe fare è eseguire le routine in un ciclo:

  1. Eseguire le subroutine con il parametro predefinito.
  2. Cattura l'eccezione OutOfMemory, modifica il parametro e prova a eseguirlo di nuovo.
  3. Eseguire il 2 ° punto fino a quando i parametri consentono di eseguire le subroutine senza generare l'eccezione (in genere, è necessaria una sola modifica).

Ora, vorrei testarlo. Lo so, posso lanciare l'eccezione OutOfMemory da solo, ma vorrei simulare una situazione reale.

Quindi la domanda principale è:
Esiste un modo di impostare un qualche tipo di limite di memoria per il mio programma, che dopo aver raggiunto l'eccezione OutOfMemory verrà generata automaticamente?
Ad esempio, mi piacerebbe impostare un limite, diciamo 400 MB di memoria per il mio intero programma per simulare la situazione quando c'è una tale quantità di memoria disponibile nel sistema.
Si può fare?

risposta

2

vorrei suggerire un altro modo di guardare a questo. Non devi necessariamente esaurire la memoria. Hai solo bisogno di monitorare la quantità di memoria utilizzata e confrontarla con la memoria totale del sistema. Forse qualcosa come GC.GetTotalMemory sarà utile qui per vedere quanta memoria stai usando. Quindi perhaps this article ti aiuterà a ottenere la quantità totale di RAM fisica disponibile sul tuo sistema.

+0

Beh, nemmeno ho bisogno di confrontarlo con la memoria di sistema, ho solo bisogno di sapere quanta MB di RAM il mio programma ha usato. Ho bisogno di leggere il documento per GC ... grazie! – Gacek

+0

ok ... beh visto che stavi cercando OutOfMemoryException, ho pensato che volessi esaurire a un certo punto ai fini della messa a punto per ottenere il massimo delle prestazioni. Ma hey, se i metodi GC funzionano per te, fantastico! – Dave

+0

Beh, credo di poter usare i metodi GC e lanciare l'eccezione da solo dopo aver raggiunto un certo limite. Forse un po 'di background ... Ho bisogno di testare se funzionerebbe. – Gacek

5

Basta allocare un array molto grande. Molto probabilmente inizierai ad uscire dalle eccezioni di memoria una volta che l'applicazione C# raggiungerà 1,2-1,6 GB di RAM (di solito nella parte inferiore di tale intervallo, a condizione che il suo targeting x86).

+0

OK, ma è lo stesso che posso ottenere lanciando l'eccezione OutOfMemory per conto mio. Voglio simulare la situazione reale e testarla utilizzando alcuni piccoli set di dati (che consumano circa 400 MB di ram invece di 1,6 GB) – Gacek

+0

Che non funzionerà in modo affidabile su 64 bit. – Thorsten79

+0

Meglio, inizia a costruire array di array con 1 GB di lunghezza ciascuno. Sarai in grado di riprodurlo abbastanza velocemente. – Nayan

6
public void EatMemory() 
{ 
    List<byte[]> wastedMemory = new List<byte[]>(); 

    while(true) 
    { 
     byte[] buffer = new byte[4096]; // Allocate 4kb 
     wastedMemory.Add(buffer); 
    } 
} 

non dovrebbe richiedere molto tempo se non hai 12 GB di ram :)

+3

Om nom nom! Windows limita le applicazioni a 2 GB di memoria su x86 e penso che sia leggermente superiore a 64 bit, quindi 12 GB non contano. – NibblyPig

+0

Interessante, ho eseguito il codice sopra, e ha infastidito bene il mio PC. Windows è diventato completamente insensibile e alla fine sono arrivato al task manager per vedere Visual STudio utilizzando 3 GB di memoria. Non ho avuto eccezioni e l'utilizzo della memoria ha continuato a crescere fino a circa 3,1 GB per poi tornare a 3 GB ... Ho 4 GB di RAM. – NibblyPig

+0

@ SLC: il file di pagina probabilmente ti protegge da quello, che probabilmente è stato avviato quando hai notato che il tuo PC ha rallentato fino alla scansione. – Dave

16

Sembra un lavoro per ... System.Runtime.MemoryFailPoint.

http://msdn.microsoft.com/en-us/library/system.runtime.memoryfailpoint.aspx

penso che l'esempio nel collegamento si inserisce la vostra situazione. Impostare MemoryFailPoint a qualsiasi livello sia necessario, quindi prendere lo InsufficientMemoryException e regolare di conseguenza i parametri di input.

+0

Sembra che questa classe funzioni al contrario di ciò di cui ho bisogno. Verifica effettivamente se è disponibile una certa quantità di memoria (ad esempio, chiamando 'MemoryFailPoint (100)' si può controllare se l'operazione che consuma 100 MB può essere eseguita. Quello che mi serve è controllare quanta memoria il mio programma abbia già consumato. – Gacek

2

Un buon modo per simulare un'eccezione di memoria esaurita è eseguire il programma in una macchina virtuale (VM). È possibile impostare l'allocazione di memoria massima per la macchina virtuale su un livello sufficientemente piccolo da creare una pressione di memoria sul programma e provocare l'eccezione.

Alcune macchine virtuali open source sono: QEMU, xen e kvm. Una buona macchina virtuale commerciale è VMware Fusion per Mac OS X o VMware Player per Linux/Windows.

2
string value = new string('crazy', int.MaxValue);