Hallo Experten,
ich muss mit einem Servlet in riesiegen (>500k) Textfiles Strings ersetzten.
Das geht auch, allerding ist es bei Dateien >64K extrem langsam. Mein 600k Testfile rödelt jetztschon eine halbe Stunde. Da muss doch etwas zu machen sein!
Die Quelle ist eine CLOB Stalte in einer Oracle DB und das Ziel ist es, einen Filedownload er (veränderten Quelle) zu machen.
InputStream is = rs.getBinaryStream("RTD\_DATA");
BufferedInputStream ib = new BufferedInputStream(is,1024\*1024);
while (0
Da ich Strings ersetzen muß, muß ich den Inputstream in einen String wandeln, und das ist auch die Bremse. Der BufferedInputStream hat da auch nix bebracht.
Hat jemand eine Idee zur Performanceverbesserung?
Danke
Nic
Hallo!
StringBuffer oder StringBuilder statt String dürften dir bei solcher Menge an Dateien schon ein bisschen Performance geben.
Womit ist das Servlet am meisten beschäftigt? Bzw. wo ist die Engstelle(CPU,RAM,HDD)?
LG Matthias
[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]
Moien
Die Quelle ist eine CLOB Stalte in einer Oracle DB und das
Ziel ist es, einen Filedownload er (veränderten Quelle) zu
machen.
InputStream is = rs.getBinaryStream(„RTD_DATA“);
BufferedInputStream ib = new
BufferedInputStream(is,1024*1024);
while (0
Da ich Strings ersetzen muß, muß ich den Inputstream in einen
String wandeln, und das ist auch die Bremse. Der
BufferedInputStream hat da auch nix bebracht.
(brauchst du die newlines mit oder ohne \r ?)
StringBuffer sb = new StringBuffer();
String temp = ib.readLine();
while (temp !=null){
sb.append (temp);
sb.append ("\n");
temp = ib.readLine();
}
s = sb.toString()
und das riesengrosse Problem bei dir die zusammenfügen mit s=s+c. Das erzeugt bei jedem Schleifendurch ein neues String-Object und lässt dann den gc Amok laufen.
Noch schneller wird das ganze mit nio. Dafür brauchst du allerdings java 1.4 und das haben noch nicht alle Server. Wie sieht’s bei dir aus ?
cu
InputStream is = rs.getBinaryStream(„RTD_DATA“);
InputStream für Binärdaten, FileReader für Textdateien.
while (0
So erzeugst Du 500.000 neue Objekte, von denen 499.999 nicht gebraucht werden.
Im Mittel ist jedes dieser Objekte 250.000 Bytes groß.
250.000 * 500.000 ist nochmal wieviel?
125.000.000.000 Bytes (125 GB). Bingo!
Hat jemand eine Idee zur Performanceverbesserung?
Die bereits genannten StringBuilder, StringBuffer, und das Einlesen ganzer Zeilen oder wesentlich größerer Blöcke als jeweils ein Byte.
Danke!
ich habe es mit pumpkins Code geändert und der Erfolg war durchschlagend. nun ist mit auch klar, wieso.
Danke an Euch alle!
ich habe es mit pumpkins Code geändert und der Erfolg war
durchschlagend.
*g*.
Wenn du Textdateien einliest erreicht java etwa 90% der Geschwindigkeit der Platte. Bei einer 60MB/s Platte wären das also etwa 54MB Text pro Sekunde. Dazu muss man ein temporäres byte[] (mit Länge = Grösse der Datei) über InputStream.read (int byte[], int pos, int length) einlesen. Dann das Array per new String (byte[] data, Charset) in einen String verwandeln.
Die Methode aus meinem ersten Post erreicht „nur“ 60-80% Plattengeschwindigkeit (Länge der Zeilen ist entscheident, Länger => schneller).
Mit nio kommt man auch über 95%, aber der Programmieraufwand steigt dann halt rapide an.
Deine 500KB Dateien sollten also …uhm … im ms-Bereich gelesen werden können. Auch mit der doofen readLine-Methode.
cu