Datei-Streaming in Java

8

Ich entwickle derzeit 3D-Grafik-Anwendungen mit JOGL (Java OpenGL-Bindung). Kurz gesagt, ich habe eine riesige Querformat-Binärdatei. Aufgrund seiner Größe muss ich in der Laufzeit Geländebrocken streamen. Daher sehen wir explizit die Random Access Sorge. Ich habe bereits die erste (und schmutzige :)) Implementierung abgeschlossen (vielleicht ist es Multithread), wo ich einen dummen Ansatz verwende ... Hier ist die Initialisierung davon:

%Vor%

Und wenn ich einen speziellen Chunk lesen (streamen) muss (ich weiß bereits, dass er "Offset" in der Datei hat), mache ich folgendes (Schande über mich:)):

%Vor%

Da ich wenig Erfahrung hatte, war das das Erste woran ich denken konnte :) So, bis jetzt habe ich 3 nützliche und ziemlich interessante Artikel gelesen (ich empfehle Ihnen, sie zu lesen, vielleicht, wenn Sie an diesem Thema interessiert sind)

  1. Byte-Puffer und Nicht-Heap-Speicher - Herr Gregory scheint in Java NIO lesen zu können.

  2. Java-Tipp: Wie man Dateien schnell liest [http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly] - Das ist ein interessanter Benchmark.

  3. Artikel: Optimieren der Java I / O-Leistung [http://java.sun.com/developer/technicalArticles/Programming/PerfTuning/] - Einfache Sun-Empfehlungen, aber bitte scrollen Sie nach unten und schauen Sie sich dort den Abschnitt "Random Access" an. Sie zeigen eine einfache Implementierung von RandomAccessFile (RAF) mit Selbstpufferung.

Herr. Gregory stellt am Ende seines Artikels mehrere * .java-Dateien zur Verfügung. Einer von ihnen ist ein Benchmarking zwischen FileChannel + ByteBuffer + Mapping (FBM) und RAF. Er sagt, dass er 4x Beschleunigung bei der Verwendung von FBM im Vergleich zu RAF bemerkt. Ich habe diesen Benchmark unter folgenden Bedingungen ausgeführt:

  1. Der Offset (z. B. Ort des Zugriffs) wird zufällig generiert (im Dateibereich, z. B. 0 - file.length ());
  2. Die Dateigröße beträgt 220 MB;
  3. 1 000 000 Zugriffe (75% Lese- und 25% Schreibvorgänge)

Die Ergebnisse waren umwerfend:

~ 28 Sekunden für RAF! ~ 0,2 Sek. für FBM!

Allerdings hat seine Implementierung von RAF in diesem Benchmark keine Selbstpufferung (der dritte Artikel erzählt von einem), also denke ich, es ist die Methode "RandomAccessFile.seek", die die Leistung so stark fallen lässt.

Ok, jetzt nach all den Dingen, die ich gelernt habe, gibt es 1 Frage und 1 Dilemma:)

Frage : Wenn wir eine Datei mit "FileChannel.map" zuordnen, kopiert Java den gesamten Dateiinhalt in den "MappedByteBuffer"? Oder emuliert es es einfach? Wenn es kopiert, dann ist die Verwendung von FBM Ansatz für meine Situation nicht geeignet, oder?

Dilemma : Hängt von deinen Antworten auf die Frage ab ...

  1. Wenn das Mappen eine Datei kopiert, dann scheint es, als hätte ich nur zwei mögliche Lösungen: RAF + selbst-puffernd (die aus dem dritten Artikel) oder make Verwendung der Position in FileChannel (nicht mit Mapping) ... Welches wäre besser?

  2. Wenn das Mapping keine Datei kopiert, habe ich 3 Optionen: zwei vorherige und FBM selbst .

Bearbeiten : Hier ist noch eine Frage. Einige von Ihnen sagen, dass das Mappen nicht in MappedByteBuffer kopiert wird. Ok, warum kann ich dann nicht 1GB-Datei zuordnen, dann bekomme ich "Meldung fehlgeschlagen" ...

P. S. Ich möchte eine erfüllte Antwort mit Ratschlägen erhalten, da ich die konsistenten Informationen zu diesem Thema im Internet nicht finden kann.

Danke:)

    
Alexander Shukaev 18.01.2011, 20:11
quelle

3 Antworten

3

Nein, die Daten sind nicht gepuffert. Ein MappedByteBuffer referenziert die Daten mit einem Zeiger . Mit anderen Worten, die Daten werden nicht kopiert, sie werden einfach in den physischen Speicher gemappt . Weitere Informationen finden Sie in der API-Dokumentation , falls Sie dies noch nicht getan haben.

>
  

Eine speicherabgebildete Datei ist ein Segment von   virtueller Speicher, der zugewiesen wurde   eine direkte Byte-für-Byte-Korrelation   mit einem Teil einer Datei oder   dateiähnliche Ressource. Diese Ressource ist   in der Regel eine Datei, die physisch ist   vorhanden auf der Festplatte, kann aber auch ein sein   Gerät, Shared-Memory-Objekt oder anderes   Ressource, die das Betriebssystem kann   Referenz über einen Dateideskriptor.   Sobald diese Korrelation besteht   die Datei und der Speicherplatz erlauben   Anwendungen zum Behandeln der Karte   Teil als wäre es der primäre Speicher.

Quelle: Wikipedia

Wenn Sie Daten sehr häufig lesen, ist es eine gute Idee, zumindest etwas davon zu speichern.

    
someguy 18.01.2011, 21:15
quelle
2

Für eine 220 MB große Datei würde ich das Ganze in den virtuellen Speicher ablegen. Der Grund, warum FBM so schnell ist, ist, dass er die Daten nicht wirklich in den Speicher liest, sondern nur zur Verfügung stellt.

Hinweis: Wenn Sie den Test ausführen, müssen Sie Vergleiche durchführen, d. h. wenn sich die Datei im Betriebssystem-Cache befindet, wird sie viel schneller sein, egal wie Sie es tun. Sie müssen den Test mehrmals wiederholen, um ein reproduzierbares Ergebnis zu erhalten.

    
Peter Lawrey 18.01.2011 20:35
quelle
1

Haben Sie bemerkt, dass wenn Sie ein Programm ausführen, dann schließen Sie es, und führen Sie es erneut aus es startet das zweite Mal viel schneller? Dies geschieht, weil das Betriebssystem die Teile der Dateien zwischengespeichert hat, auf die beim ersten Durchlauf zugegriffen wurde, und nicht auf den Datenträger für sie zugreifen muss. Die Speicherzuordnung einer Datei ermöglicht im Wesentlichen einen Programmzugriff auf diese Puffer, wodurch Kopien, die beim Lesen gemacht werden, minimiert werden. Beachten Sie, dass die Speicherzuordnung einer Datei nicht dazu führt, dass sie vollständig im Speicher gelesen wird. Die gelesenen Teile werden von der Festplatte bei Bedarf gelesen. Wenn das Betriebssystem feststellt, dass wenig Speicher vorhanden ist, kann es beschließen, einige Teile der zugeordneten Datei aus dem Speicher freizugeben und sie auf der Festplatte zu belassen.

Bearbeiten: Was Sie wollen, ist FileInputStream.getChannel (). map (), dann passen Sie das an einen InputStream an, dann verbinden Sie das mit dem DataInputStream.

    
Tassos Bassoukos 19.01.2011 22:02
quelle

Tags und Links