Processing von sehr großen Textdateien

Wen ndu kein GUI-Zeugs benutzt kannst du evtl. sogar in java coden und das mit GCJ nativ kompilieren lassen.
@Avatar ich möchte keine Flamewar anzetteln oder sonst irgendwas. Meiner Erfahrung nach ist Java einfach vielerorts bequemer als C++ (wobei das vom Framework abhängt) und letzteres je nach Einsatzgebiet den Performancevorteil oft nicht wert.
Mit Qt kann man z.B. auch in C++ sehr schön arbeiten. (Plattformunabhängig)
Ich meine nur, wenn die Performance von VM-basierten Sprachen derart schlimm wäre, würden nicht SAP, Oracle usw. so breit auf Java setzen und .Net-basierte Software in der Windowswelt aus dem Boden schießen wie Pilze...
Die CLR ist auch nicht so viel anders als die JVM...
Mit IKVM gibt es sogar Cross-Compiler... *noahnung*
Am besten ist er codet mit dem was ihm am meisten liegt. Sonst macht die Fehlersuche am Ende den Performancevorteil zunichte.
 
Eigentlich wollt ich den Thread-Ersteller nur vor dem sicheren Abgrund bewahren(und keine Grundsatzdiskussionen führen), weil IO Operation im Verhältnis sehr langsam sind. Sorry ich sag´s ehrlich, niemand käme auf die Idee einzelne Dateien mit 80GB, 500GB oder gar 1TB Umfang bereinigen zu wollen.

Selbst die Datenbank würde bei native Datenbankausführung auf der gesamten Datenmenge (select und replace) aus dem letzten Loch preifen lach.
 
Da möchte ich auch gar nicht widersprechen. Ich habe die Aufgabenstellung halt mal als gegeben hingenommen und hatte zuerst den Eindruck, das sei mehr ein kurzzeitiges oder Migrationsprojekt.

Mir ging es nur darum, dass man hier (meines Wissens nach) durch die Sprache in Sachen Laufzeit keine großartigen Unterschiede bekommt (intelligente Implementierung vorausgesetzt).
Und das diese "intelligente Implementierung" mit Java afair am schnellsten erreicht ist.

Naja, bin mal gespannt, ob er sich nochmal zu Wort meldet!? Neugierig auf News bin ich jetzt irgendwie schon.
 
Servus, hatte heute langeweile und hab mich der Sache mal angenommen.
Ich hab ne Textdatei .txt mit 100.000 Zeilen a 20 Zahlen. Dazu hab ich jeweils ne Version in C mit FILE und char *
Java mit BufferedReader und StringTokenizer
C++ mit split (QT).

Die Ergebnisse sind schon mal beindruckend.

einfach einlesen, d.h durch die Datei iterieren:
C++ : 33ms, ifstream
Java: 142ms, BufferedReader
C : 18ms, FILE * und gets(..)

Alle Daten in die Liste als string bzw. (char *):
C++ : 80ms, ifstream und list<string>
Java: 151ms, BufferedReader und ArrayList<byte[]>
C : 29ms, FILE *, gets(..) und list<char *>

Alle Daten in Liste packen als byte[] bzw (char *):
C++ : 170ms, ifstream, list<string> und QString.split(..)
Java: 389ms, BufferedReader, ArrayList<byte[]> und StringTokenizer
C : 40ms, FILE, list<char *> und strtok(..)

Auf Optimierung wie O2 oder O3 hab ich verzichtet, da wär das Ergebnis noch beeindruckender :))

Java6 und GCC 4.2 auf OSX 10.6
 
Hallo,
da melde ich mich mal wieder. Also es wurde schon richtig gemunkelt, es ist in etwa eine quick'n'dirty Lösung, die eine Weile funktionieren soll. Bisher klappt das alles super. Um ehrlich zu sein kann ich gerade nicht sagen, was ich genau genommen hatte. Ich weiß aber noch es war FileChannel mit einem Buffer. Ich hatte damals einen Test vieler möglicher Kombinationen (mit ohne Buffer, io, nio usw.) gesehen und da war das fast mit die optimalste Lösung. Wenn ich demnächst mal wieder Zugriff auf den Source habe, werde ich mich nochmal melden und bisschen Code posten.

Bzgl. des Codings muss ich auch schon vorweg nehmen, ich bin kein typischer Informatiker/Coder. Ich habe Plan von der Materie und verstehe das meiste was man wirklich braucht, aber mein Codingstyle ist mangels Übung wohl etwas diletantisch ;) Als Wirtschaftsinformatiker von einer Wirtschaftsfakultät ist das aber auch nicht verwunderlich. ;D

@Avatar:
Deine Tests zeigen eins: Man kann mit Optimierung und der richtigen Sprache viel rausholen. Bei mir zählten aber auch andere Sachen:
1. Die Usability der Sprache, sowohl für mich als auch für andere zum Einarbeiten. Und allein schon javadoc ist einfach genial zum Einarbeiten in Code. Natürlich muss das im Verhältnis zu den anderen Eigenschaften stehen (wie gesagt, Laufzeit ist nicht das Kriterium #1, aber dennoch zu betrachten. Wir reden über <24h bei 1 TeraByte auf einem größeren Server... also auch mit Java zu schaffen )
2. Schnelle Implementierung (ok liegt auch an den Skills des Coders ;) )
3. Plattformunabhängigkeit (32/64bit von Linux bis Windows, größtenteils wohl x86) bzw. kein Portierungsaufwand

Alles in allem hat Java da eben einen Megavorteil v.a. bei 3.

Also bis dahin, wenn ich den Link zu den Performance Tests von io und nio gefunden hab und wieder an meinen Code kann.

Grüße
pm
 
http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly#Conclusions

Leider funktioniert der Link zu dem Artikel nicht mehr, war in Bezug auf Java und schnell Lesen recht aufschlussreich. Deswegen hatte ich meine Kombination gewählt. (Glaube ich aber noch in einer einfacheren Variante, aber zumindest java.nio.*)

Jedenfalls hier mal der Code vom Lesen / Schreiben der Daten:
http://pastebin.com/Mjf1nrXX (Der Link gilt für 30 Tage)

Und nun: macht mich fertig, schaut sicherlich scheußlich durcheinander/dilettantisch/verschwenderisch aus ;D
 
Naja Unicode-File als Stream zu verarbeiten ist natürlich auch komplexer als Reader zu benutzen.
Das würde den Code hier voll vereinfachen.
Was hier richtig bremst ist, dass du für jedes neue Zeichen einen String konkatenisert(also jedes Mal ein neuen String erzeugst), da kannste mit StringBuffer ne Menge Performance rausholen.

Die Grundidee war doch die Zeilen auszulesen und das Raute Zeichen darin zu entfernen und ggf. die Zeichenkodierung zu ändern?
 
Hui, da is ja richtig was passiert in der Zwischenzeit.

@perpetuum.mobile
Beim Überfliegen habe ich mich über die Methode setLinebreakEncodingProcess() gewundert: "\r" ist Carriage Return, "\n" ist Linefeed.

@Avatar
Deine Messergebnisse überraschen mich, habe aber noch keine Zeit gefunden, eigene Messungen zu machen. :-/
Eine Test auf einem anderen OS wäre aber noch aufschlussreich. Ich könnte mir vorstellen, dass die JRE auf OS X noch so ihre Tücken hat.
(ich könnte einen Linux-Test beisteuern, falls du den Quellcode rausrückst)
 
Klar,
der Java-Code : http://pastebin.com/KJdMZfau
Jetzt fehlt noch die 5.2 MB Text-Datei mit 100.000 Zeilen. Kannst mir ja mal deine Email senden.

Wir können auch gern mal n paar andere Benches machen, weil Java hier durch die IO-Limitierung gerettet wird, so dass
C/C++ hier nur um den Faktor 2-5(10) besser abschneidet ^^
 
Zuletzt bearbeitet:
Naja Unicode-File als Stream zu verarbeiten ist natürlich auch komplexer als Reader zu benutzen.
Das würde den Code hier voll vereinfachen.
Was hier richtig bremst ist, dass du für jedes neue Zeichen einen String konkatenisert(also jedes Mal ein neuen String erzeugst), da kannste mit StringBuffer ne Menge Performance rausholen.

Die Grundidee war doch die Zeilen auszulesen und das Raute Zeichen darin zu entfernen und ggf. die Zeichenkodierung zu ändern?

Danke für den Tipp, das stimmt. Ich hab mir ab dem Zeitpunkt, ab dem das halbwegs gut funktioniert hat, keine weiteren Gedanken um Performance gemacht. Die Grundidee hast du teilweise erfasst. Die ausgelesene Zeile soll dann in ein Array überführt werden, etwas bearbeitet und dann wieder geschrieben werden.

Hui, da is ja richtig was passiert in der Zwischenzeit.

@perpetuum.mobile
Beim Überfliegen habe ich mich über die Methode setLinebreakEncodingProcess() gewundert: "\r" ist Carriage Return, "\n" ist Linefeed.
...

Das Problem ist, die Daten können auf einem Windows (\r\n) und einem Linux (\n) System entstanden sein können. Je nach Systemsetting dort ists halt mal der eine oder andere Zeilenumbruch. QuellSystem muss nicht gleich Zielsystem (dort wo dekodiert wird) sein. Daher muss das auch gesetzt werden. Die Einstellungen kommen von der GUI.

Klar,
der Java-Code : http://pastebin.com/KJdMZfau
Jetzt fehlt noch die 5.2 MB Text-Datei mit 100.000 Zeilen. Kannst mir ja mal deine Email senden.

Wir können auch gern mal n paar andere Benches machen, weil Java hier durch die IO-Limitierung gerettet wird, so dass
C/C++ hier nur um den Faktor 2-5(10) besser abschneidet ^^

Bitte vergesst nicht, dass die Datenmengen von denen ich rede wesentlich größer sind. Also auch locker mal 100 MB / 1 GB oder so.
 
Zurück
Oben Unten