tutorials.de Buch-Aktion 05/2012
Like Tree1Danke
  • 1 Beitrag von Fabio Hellmann
ERLEDIGT
JA
ANTWORTEN
3
ZUGRIFFE
476
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Avatar von miffi
    miffi miffi ist offline Mitglied Gold
    Registriert seit
    Jul 2009
    Ort
    Ravensburg (BW)
    Beiträge
    139
    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:
    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
                    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);
                    }
    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:
    1. 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.
    2. Andere Streams zu verschachteln (FileInputStream => BufferedInputStream => InputStreamReader => BufferedReader) hat keinen Unterschied gemacht
    3. RandomAccessFile#readLine() dauert ebenfalls gleich lang
    4. 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).
    5. 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
    Geändert von miffi (30.11.11 um 13:13 Uhr)
     
    "A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools."
    Douglas Adams

  2. #2
    Avatar von Fabio Hellmann
    Fabio Hellmann Fabio Hellmann ist gerade online Mitglied Brokat
    Registriert seit
    Aug 2011
    Ort
    München
    Beiträge
    494
    Hi,
    also ich habe auch die Zeit vom BufferedReader gestoppt und komme auf weniger.
    Ersteinmal meine PC-Daten:
    CPU: Intel Core 2 Duo 2,80 GHz
    RAM: 2GB

    Ich komme bei einem Textdatei mit einer Größe von 445MB auf eine Lesegeschwindigkeit von 0,0027 ms/Line. Die Textdatei enthält 5millionen Zeilen. Für die gesamte Textdatei benötige ich eine Zeit von 13500ms oder anders 13,5sec.

    Hier mein Code mit dem ich getestet habe.
    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new InputStreamReader(new FileInputStream(new File("./Tests/bigfile.txt"))));
                String line;
                StopWatch sw = new StopWatch();
                sw.start();
                int lineCounter = 0;
                while((line = reader.readLine()) != null) {
                    lineCounter++;
                }
                sw.stop();
                System.out.println("NeededTime=" + sw.getTime() + ", Lines="+lineCounter+", ms/Line="+((double)sw.getTime()/(double)lineCounter));
            } catch(FileNotFoundException e) {
                e.printStackTrace();
            } catch(IOException e) {
                e.printStackTrace();
            } finally {
                IOUtils.closeQuietly(reader);
            }
        }

    Du solltest bei deinem Code darauf achten, bei einer Zeitmessung kein Thread.sleep(...) einzubauen. Das ist dann klar, dass wen du den Thread für 1msec schlafen legst, dass er dann pro Zeile ca. 1msec braucht.
    Außerdem verlangsamt eine Ausgabe die Zeitmessung zusätzlich, genauso wie sonstige Berechnung, Bedingungen, etc.

    Gruß

    Fabio
    miffi bedankt sich. 
    Bitte die Code-Tags verwenden. Bei Java-Code: [java]...[/java]

    Tutorials:
    Automatisches erzeugen eines Inhaltsverzeichnisses (Javascript)
    JAnimationPanel - Animationen für Swing/AWT
    SWTRatingBar (Bewertungs-Composite) selbst programmieren
    ____________________________________________________________________________
    Über eine Bewertung (Stern links unter dem Beitrag) oder ein Danke freue ich mich sehr.

  3. #3
    Avatar von miffi
    miffi miffi ist offline Mitglied Gold
    Registriert seit
    Jul 2009
    Ort
    Ravensburg (BW)
    Beiträge
    139
    Hi Fabio, danke für die schnelle Antwort!

    Der sleep()-call war ein Relikt aus einer anderer Schleife, die ich an dieser Stelle hatte. Und vor lauter Betriebsblindheit hab ich es total übersehen...
    Ich geh jetzt in 6.7s über 6.2 Mio Zeilen Text, von daher ist alles in Ordnung. Weißt, da programmiert man seit Jahren professionell, und dann passiert einem so ein Erstsemester-Kram xD
    Wär ja direkt lustig, wenn nicht 8 wichtige Arbeitsstunden für die Forschung nach Alternativen draufgegangen wären...

    Danke dir und Gruß
    miffi
     
    "A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools."
    Douglas Adams

  4. #4
    Avatar von Fabio Hellmann
    Fabio Hellmann Fabio Hellmann ist gerade online Mitglied Brokat
    Registriert seit
    Aug 2011
    Ort
    München
    Beiträge
    494
    Keine Ursache. Oft hilft auch gelegentlich eine kurze Pause von 5 Minuten, um seine Blindheit zu überwinden.
    Aber ich kenn das auch, die kleinsten Fehler sucht man prinzipell immer am längsten.

    Gruß

    Fabio
     
    Bitte die Code-Tags verwenden. Bei Java-Code: [java]...[/java]

    Tutorials:
    Automatisches erzeugen eines Inhaltsverzeichnisses (Javascript)
    JAnimationPanel - Animationen für Swing/AWT
    SWTRatingBar (Bewertungs-Composite) selbst programmieren
    ____________________________________________________________________________
    Über eine Bewertung (Stern links unter dem Beitrag) oder ein Danke freue ich mich sehr.

Ähnliche Themen

  1. BufferedReader
    Von mal2000b im Forum Java
    Antworten: 2
    Letzter Beitrag: 05.02.10, 20:59
  2. BufferedReader Limit?
    Von Conners im Forum Java
    Antworten: 2
    Letzter Beitrag: 22.10.08, 09:07
  3. BufferedReader
    Von steffias im Forum Java Grundlagen
    Antworten: 2
    Letzter Beitrag: 04.05.08, 22:17
  4. BufferedReader
    Von Kenbu im Forum Swing, Java2D/3D, SWT, JFace
    Antworten: 2
    Letzter Beitrag: 22.08.07, 16:59
  5. Label / Emblem um einen Flaschenhals wickeln...
    Von tobsnn im Forum Cinema 4D
    Antworten: 9
    Letzter Beitrag: 17.02.05, 16:11