Schnellstmögliches Lesen/Schreiben auf HDD ?

Status
Nicht offen für weitere Antworten.
G

Guest

Gast
Ahoi!
Ich versuche gerade so fix wie möglich ein riesiges double-Array auf die HDD zu schreiben und es von dort wieder zu rekonstruieren.

Als Kandidaten fielen mir hierfür ein: DataOutputStream und ObjectOutputStream (bzw. jeweils *Input*).
Folgender Mini-Benchmark zeigt, dass ObjectOutputStream wesentlich schneller ist. Meine Ergebnisse:

Streaming out: 10 x 1000000 doubles
dos-time : 24422
oos-time : 1203
Streaming in: 10 x 1000000 doubles
dis-time : 16344
ois-time : 1063

Allerdings schafft eine zum Vergleich in PureBasic gecodete und in Maschinencode übersetzte Version für denselben Zweck mit einiges Tricks Laufzeiten von um die 700 (streaming out) und nur 120 (streaming in), also nochmals stark beschleunigt. Auch habe ich bereits die PureBasic-gecodeten Routinen in eine DLL gepackt und dann per JNI von Java aus aufgerufen. Auch diese Variante ist immernoch (wenn auch nur noch geringfügig) schneller.

Hat also noch jemand eine Idee, wie das mit Java-eigenen Mitteln zu beschleunigen geht ? Irgendwie direkt von der Datei in den Speicher streamen, oder so ?

Der Speedcontest ist eröffnet ;-)

Danke + Guten Morgen,

kopfsalat

Hier meine Testklassen:

Die Datenhaltungs-Klasse
Code:
package serializableSpeed;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;

public class MyData implements Serializable {
	private static final long serialVersionUID = -2319633440412883951L;
	
	private double[] data;

	public void initializeByRandom(int size) {
		data = new double[size];
		
		for (int i=0; i<size; i++) {
			data[i] = Math.sin(i * 1.0 / 44100); 
		}
	}
	
	public void saveManuallyDataOutputStream(File file) throws IOException {
		FileOutputStream fos = new FileOutputStream(file);
		DataOutputStream ds = new DataOutputStream(fos);
				
		ds.writeInt(data.length);
		for (int i=0; i<data.length; i++) {
			ds.writeDouble(data[i]);
		}

		ds.flush();
		ds.close();
		fos.close();
	}
	
	public void loadManuallyDataInputStream(File file) throws IOException {
		FileInputStream fis = new FileInputStream(file);
		DataInputStream ds = new DataInputStream(fis);
				
		data = new double[ds.readInt()];
		for (int i=0; i<data.length; i++) {
			data[i] = ds.readDouble();
		}

		ds.close();
		fis.close();
	}
}

Die Datei, um den Benchmark-Test zu starten
Code:
package serializableSpeed;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class RunSpeedTest {

	public static void streamTest() throws IOException, ClassNotFoundException {
		int size = 1000000;
		int count = 10;
		MyData dat = new MyData();
		
		dat.initializeByRandom(size);

		//
		// SAVING
		//
		System.out.println("Streaming out: " + count + " x " + size + " doubles");

		long time = System.currentTimeMillis();
		File f;

		// saving using a DataOutputStream
		for (int i=0; i<count; i++) {
			f = new File("dos_" + i + ".dat");
			dat.saveManuallyDataOutputStream(f);
		}
		time = System.currentTimeMillis() - time;
		System.out.println("dos-time : " + time); System.out.flush();
				
		// saving using an ObjectOutputStream
		time = System.currentTimeMillis();
		for (int i = 0; i < count; i++) {
			f = new File("oos_" + i + ".dat");

			FileOutputStream fos = new FileOutputStream(f);
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			oos.writeObject(dat);
			oos.flush();
			oos.close();
			fos.close();
		}
		time = System.currentTimeMillis() - time;
		System.out.println("oos-time : " + time);
		System.out.flush();

		//
		// LOADING
		//
		System.out.println("Streaming in: " + count + " x " + size + " doubles");
		dat.initializeByRandom(0);

		// loading using a DataOutputStream
		time = System.currentTimeMillis();
			for (int i=0; i<count; i++) {
				f = new File("dos_" + i + ".dat");
				dat.loadManuallyDataInputStream(f);
			}
		time = System.currentTimeMillis() - time;
		System.out.println("dis-time : " + time); System.out.flush();

		// loading using an ObjectInputStream
		@SuppressWarnings("unused")
		MyData du;
		time = System.currentTimeMillis();
		for (int i = 0; i < count; i++) {
			f = new File("oos_" + i + ".dat");

			FileInputStream fis = new FileInputStream(f);
			ObjectInputStream ois = new ObjectInputStream(fis);
			du = (MyData) ois.readObject();
			ois.close();
			fis.close();
		}
		time = System.currentTimeMillis() - time;
		System.out.println("ois-time : " + time);
		System.out.flush();
	}

	public static void main(String[] args) throws IOException, ClassNotFoundException {
		streamTest();
		
		System.out.println("\nFINISHED");
	}
}
 

kopfsalat

Bekanntes Mitglied
Danke für die Tipps!

Ein einfaches
Code:
FileOutputStream fos = new FileOutputStream(f);
BufferedOutputStream bos = new BufferedOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(bos);
anstelle
Code:
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
hat tatsächlich schon einen gewissen Speedup gebracht. Buffered ist also fixer.

Aber die FileChannels mit den Buffern aus dem java.nio-package sind nochmals deutlich schneller!

Für 10.000.000 double-Werte (also 80MB) benötigen die Methoden nun etwa (gemittelt über 50 Durchläufe):
Speichern per BufferedOO: 960 ms
Speichern per FileChannels: 360 ms
Laden per BufferedOO: 1200 ms
Laden per FileChannels: 390 ms

zum Vergleich noch die Daten der .exe-Datei:
Speichern per exe-Datei: 700ms
Laden per exe-Datei: 180ms

Die braucht also für das Speichern länger, ist aber beim Laden fixer.

Ich habe auch noch mit den FileMapping-Routinen (per FileChannel.map(..)) gespielt und damit nochmals deutlich schnellere Zeiten als mit Channels und Buffern erzeugt. Allerdings gab es da teilweise rapide Einbrüche, wenn eine Datei, in die durch Mapping geschrieben wurde kurz darauf wieder per Mapping eingelesen werden sollte. Die Javadocs verweisen auch nur auf unbeeinflussbares Verhalten des Betriebssystem, und dass nicht festgelegt werden kann, wann das FileMapping wieder freigegeben wird.

Am sichersten + schnellsten erscheinen mir daher die FileChannels mit Buffern.

Hier noch die von mir verwendeten Methoden.

Code:
private double[] data;
	private static final int NUMELEMS = 4096;
	private static final int ELEMSIZE = 8; // 8 bytes a double 

	public void saveViaChannels(File file) throws IOException {
		FileOutputStream fout = new FileOutputStream(file);
		FileChannel fc = fout.getChannel();

		// create a byte-buffer
		ByteBuffer buffer = ByteBuffer.allocateDirect(NUMELEMS * ELEMSIZE);
			
		// write the arrays size as Double (no trouble, because each int is mapped to double without loss of precision)
		buffer.putDouble(data.length);
		buffer.flip();
		fc.write(buffer);
		buffer.clear();

		// create a double-buffer on the buffer
		DoubleBuffer dBuffer = buffer.asDoubleBuffer();
		dBuffer.clear();
		
		// write the array until far to the end 
		int i=0;
		while (i < data.length - NUMELEMS) {
			// add the data to dBuffer
			dBuffer.put(data, i, NUMELEMS);
			dBuffer.clear();
			
			// reset the buffer-marks (independant of dBuffer-marks) and write buffer
			buffer.position(0);
			buffer.limit(NUMELEMS*ELEMSIZE);
			fc.write(buffer);
			
			i += NUMELEMS;
		}

		// add the rest of data to dBuffer
		dBuffer.put(data, i, data.length-i);
		dBuffer.clear();
		
		// reset the buffer-marks and write buffer
		buffer.position(0);
		buffer.limit((data.length - i)*ELEMSIZE);
		fc.write(buffer);

		// close the stream (also channel)
		fout.close();
	}
	
	public void loadViaChannels(File file) throws IOException {
		FileInputStream fin = new FileInputStream(file);
		FileChannel fc = fin.getChannel();

		// create a byte-buffer and a DoubleBuffer on it
		ByteBuffer buffer = ByteBuffer.allocateDirect(NUMELEMS * ELEMSIZE);
		DoubleBuffer dBuffer = buffer.asDoubleBuffer();
		
		// fill the buffer the first time
		int len = fc.read(buffer);
		if (len % 8 != 0) {
			System.err.println("blocklength read not 8-byte-aligned! This should not happen and is not handled atm.");
		}
		dBuffer.position(0);
		dBuffer.limit(len / 8);
		
		// create the new data-array of correct size and wrap a new DoubleBuffer around  
		data = new double[(int) dBuffer.get()];
		DoubleBuffer dataBuffer = DoubleBuffer.wrap(data);
		dataBuffer.clear();
		
		// put the current dBuffer into the dataBuffer
		dataBuffer.put(dBuffer);

		// reset for a new read
		buffer.clear();
		len = fc.read(buffer);
		while (len >= 0) {
			if (len % 8 != 0) {
				System.err.println("blocklength read not 8-byte-aligned! This should not happen and is not handled atm.");
			}
			dBuffer.position(0);
			dBuffer.limit(len / 8);

			// put the current dBuffer into the dataBuffer
			dataBuffer.put(dBuffer);

			// reset for a new read
			buffer.clear();
			len = fc.read(buffer);
		}

		// close the stream (also channel)
		fin.close();
	}
Ab einer NUMELEMS von 33041 also mal 8 = 264328 Bytes Buffergröße bricht bei mir die Laufzeit übrigens rapide ab, das hängt wahrscheinlich mit irgendwelchen Festplatteneigenschaften zusammen. Unter dieser Grenze ist aber die Buffergröße relativ egal, deswegen habe ich einfach mal nur 4096 genommen.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Problem mit dem Lesen einer projektinternen .csv aus der runnable JAR Allgemeine Java-Themen 3
R 11 GB File lesen ohne zu extrahieren Filedaten Bereich für Bereich adressieren dann mit Multi-Thread id die DB importieren Allgemeine Java-Themen 3
G Dateien lesen Allgemeine Java-Themen 3
OnDemand Excel lesen wie CSV Allgemeine Java-Themen 7
S Textdatei statt von Dateisystem aus .jar lesen Allgemeine Java-Themen 3
oskarS85 GeoTiff NDVI pixelweise lesen Allgemeine Java-Themen 2
R Lesen von Interfaces (Programm Vervollständigen) Allgemeine Java-Themen 10
OnDemand CSV lesen flexible Spalten Allgemeine Java-Themen 3
E Datentypen Wie kann ich die Längen der unterschiedlichen Ebenen aus einem Objekt lesen von dem ich weiß, dass es ein mehrdimensionaler Array ist? Allgemeine Java-Themen 3
S File lesen und schreiben Java 6 Allgemeine Java-Themen 2
J Die Letzte Zahl aus einer Text datei lesen Allgemeine Java-Themen 8
L Input/Output Kassenzettel lesen aus einem Bild Allgemeine Java-Themen 2
M Daten aus MatLab Datei lesen Allgemeine Java-Themen 8
G Excel Tabelle lesen und in neue Excel Tabelle einfügen Allgemeine Java-Themen 11
J File in Package erstellen & lesen mit Programmstart in externe Projekt Allgemeine Java-Themen 3
A File lesen Codierung Charset Allgemeine Java-Themen 5
E Socket Dynamische Klasse von ObjectOutputStream lesen. Allgemeine Java-Themen 8
D Mit Java PHP hashmap lesen Allgemeine Java-Themen 1
B Quellcode lesen - Aussortieren Allgemeine Java-Themen 3
A Steuerung von Spiel aus Datei lesen Allgemeine Java-Themen 0
F Best Practice Große Anzahl an Objekten speichern und lesen Allgemeine Java-Themen 19
L CSV File lesen, in ArrayList speichern und ausgeben Allgemeine Java-Themen 3
S Eigenschaften (hier Verknüpfung) eines Files lesen Allgemeine Java-Themen 2
OnDemand Java Barcode lesen Allgemeine Java-Themen 4
F Json in sql speichern und lesen Allgemeine Java-Themen 10
K Classpath Alle Classen aus einem Package lesen Allgemeine Java-Themen 7
X NetBeans Bilder und andere Dateien ins .jar schreiben und wieder aus .jar lesen Allgemeine Java-Themen 6
K Bestimmten Bereich eines Strings lesen Allgemeine Java-Themen 6
H Input/Output .txt Datei in Jar lesen Allgemeine Java-Themen 6
F Lesen effizienter als schreiben? Allgemeine Java-Themen 4
RalleYTN REST API ResponseType application/pdf lesen Allgemeine Java-Themen 0
R Inputstream lesen mit Pointer Allgemeine Java-Themen 0
I Setzen und Lesen eines Objektes (Enum?) Allgemeine Java-Themen 10
javampir Input/Output Effizienz beim binären Lesen einer Datei Allgemeine Java-Themen 6
D Datentyp von Unbounded Wildcards lesen Allgemeine Java-Themen 2
J Text lesen und in Variablen speichern Allgemeine Java-Themen 3
B SMS von Vodafone Mobile Connest mit JAVA-Programm lesen Allgemeine Java-Themen 0
2 String Array in Datei schreiben und wieder davon lesen Allgemeine Java-Themen 2
A In Excel-Datei schreiben, Formeln der Mappe anwenden, Wert lesen Allgemeine Java-Themen 3
Thallius Dateien Zippen und wieder heraus lesen? Allgemeine Java-Themen 4
L Input/Output Datei in den Speicher lesen. Allgemeine Java-Themen 9
E Lesen von mehrere Csv-Datei und ihre Inhalte vergleichen Allgemeine Java-Themen 3
F Java Bytecode lesen Allgemeine Java-Themen 5
W Schreiben/Lesen aus RS232 / jssc Allgemeine Java-Themen 0
L Input/Output Datei lesen Allgemeine Java-Themen 1
H Mehrere Bilder aus einer Datei lesen Allgemeine Java-Themen 2
OnDemand Lesen aus Properties Allgemeine Java-Themen 7
S XML lesen, verarbeiten, speichern klappt in Eclipse, aber nicht in der JAR Allgemeine Java-Themen 4
N Content von URL lesen Allgemeine Java-Themen 18
T UTF-16LE String aus LDAP lesen und als ISO-8859-1 in DB speichern? Allgemeine Java-Themen 2
J Bytes aus Socket lesen Allgemeine Java-Themen 9
M Aus Excel Tabelle lesen und Werte in Array speichern Allgemeine Java-Themen 15
W Passwortgeschuetzte .mpp Datei mit MPXJ lesen Allgemeine Java-Themen 3
O BufferedReader von ganz unten anfangen zu lesen Allgemeine Java-Themen 7
G Binäre Datei lesen / schreiben Allgemeine Java-Themen 9
E Apache POI-Datei lesen und umschreiben Allgemeine Java-Themen 8
T Welches Tuturial soll ich paralell lesen ? Allgemeine Java-Themen 3
T Datei lesen, bearbeiten, speichern Allgemeine Java-Themen 14
G Kann HTML Datei nicht lesen Allgemeine Java-Themen 3
S Die Zeile die JUnit gerade ausführt lesen Allgemeine Java-Themen 15
A nur einen Wert aus einer .conf lesen und erneuern Allgemeine Java-Themen 3
H Input/Output InputStream: 32-Bit-Ganzzahl (DWORD) binär lesen Allgemeine Java-Themen 5
B Hex aus .txt lesen Allgemeine Java-Themen 8
C Datentypen von string in ein array lesen Allgemeine Java-Themen 4
C aus einem String einzelne Hex Werte lesen Allgemeine Java-Themen 7
D Ausgabe von C# Konsolenanwendung lesen Allgemeine Java-Themen 5
F CSV-Datei aus Internet lesen Allgemeine Java-Themen 2
P ObjectInputStream kann nicht vernünftig lesen... Allgemeine Java-Themen 9
R Datei zeilenweise lesen und schreiben Allgemeine Java-Themen 6
0 Datein aus laufender Jar lesen und bearbeiten Allgemeine Java-Themen 10
S Dateien aus src-Ordner lesen Allgemeine Java-Themen 3
F hex-farbwert der pixel aus bildern lesen Allgemeine Java-Themen 4
L Wikipedia Artikel lesen Allgemeine Java-Themen 16
J HSSF - schreiben in und lesen aus vorhandener Datei Allgemeine Java-Themen 6
R Properties Datei aus Applikationsverzeichnis lesen Allgemeine Java-Themen 5
J xlsx Dateien lesen OHNE apache POI Allgemeine Java-Themen 6
C Property-File lesen und schreiben Allgemeine Java-Themen 20
M Binäre Datei schreiben und lesen Allgemeine Java-Themen 4
N Problem beim lesen einer File in JAR-File Allgemeine Java-Themen 3
D Datei lesen ohne sie für umbenennen/verschieben zu sperren Allgemeine Java-Themen 13
reibi Sicher ein File lesen Allgemeine Java-Themen 28
R Java lesen von Dateien, Little-Endian Allgemeine Java-Themen 2
N Performates lesen von Objekten aus Dateien Allgemeine Java-Themen 2
T Integer aus InputStream lesen Allgemeine Java-Themen 3
C Alle Klassen eines Packages lesen und instanzieren? Allgemeine Java-Themen 9
D Probleme beim schreiben / lesen in TreeMap Allgemeine Java-Themen 9
D (Viele) Daten performant speichern und lesen Allgemeine Java-Themen 5
TiME-SPLiNTER Unbekannte Anzahl serialisierter Objekte lesen Allgemeine Java-Themen 2
brunothg Iso lesen Allgemeine Java-Themen 2
B PDF lesen funktioniert bei bestimmten Dateien nicht mit pdfview Allgemeine Java-Themen 4
C Markierung durch Maus lesen Allgemeine Java-Themen 9
nrg JDOM Tabelle lesen Allgemeine Java-Themen 6
P Datei in einen String lesen Probleme bei Codierung Allgemeine Java-Themen 2
L Grafik lesen Allgemeine Java-Themen 2
P Mime Type aus Stream lesen Allgemeine Java-Themen 5
H POI Excel lesen und schreiben Allgemeine Java-Themen 10
Iron Monkey Object in Datei effizienter lesen / schreiben Allgemeine Java-Themen 13
L Lesen von Objekten aus Datei Allgemeine Java-Themen 17
M PCL Stream lesen und schreiben Allgemeine Java-Themen 6
U Java file aus Classpath lesen Allgemeine Java-Themen 1

Ähnliche Java Themen

Neue Themen


Oben