2013-08-04 11 views
7

Ho usato i flussi molte volte ma non ho mai letto molto su come effettivamente funziona. Né ne so molto di loro se non che un flusso è solo una metafora. Un flusso rappresenta solo una sequenza di byte. Non so molto su come effettivamente funzionano, suppongo che l'apertura di un flusso di file in Java interagisca con il sistema operativo che ha la funzionalità di dare un "puntatore" a un flusso.In che modo gli stream in Java influiscono sul consumo di memoria?

Fondamentalmente la mia domanda è come i flussi influenzano il consumo di memoria. Quando si dispone ad esempio di un flusso di input e si inizia a leggere da esso, si inizia ad aumentare il consumo di memoria con la quantità di byte letti? Quando si apre un flusso in Java, non si carica effettivamente il file completo prima di iniziare a leggere? Se si legge da uno stream e si scrive direttamente su un altro stream, si aumenta solo la memoria con la quantità di byte letti (e potenzialmente presenti nel buffer)? Se leggi byte su un array di byte in java, aumenti il ​​consumo di memoria con le dimensioni del file?

Può sembrare una domanda strana ma potrei aver bisogno di una guida/correzione sulla mia comprensione. Grazie.

+0

Hai una spiegazione molto buona [qui] (http://www.ibm.com/developerworks/library/j-zerocopy/index.html) zero copia. Inoltre spiega i buffer e l'utilizzo della memoria. –

risposta

3

C'è quasi il nessun sovraccarico di memoria dopo aver iniziato a leggere dal InputStream. L'OS-overhead è molto piccolo per l'apertura di un file e un piccolo overhead nella JVM per la nuova allocazione degli oggetti. Potrebbe anche esserci un piccolo overhead nel caso in cui si utilizza BufferedInputStream, che è 8 KB per impostazione predefinita.

L'overhead per la scrittura dipende molto da dove si scrive. Se è un FileOutputStream, allora è lo stesso come descritto sopra. Se si tratta di un valore ByteArrayOutputStream, nel caso migliore sono i byte (2 * lunghezza del flusso) e (3 * lunghezza del flusso) byte nello scenario peggiore. Cioè per copiare 10k byte da un InputStream in un array di byte 30k byte verranno allocati nel caso peggiore.

La ragione di ciò è che la crescita delle dimensioni di ByteArrayOutputStream 2 volte dopo il raggiungimento del limite e alloca anche un nuovo buffer quando si chiama toByteArray().

5

Tutte le risposte di cui sopra sono ottime risposte, ma non credo che rispondano alla tua domanda iniziale sul consumo di memoria.

In Java è possibile visualizzare i flussi in diversi modi. Prima di tutto hai flussi Raw che sono il flusso di livello più basso e interagisci con il sistema operativo sottostante (File, Rete ecc.) Con un sovraccarico di memoria minimo. In secondo luogo sono i flussi bufferizzati che possono essere utilizzati per avvolgere un flusso raw e aggiungere un po 'di buffering e migliorare significativamente le prestazioni. Il buffering del flusso aggiunge una quantità fissa di overhead di memoria per il buffering e può essere impostato dall'applicazione. Non sei sicuro di quale sia l'impostazione predefinita, ma probabilmente è qualcosa di minimo come 32K.

Il terzo tipo di flusso è un flusso di memoria (ad es. ByteArrayInput/Ouput) che utilizza quanta memoria si scrive su di essi e crescerà se necessario e non disporrà della loro memoria finché il conteggio dei riferimenti non si azzera (sono non più utilizzato). Questi flussi sono molto utili ma ovviamente possono consumare molta memoria.

Il tipo finale non è in realtà un flusso ma è una classe di I/O denominata Readers che fornisce assistenza con la conversione dei dati da e verso uno stream come indicato sopra. Questi flussi operano su un raw. bufferizzato o flusso di memoria e consumerà tutta la memoria del flusso sottostante che viene utilizzato.

Problemi correlati