Ich habe eine 35 GB CSV
Datei. Ich möchte jede Zeile lesen und die Zeile in eine neue CSV schreiben, wenn sie einer Bedingung entspricht.
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("source.csv"))) {
try (BufferedReader br = Files.newBufferedReader(Paths.get("target.csv"))) {
br.lines().parallel()
.filter(line -> StringUtils.isNotBlank(line)) //bit more complex in real world
.forEach(line -> {
writer.write(line + "\n");
});
}
}
Dies dauert ca. 7 Minuten. Ist es möglich, diesen Prozess noch weiter zu beschleunigen?
java
java-stream
java-io
Mitgliedssound
quelle
quelle
parallel
macht das Entfernen das schneller? Und mischt das nicht die Zeilen herum?BufferedWriter
selbst mit dem Konstruktor , mit dem Sie die Puffergröße festlegen können. Möglicherweise macht eine größere (oder kleinere) Puffergröße einen Unterschied. Ich würde versuchen, dieBufferedWriter
Puffergröße an die Puffergröße des Host-Betriebssystems anzupassen.Antworten:
Wenn dies eine Option ist, können Sie GZipInputStream / GZipOutputStream verwenden, um die Festplatten-E / A zu minimieren.
Files.newBufferedReader / Writer verwenden eine Standardpuffergröße von 8 KB, glaube ich. Sie könnten einen größeren Puffer versuchen.
Die Konvertierung in String, Unicode, verlangsamt sich auf (und verwendet den doppelten Speicher). Das verwendete UTF-8 ist nicht so einfach wie StandardCharsets.ISO_8859_1.
Am besten wäre es, wenn Sie größtenteils mit Bytes arbeiten können und diese nur für bestimmte CSV-Felder in String konvertieren.
Eine Speicherzuordnungsdatei ist möglicherweise am besten geeignet. Parallelität kann von Dateibereichen verwendet werden, die die Datei aufspucken.
Dies wird ein bisschen viel Code, der die Zeilen richtig einfügt
(byte)'\n'
, aber nicht übermäßig komplex ist.quelle
GZipInputStream + GZipOutputStream
vollständigen Speicher auf einer Ramdisk getestet . Die Leistung war viel schlechter ...MappedByteBuffer
Position aus der letzten Position, die als gut bekannt ist (FileChannel.map
dauert lange).new RandomAccessFile(…).getChannel()
. Einfach benutzenFileChannel.open(…)
.Sie können dies versuchen:
Ich denke, das spart Ihnen ein oder zwei Minuten. Der Test kann auf meinem Computer in ca. 4 Minuten durchgeführt werden, indem die Puffergröße angegeben wird.
könnte es schneller sein Versuche dies:
Dies sollte Ihnen drei oder vier Minuten sparen.
Wenn das noch nicht reicht. (Der Grund, warum Sie die Frage wahrscheinlich stellen, ist wahrscheinlich, dass Sie die Aufgabe wiederholt ausführen müssen.) wenn Sie es in einer Minute oder sogar ein paar Sekunden erledigen möchten. Dann sollten Sie die Daten verarbeiten und in db speichern und dann die Aufgabe von mehreren Servern verarbeiten.
quelle
cbuf
Inhalt bewerten und nur Teile ausschreiben? Und müsste ich den Puffer zurücksetzen, sobald er voll ist? (Dank all Ihrer Vorschläge war der schnellste Austausch mit dem Autor, mit
BufferedOutputStream
dem sich ca. 25% verbessert haben:Trotzdem ist die Leistung
BufferedReader
besser alsBufferedInputStream
in meinem Fall.quelle