Java: der Schnellste Weg, das zu tun, random reads auf den riesigen Festplatten-Datei(en)
Habe ich eine mäßig große Menge von Daten, über 800 MB oder so, das ist im Grunde einige große vorausberechnete Tabelle, die ich brauche, um die Geschwindigkeit um etwa die Berechnung von mehreren Größenordnungen (das erstellen dieser Datei dauerte mehrere mutlicores Computern Tagen zu produzieren, mit einem optimierten und multi-threaded-algo... ich Mach wirklich müssen, dass-Datei).
Nun, es wurde einmal berechnet, dass 800 MB Daten nur Lesen.
Kann ich nicht halten Sie in Erinnerung.
Ab jetzt ist es eine riesig große 800MB-Datei, sondern aufteilen in kleinere Dateien ist nicht ein problem, wenn es helfen kann.
Ich Lesen müssen, über 32-bit-Daten hier und da in dieser Datei eine Menge Zeit. Ich weiß nicht, bevor die hand, wo werde ich brauchen, um Lesen Sie diese Daten ein: das liest sich gleichmäßig verteilt.
Was wäre der Schnellste Weg in Java zu tun, meine random liest in einer Datei oder Dateien? Idealerweise sollte ich tun, diese liest aus mehreren voneinander unabhängigen threads (aber ich könnte Warteschlange der liest in einem einzigen thread, falls erforderlich).
Ist Java NIO der Weg zu gehen?
Ich bin nicht vertraut mit 'memory-mapped file': ich denke, ich will keine Karte die 800 MB im Speicher.
Alles was ich will ist die Schnellste zufällig liest, die ich bekommen kann, um Zugriff auf diese 800 MB disk-basierte Daten.
btw falls Leute Fragen, das ist nicht das gleiche, wie die Frage, die ich vor nicht langer Zeit:
Java: schnelle disk-basierte hash-set
- Gibt es keine Möglichkeit zu werfen, dass die Daten in eine Datenbank, die exakt optimiert, das zu tun diese Art von Sachen?
- Ich bin vorausgesetzt, es ist bereits sortiert-und Sie tun binäre [oder interpolation] Suche Sie es mit der rechten? Auch, wenn möglich, Sie könnte schieben Sie es in eine DB, die ist optimiert für die Abfrage von großen Datenmengen, perf. viel besser sein wird.
- Warum können Sie nicht setzen alles in den Speicher? Den Kauf von mehr Speicher wird wahrscheinlich viel billiger sein, als code zu schreiben um die situation zu verbessern - und es hat den Vorteil, so dass Sie mehr Speicher für andere Dinge auch... 800 MB ist wirklich nicht viel Speicher in diesen Tagen.
- Sie möchten die Geschwindigkeit Ihres random-access-um eine Größenordnung. Holen Sie mehr RAM, wie Jon sagt, oder wenn nicht möglich, verwenden Sie ein solid-state-Laufwerk.
- Skeet und JRL: leider ist dies für etwas, das bereitgestellt wird, auf eine Menge von Maschinen...
- Und solche Maschinen sind alle Massiv short Speicher? Würden Sie nicht profitieren, im Allgemeinen? Im ernst, mehr Speicher wird wahrscheinlich geben Ihnen die beste bang für die buck im Allgemeinen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
800 MB ist nicht sehr viel zu laden und im Speicher speichern. Wenn Sie sich leisten können, haben multicore-Maschinen rippen entfernt an ein Daten-set für Tage am Ende, die Sie sich leisten können, ein extra-GB-oder zwei RAM, nicht?
Sagte, Lesen Sie auf der Java -java.nio.MappedByteBuffer. Es ist klar aus deinem Kommentar "ich denke, ich will keine Karte die 800 MB im Speicher", dass das Konzept nicht klar.
In einer Mutter-shell, ein zugeordnetes byte-Puffer ermöglicht einen programmgesteuerten Zugriff auf die Daten wie im Speicher, obwohl es vielleicht auf der Festplatte oder im Arbeitsspeicher--das ist für das OS zu entscheiden, wie Java MBB basiert auf dem Betriebssystem Virtuellen Speicher-subsystem. Es ist auch schön und schnell. Sie werden auch in der Lage sein, um Zugriff auf eine einzige MBB aus mehreren threads sicher.
Hier sind die Schritte, die ich empfehlen, dass Sie:
byte[4]
array.get(byte[] dst, int offset, int length)
Und presto! Sie haben Ihre Daten!
Ich bin ein großer fan von Baby wird von einem und habe Sie erfolgreich für solche Aufgaben in der Vergangenheit.
RandomAccessFile (Blockierung) kann helfen: http://java.sun.com/javase/6/docs/api/java/io/RandomAccessFile.html
Können Sie auch
FileChannel.map()
auf der Karte eine region der Datei in den Speicher, dann Lesen Sie dieMappedByteBuffer
.Siehe auch: http://java.sun.com/docs/books/tutorial/essential/io/rafs.html
Eigentlich 800 MB ist nicht sehr groß. Wenn Sie 2 GB Speicher oder mehr, Sie können sich im disk-cache, wenn nicht in Ihrer Anwendung selbst.
Für den write-Fall, auf Java 7, AsynchronousFileChannel angeschaut werden soll.
Bei der Durchführung zufälligen Datensatz-orientiert schreibt bei großen Dateien (größer als Physischer Speicher für die Zwischenspeicherung ist nicht zu helfen alles) auf NTFS, ich finde, dass AsynchronousFileChannel führt mehr als doppelt so viele Operationen in single-threaded-Modus, im Vergleich zu einem normalen FileChannel (auf einer 10GB-Datei, 160-byte-records, völlig zufällig schreibt, einige zufällige Inhalt, mehrere hundert Iterationen des benchmarking-Schleife zu erreichen steady-state ungefähr 5,300 Schreibvorgänge pro Sekunde).
Meine beste Vermutung ist, dass da die asynchrone io läuft darauf hinaus, überlappende E /a in Windows 7 die NTFS-Datei-system-Treiber zu aktualisieren können Sie Ihre eigene interne Strukturen schneller, wenn Sie nicht haben, um erstellen Sie einen sync-Punkt nach jedem Aufruf.
Ich micro-Benchmarks gegen RandomAccessFile, um zu sehen, wie Sie durchführen würde (die Ergebnisse sind sehr nah an FileChannel, und immer noch die Hälfte der Leistung von AsynchronousFileChannel.
Nicht sicher, was passiert mit multi-Thread schreibt. Dies ist auf Java 7 auf einer SSD (die SSD ist eine Größenordnung schneller als magnetische und andere Größenordnung schneller auf kleinere Dateien, die in den Speicher passt).
Wird interessant sein zu sehen, ob die gleichen Verhältnisse halt auf Linux.