Domanda

Ho 10 thread che scrivono migliaia di piccoli buffer (16-30 byte ciascuno) in un file enorme in posizioni casuali. Alcuni dei fili gettare OutOfMemoryException su FileStream.Write) opreation (.

Qual è la causa del OutOfMemoryException? Che cosa cercare?

sto usando il FileStream come questo (per ogni elemento scritto - questo codice viene eseguito da 10 diversi thread):

using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite, BigBufferSizeInBytes, FileOptions.SequentialScan))
{
 ...
 fs.Write();
}

Ho il sospetto che tutti i buffer allocati all'interno del FileStream non vengono rilasciate nel tempo da parte del GC. Quello che non capisco è il motivo per cui il CLR, invece di buttare, non si limita a eseguire un ciclo di GC e liberare tutti i buffer non utilizzati?

Nessuna soluzione corretta

Altri suggerimenti

Se dieci le discussioni stanno aprendo i file il tuo codice mostra, allora avete un massimo di dieci oggetti FileStream undisposed in qualsiasi momento. Sì, FileStream ha hanno un buffer interno, la cui dimensione specificata con "BigBufferSizeInBytes" nel codice. La prego di rivelare l'esatto valore? Se questo è abbastanza grande (per esempio ~ 100MB) allora potrebbe essere la fonte del problema.

Per impostazione predefinita (vale a dire quando non si specifica un numero su di costruzione), questo buffer è 4kB e che di solito è bene per la maggior parte delle applicazioni. In generale, se si ha realmente a cuore le prestazioni di scrittura del disco, allora si potrebbe aumentare questo per un paio di 100kB, ma non di più.

Tuttavia, per la vostra applicazione specifica così facendo non avrebbe molto senso, come ha detto tampone non potrà mai contenere più di 16-30 i byte si scrive in esso prima di Dispose () dell'oggetto FileStream.

Per rispondere alla tua domanda, un OutOfMemoryException si butta solo quando la memoria richiesta non può essere allocato dopo di un GC è stato eseguito. Anche in questo caso, se il buffer è davvero grande allora il sistema potrebbe avere un sacco di memoria sinistra, non solo una contiguo chunk. Questo perché il mucchio di grandi dimensioni oggetto non è mai compattato.

Ho ricordato alla gente questo un paio di volte, ma il Grande oggetto mucchio può gettare tale eccezione piuttosto subtially, in cui apparentemente si hanno pleanty di memoria disponibile o l'applicazione è in esecuzione su OK.

Ho eseguito in questo problema abbastanza frequentemente quando si fa quasi exactally ciò che il vostro discribing qui.

È necessario inviare più del vostro codice per rispondere a questa domanda in modo corretto. Comunque, sto cercando di indovinare che potrebbe anche essere collegato ad un potenziale problema di Halloween (Spooky Dooky) .

Il buffer per cui si sta leggendo può anche essere il problema (di nuovo oggetto di grandi dimensioni heap legati) anche di nuovo, è necessario mettere in maggiori dettagli su quello che sta succedendo lì nel ciclo. Ho appena inchiodato l'ultimo bug che ho avuto, che è praticamente identico (sto eseguendo molti hash parallelo aggiornamento di cui tutti richiedono Stato indipendente da mantenere attraverso lettura di del file di input) ....

OOP! basta scorrere su e ho notato "BigBufferSizeInBytes", sto appoggiato verso Large Object Heap di nuovo ...

Se fossi in te, (e questo è estremamente difficile a causa della mancanza di contesto), vorrei fornire una piccola spedizione "mbuf", dove è stato copiato dentro e fuori invece di consentire tutti del tuo thread disperate di leggere individualmente attraverso il vostro grande array supporto ... (vale a dire che è difficile non provocare allocazioni insadential con la sintassi codice molto sottile).

Buffer non sono in genere assegnate all'interno FileStream. Forse il problema è la linea "scrivere migliaia di piccoli buffer" - non si ha realmente dire che? Normalmente si ri-utilizzare un buffer molte, molte, molte volte (vale a dire su diverse chiamate di lettura / scrittura).

Inoltre - questo è un singolo file? Una singola FileStream non è garantito per essere thread-safe ... quindi se non stai facendo la sincronizzazione, si aspettano il caos.

E 'possibile che queste limitazioni derivano dal sistema operativo sottostante, e che .NET Framework è impotente a superare questo tipo di limitazioni.

Quello che non posso dedurre dal codice di esempio è se si apre un sacco di questi oggetti FileStream, allo stesso tempo, o aprirli veramente veloce in sequenza. L'utilizzo del 'usando' parola chiave farà in modo che i file sono chiusi dopo la chiamata fs.Write (). Non c'è nessun ciclo GC necessario per chiudere il file.

La classe FileStream è davvero orientata verso sequenziale accesso in lettura / scrittura ai file. Se avete bisogno di scrivere rapidamente a posizioni casuali in un file di grandi dimensioni, si potrebbe voler dare un'occhiata a utilizzando il mapping file virtuale.

Aggiornamento: Sembra che la mappatura del file virtuale non sarà ufficialmente supportato in .NET fino 4.0. Si consiglia di dare un'occhiata a implementazioni di terze parti per questa funzionalità.

Dave

sto vivendo qualcosa di simile e si chiese se mai inchiodato lungo la radice del problema?

Il mio codice fa un bel po 'di copia tra i file, passando un bel paio di mega byte tra file diversi. Ho notato che, mentre l'utilizzo della memoria processo rimane all'interno di un intervallo ragionevole, l'allocazione di memoria di sistema spara troppo alto durante la copia - molto più di quanto è utilizzato da mio processo.

Ho rintracciato il problema fino al FileStream.Write () chiamata - Quando questa linea è preso, l'utilizzo della memoria sembra andare come previsto. I miei BigBufferSizeInBytes è il valore predefinito (4k), e non riesco a vedere da nessuna parte dove questi potrebbero essere la raccolta di ...

Tutto ciò che hai scoperto mentre guardando il vostro problema riconoscente sarebbe ricevuto!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top