2010-10-27 7 views
6

Desidero leggere un grande InputStream e restituirlo come stringa. Questo InputStream è grande. Quindi, normalmente ci vuole molto tempo e molta memoria mentre è in esecuzione. Il seguente codice è quello che ho sviluppato finora. Ho bisogno di convertire questo codice come fa il lavoro in un tempo minore consumando meno memoria.Ottimizzazione delle prestazioni di lettura di un grande InputStream in java

Puoi darmi qualche idea per farlo.

BufferedReader br = 
    new BufferedReader(
     new InputStreamReader(
      connection.getInputStream(), 
      "UTF-8") 
     ); 

StringBuilder response = new StringBuilder(1000); 

char[] buffer = new char[4096]; 

int n = 0; 
while(n >= 0){ 
    n = br.read(buffer, 0, buffer.length); 
    if(n > 0){ 
     response.append(buffer, 0, n); 
    } 
} 
return response.toString(); 

Grazie!

+2

cos'è un "lotto" di memoria. È inevitabile che ti serva abbastanza memoria per contenere l'intera stringa che stai costruendo. Stai vedendo qualcosa di drammaticamente peggiore di quanto ti aspetteresti? – djna

+0

cosa stai leggendo? – dogbane

+0

Sì. è vero che la memoria consumata è proporzionale alla dimensione della risposta (String). Ma qui, sta per usare la memoria in modo efficace (Riducendo l'uso di memoria non necessario, ecc.). Per un esempio qui ho usato StringBuilder invece di accodare l'input a una stessa String usando + 's (come str = str + newStr)) per ridurre l'uso di memoria non necessario. In questo modo, mi aspettavo ulteriori idee per rendere il mio codice molto migliore gestendo la memoria e velocizzando il codice. – Namalak

risposta

3

Quando si esegue l'I/O bufferizzato, è possibile leggere un solo carattere alla volta dal lettore bufferizzato. Quindi crea la stringa e fai un toString() alla fine.

+0

Non sono questi caratteri di lettura, mentre memorizzarli in un array di caratteri è meglio della lettura di ogni carattere e della stringa? Voglio dire read() Vs read (char [], int start, int end) – Namalak

+1

Questo è ciò che fa il lettore bufferato sotto le copertine .... Prova a guardare l'origine di BufferedReader. –

1

È possibile che per file di grandi dimensioni su alcuni sistemi operativi, mmap il file tramite FileChannel.map offra prestazioni migliori: mappare il file e quindi creare una stringa dal ByteBuffer mappato. Dovrai fare un benchmark, perché può darsi che l'I/O tradizionale sia più veloce in alcuni casi.

+0

OP sta leggendo un URL, non un file. – dogbane

+0

Sì. Sono nuovo di questo FileChannel.map. Può essere usato con l'OP che legge un URL – Namalak

+0

@dogbane e Namalak: Per essere onesti non è stato chiarito fino a dopo aver lasciato la mia risposta :) Lascerò questo qui se qualcuno arriva più tardi e vuole fare il lo stesso per un file. –

0

Sai in anticipo la probabile lunghezza massima della tua corda? Al momento si specifica una capacità innata di 1000 per il proprio buffer. Se ciò che leggi è molto più grande di quello che pagherai, dovrai assegnare dei buffer interni più grandi.

Se si ha il controllo del ciclo di vita di ciò che si sta leggendo, forse è possibile allocare un singolo array di byte riutilizzabile come buffer. Quindi evitando la garbage collection.

0

Aumentare la dimensione del buffer. Più grande è il buffer, più velocemente tutti i dati possono essere letti. Se sai (o puoi allenarti) quanti byte sono disponibili nello stream, potresti persino allocare un buffer della stessa dimensione in anticipo.

+0

Grazie. 1000 è buono fino ad ora. Anche l'aumento non necessario della dimensione del buffer è inefficiente vero? – Namalak

+0

Intendevo il buffer di caratteri che hai impostato su 4096. – dogbane

0

È possibile eseguire il codice in un thread separato ... non verrà eseguito più velocemente, ma almeno il programma sarà in grado di eseguire altre operazioni anziché attendere i dati dallo streaming.

+0

Ma non ci sono lavori paralleli eseguibili. – Namalak

Problemi correlati