Schnelle Möglichkeit, Millionen kleiner Textdateien in Java zu schreiben?

8

Ich muss 6 Millionen Dateien ablegen, die ungefähr 100-200 Zeichen enthalten, und es ist schmerzhaft langsam. Der eigentliche langsame Teil ist das Schreiben der Datei, wenn ich diesen Teil kommentiere (der Aufruf der WriteSoveraFile-Methode), läuft das Ganze in 5-10 Minuten ab. So lief es über Nacht (16 Stunden) und wurde mit 2 Millionen Platten erledigt.

  1. Gibt es eine schnellere Methode?

  2. Wäre es besser, ein Array von Arrays zu erstellen und dann alles auf einmal zu speichern? (Mein System hat nur 4 GB, würde es nicht an den 6 GB Daten sterben, die dadurch verbraucht werden?)

Hier ist die Vorgehensweise:

%Vor%     
Rob 06.12.2013, 14:18
quelle

4 Antworten

3

Dies ist mit ziemlicher Sicherheit ein OS-Dateisystemproblem; viele Dateien zu schreiben ist einfach langsam. Ich empfehle einen Vergleichstest in der Shell und in C zu schreiben, um eine Vorstellung davon zu bekommen, wie viel das Betriebssystem beiträgt. Zusätzlich würde ich zwei wichtige Verbesserungen vorschlagen:

  • Stellen Sie sicher, dass das System, auf dem es ausgeführt wird, eine SSD verwendet. Die Latenzzeit beim Suchen nach Dateisystemjournalen ist eine Hauptquelle für Overhead.
  • Multithread Ihren Schreibprozess. Serialisiert kann das Betriebssystem keine Optimierungen wie das Schreiben von Batch-Operationen durchführen, und die FileWriter kann bei der Operation close() blockieren.

(Ich wollte vorschlagen, NIO zu betrachten, aber die APIs scheinen für Ihre Situation keinen großen Nutzen zu bieten, da das Einrichten eines mmapped-Puffers wahrscheinlich mehr Overhead verursachen würde, als es für diese Größe sparen würde.)

    
chrylis 06.12.2013, 14:25
quelle
4

Sie können nio package verwenden. Es ist schneller als io . Schau mal: Ссылка

Vorteile von NIO:
1. Puffer-orientiertes 2. Nicht blockierende IO

Da es nicht blockierend ist, können Sie eine Datei erstellen, Daten darauf schreiben und sie wird in einem Puffer gespeichert. Ihre Anwendung kann dann zur nächsten Datei weitergehen, Daten in den Puffer schreiben und so weiter und so fort. Das bedeutet, dass Sie nicht warten müssen, bis die Daten tatsächlich geschrieben sind, bevor Sie fortfahren.

Dadurch sparen Sie viel Zeit bei Millionen von Dateien. Also selbst wenn es dir eine viertel Sekunde spart, multipliziere es mit einer Million und mach die Mathematik =)

    
Little Child 06.12.2013 14:21
quelle
2

Wie bereits erwähnt, ist Ihr begrenzender Faktor der Speicherzugriff, nicht Ihr Code oder die JVM. Es gibt ein paar Dinge in Ihrem Code, die Code verbessert werden, aber die Änderungen würden unbemerkt bleiben, da der zugrunde liegende Engpass die Datei IO ist.

Es gibt einige Möglichkeiten, den Prozess zu beschleunigen:

  • Schreiben Sie auf ein schnelleres Laufwerk (höhere RPM-Festplatte oder eine SSD - NICHT ein USB-Laufwerk, da die USB-Kommunikation viel langsamer als SATA ist.)
  • Verwenden Sie mehrere Threads, um auf ein RAID-Laufwerk zu schreiben. Es gibt RAID-Level (kann sich nicht erinnern, welche), die gleichzeitige Schreibvorgänge unterstützen.
  • Überdenken Sie die Dateistruktur so, dass es nicht notwendig ist, 6 Millionen Dateien zu haben. Wenn sich die Dateien an einem einzigen Speicherort befinden, weiß ich nicht, warum Sie so viele kleine Dateien benötigen. Die Funktionalität könnte wahrscheinlich erreicht werden, indem eine oder zwei größere Dateien erstellt werden, die alle Daten übernehmen. Sie müssten nur das Format und die Lesekomponente ändern. Eine Datei wäre 200 Zeichen * 2 * 6 Millionen = ~ 2,4 GB (200 Zeichen bei 2 Byte / Zeichen mal 6 Millionen Dateien).
MadConan 06.12.2013 15:15
quelle
-1

Verwenden Sie keinen BufferedWriter. Verwenden Sie die write () -Methode der FileWriter-Klasse.

    
Mark Bertenshaw 06.12.2013 14:26
quelle

Tags und Links