Input/Output NIO: Block-Move

Bernd Hohmann

Top Contributor
Ich hab hier ein RandomAccessFile, was serialisierte Datenblöcke unterschiedlicher Grösse (zwischen 1KB und 100MB) enthält. Jetzt soll das File reorganisiert - also gelöschte Blöcke entfernt - werden.

Also von vorne nach hinten durch eine Liste mit den Blöcken gehen, Datenblock lesen und weiter vorne wieder wegschreiben.

Funktioniert mit normalem IO ganz gut, ich hab das jetzt nach NIO umgeschrieben und es ist auch schon etwas schneller geworden.

Was mich an der derzeitigen Programmierung stört ist das ständige Neuanlegen des ByteBuffers. Konstante Buffergrösse geht leider nicht weil die Chunks unterschiedliche Grösse haben. Nur einen Teil eines grösseren Buffers zu nutzen hab ich nicht gefunden.

Kann man die Datei nicht komplett in den Speicher mappen und dann die MMU die Arbeit erledigen lassen? channel.transferTo/transferFrom geht anscheinend nur wenn unterschiedliche Channels genutzt werden.

Oder irgendeine andere Idee?

Hier das Stückchen Code:

Java:
		FileChannel fc = rafCache.getChannel();
		ArrayList<Chunk> lstNew = new ArrayList<Chunk>();
		long lngNewOffset = 0;
		int size = lstChunk.size();
		for (int i = 0; i < size; i++) {
			Chunk c = lstChunk.get(i);
			if (c.intIdx == -1) continue; // empty chunk

			// read chunk
			ByteBuffer bb = ByteBuffer.allocateDirect(c.intSize);
			fc.read(bb, c.lngOffset);

			// create new chunk entry
			[...]
			n.lngOffset = lngNewOffset;

			// write chunk back
			bb.flip();
			fc.position(n.lngOffset);
			while (bb.hasRemaining())
				fc.write(bb);

			lngNewOffset = lngNewOffset + c.intSize;
		}

Bernd
 

Bernd Hohmann

Top Contributor
Ja, den MappedByteBuffer hab ich mir angeschaut und nach durchlesen aller Dokus das so verstanden:

1) FileChannel vom RandomAccessFile geben lassen,

2) MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE,0, lngFileLength) um das gesamte File ins VM zu Mappen

3) mbb.position(wo_soll_gelesen_werden)

4) mbb.get(buffer,0,chunk_length)

5) mbb.flip();

6) mbb.position(wo_soll_geschrieben werden)

7) mbb.put(buffer,0,chunk_length)

NUR: mbb.position(int) statt (long), damit hab ich ein 2GB Limit - irgendwas stimmt da nicht.

Bernd
 

Bernd Hohmann

Top Contributor
Nur überflogen, aber...

Jo, das mit dem ".limit(...)" war es. Statt beim read/write die anzahl der Bytes anzugeben setzt man das interne Limit des Buffers vorher. Wenn man es weiss, eigentlich eine schöne Konstruktion.

In wie weit das natürlich intern irgendwelche Bottlenecks und zusätzliche Pagefaults erzeugt ist kaum feststellbar.

Bernd
 

Noctarius

Top Contributor
[c]allocateDirect[/c] ist nur schneller wenn man auf external Memory weiterarbeitet. Da aber der Kram über HeapBuffer verarbeitet wird muss alles hin und her kopiert werden. Bei SocketChannels wäre der DirectBuffer schneller :D
 

Bernd Hohmann

Top Contributor
[c]allocateDirect[/c] ist nur schneller wenn man auf external Memory weiterarbeitet

Sagmal: wird der ByteBufer im Virtuellen Adressraum abgebildet sodass ich einen Buffer allokieren könnte der grösser als der freie Speicher ist?

Mir ist aufgefallen, dass es bei der Reorganisation immer mehrere zusammenhängende Blöcke gibt die ich zusammen verschieben könnte und frage mich, was ich als Limit nehmen soll (gerade auf 32bit Maschinen mit wenig RAM).

Bernd
 

Noctarius

Top Contributor
Mit DirectByteBuffern / HeapByteBuffern geht das nicht:
Diese werden im vorher definierten Heap bzw im RAM neben der JVM initialisiert. Generell natürlich mit virtuellen Speicheradressen (diese nutzt ja das OS) aber müssen in den verfügbaren Speicher passen.

Mit Mapped Files geht das:
Generell kannst du mehr Speicher mappen als der Rechner hat (wie du bereits sagst, es ist nur der virtuelle Adressraum), allerdings ist auf 32Bit Betriebssystemen der virtuelle Speicherbereich für Anwendungen irgendwo bei 3,x GB zuende. Die 4GB pro Prozess erreicht man nicht ganz. Auf 64Bit Betriebssystemen und einer 32Bit Anwendung gilt dieses Problem auch noch, erst mit einer 64Bit Anwendung hast du da keine Probleme mehr.
Über MemoryMapped Files kannst du theoretisch Terrabyte an "Anwendungsspeicher" zur Verfügung stellen (das machen OS ja auch mit dem Auslagerungs- / Swapspeicher).
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
R Größter zusammenhängender Block gleicher Zeichen im String Java Basics - Anfänger-Themen 1
J In der Ausgabe wird ohne Eingabe in den else Block gesprungen. Java Basics - Anfänger-Themen 0
J In der Ausgabe wird ohne Eingabe in den else Block gesprungen. Java Basics - Anfänger-Themen 5
D try/catch-Block bei for-Schleife Java Basics - Anfänger-Themen 14
Zwanglos Warum wird nur die erste Zeile im while Block ausgeführt? Java Basics - Anfänger-Themen 8
B Try-Catch Block Java Basics - Anfänger-Themen 3
F Mehrere Exceptions in einem Catch-Block abfangen Java Basics - Anfänger-Themen 12
E Synchronisierte Methoden vs. Synchronized(lockObject) Block Java Basics - Anfänger-Themen 7
A break; mit Einfluss hinter else if Block Java Basics - Anfänger-Themen 3
tsom Erste Schritte itext Text als Block auf neue Seite Java Basics - Anfänger-Themen 0
J Code in Try-Catch Block wird nicht komplett ausgeführt Java Basics - Anfänger-Themen 5
A Nicht zu findender Fehler in einem try/catch Block Java Basics - Anfänger-Themen 6
E Buchstaben verhindern / Try & Catch Block Java Basics - Anfänger-Themen 3
D if block mit equals im rumpf Java Basics - Anfänger-Themen 11
L Warum ist der catch-Block nicht erreichbar ? Java Basics - Anfänger-Themen 8
T Threads Join() = Block? oO Java Basics - Anfänger-Themen 4
B Classpath static block - Verwirrung Java Basics - Anfänger-Themen 2
J Methoden Wert im Block einer for-Schleife wird nicht aktualisiert Java Basics - Anfänger-Themen 9
J Grosses einmaleins 5er Block Ausgabe Java Basics - Anfänger-Themen 3
S Schlüsselworte Thread Block sprerren Java Basics - Anfänger-Themen 8
H .class und static Block ? Java Basics - Anfänger-Themen 4
N Catch Block in Try erzwingen Java Basics - Anfänger-Themen 14
E Problem mit for schleife/ try-catch block Java Basics - Anfänger-Themen 7
S if-Block dynamisch aufbauen Java Basics - Anfänger-Themen 5
N try and catch block in finally Java Basics - Anfänger-Themen 8
H Finalize Block blockiert Programmablauf Java Basics - Anfänger-Themen 15
A Datentypen problem return aus try-block Java Basics - Anfänger-Themen 4
D Scanner hasNext(Line)() Block Problematik... Java Basics - Anfänger-Themen 6
B Exception vor catch Block definieren Java Basics - Anfänger-Themen 9
V Was ist ein Try-Catch Block Java Basics - Anfänger-Themen 4
Z Applet mit einem beweglichem Block Java Basics - Anfänger-Themen 7
G static block und konstanten Java Basics - Anfänger-Themen 2
R wait() in synchronized - Block oder nicht? Java Basics - Anfänger-Themen 4
G Verschiedene Exceptions zu gleichem Block Java Basics - Anfänger-Themen 6
G InputStream im finally-Block schließen Java Basics - Anfänger-Themen 7
F reiner Code-Block Java Basics - Anfänger-Themen 6
G If-Block und String Java Basics - Anfänger-Themen 3
M Exception->mehrere Exceptions in einem Catch Block behand Java Basics - Anfänger-Themen 4
S nio move() funktioniert nicht richtig Java Basics - Anfänger-Themen 2

Ähnliche Java Themen

Neue Themen


Oben