miffi
Erfahrenes Mitglied
Hallo zusammen.
Momentan muss ich Log-Dateien parsen, es handelt sich dabei um große Text-Dateien mit mindestens mehreren hundert MB (mein Testfile ist ~400MB). Da ich jede Zeile einzeln brauche, hat sich der java.io.BufferedReader angeboten, der mir bequemerweise bereits eine readLine() Methode liefert.
Das Problem ist jetzt, dass das Einlesen der Datei viel zu lang dauert. Ich habe alle Operationen auf die eingelesenen Zeilen auskommentiert, um wirklich die reine Lesedauer zu erhalten. Die Messung sieht folgendermaßen aus:
Diese Messung ergibt ca. 1ms/Zeile Verarbeitungszeit. Was auch zutrifft, wenn ich ein kleines Testfile benutze oder den Puffer des Readers höhersetze (Maximum waren 10k bisher).
Meine bisherigen Überlegungen/Ansätze/Tests:
Ich hoffe sehr, dass Java in Sachen Character-Verarbeitung nicht einfach nur langsam ist und einer von euch mir weiterhelfen kann. Mein guter Freund Google sagt mir seit gestern, dass es (außer Frameworks von Apache z.B.) keine besseren Ansätze gibt zum zeilenweisen Auslesen als den BufferedReader.
Grüße
miffi
Momentan muss ich Log-Dateien parsen, es handelt sich dabei um große Text-Dateien mit mindestens mehreren hundert MB (mein Testfile ist ~400MB). Da ich jede Zeile einzeln brauche, hat sich der java.io.BufferedReader angeboten, der mir bequemerweise bereits eine readLine() Methode liefert.
Das Problem ist jetzt, dass das Einlesen der Datei viel zu lang dauert. Ich habe alle Operationen auf die eingelesenen Zeilen auskommentiert, um wirklich die reine Lesedauer zu erhalten. Die Messung sieht folgendermaßen aus:
Java:
FileReader fr = new FileReader(file);
br = new BufferedReader(fr);
String line = null;
long lineCounter = 0;
long ts1 = System.currentTimeMillis();
while((line = br.readLine()) != null){
// hier kämen Aufrufe zum Verarbeiten der Zeile
lineCounter++;
if(lineCounter % 1000 == 0){
long ts2 = System.currentTimeMillis();
System.out.println(lineCounter + " (" + (ts2 - ts1) + "ms)");
ts1 = ts2;
}
Thread.sleep(1);
}
Meine bisherigen Überlegungen/Ansätze/Tests:
- An mangelnden System-Resourcen/hohem Garbage-Collecting kann es kaum liegen, da stets zwischen 1 und 2 GB RAM zur Verfügung standen, sowie 90% CPU (2x2.3GHz). Der Javaw-Prozess hat auch nie mehr 10 - 12 KB RAM in Anspruch genommen.
- Andere Streams zu verschachteln (FileInputStream => BufferedInputStream => InputStreamReader => BufferedReader) hat keinen Unterschied gemacht
- RandomAccessFile#readLine() dauert ebenfalls gleich lang
- Mit einer Puffergröße von 10k komme ich beim byte-weisen Einlesen auf 0.0068ms/Zeile. Das ist jedoch hinfällig, wenn die Daten programmatisch wieder nach CR/LF o.Ä. durchsucht und gesplitted werden müssen (ebenfalls 1ms/Zeile).
- Ein Kollege hat eine kleine (und schlampige) Test-Routine in C# geschrieben, mit einem BufferedReader-Äquivalent und kam (inkl. kleiner Stringverarbeitung) auf 0.038ms/Zeile, was immerhin um einen Faktor 25+ schneller ist als mein Auslesen.
Ich hoffe sehr, dass Java in Sachen Character-Verarbeitung nicht einfach nur langsam ist und einer von euch mir weiterhelfen kann. Mein guter Freund Google sagt mir seit gestern, dass es (außer Frameworks von Apache z.B.) keine besseren Ansätze gibt zum zeilenweisen Auslesen als den BufferedReader.
Grüße
miffi
Zuletzt bearbeitet von einem Moderator: