Unerwartetes Verhalten von BufferedWriter

Schnoogle

Mitglied
Hallo,

ich schreibe gerade ein Programm, dass eine CSV-Datei erstellt.

Dabei verhält sich die Performance des Programms für mich unerwartet.

Ich habe folgenden Writer verwendet:

FileWriter fileWriter = new FileWriter(file);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
PrintWriter printWriter = new PrintWriter(bufferedWriter);

Die folgenden Methoden von PrintWriter verwende ich:

printWriter.print(','); //Separator
printWriter.println(); //Zeilenumbruch
printWriter.print(...) //Für Datentypen, die von Number ableiten
printWriter.write(String) //Für Strings

Jetzt habe ich folgendes Verhalten bemerkt. Das Programm läuft schneller, wenn ich nach jedem printWriter.println() die Methode printWriter.flush() aufrufen, als wie wenn ich nur am Ende printWriter.close() aufrufe.

Kann dies vielleicht daran liegen, dass ich eine SSD verwende?
 

Bratkartoffel

gebratene Kartoffel
Premium-User
Hi,

Wie hast du da die Zeit gemessen?
Wie viel Daten schreibst du?

Ich kann mir kaum vorstellen, dass ein explizites flush() das Schreiben der Daten schneller macht. SSD oder nicht, das ist hier eher weniger relevant. Das flush() schaltet vereinfacht gesagt mehr oder weniger den internen Cache des Systems ab und zwingt die Daten auf die Festplatte. Ohne flush() kümmert sich das System darum, dass die Daten so schnell und mit so wenig Zugriffen wie möglich auf der Platte landen.

Grüsse,
BK

// Edit: Habe hier noch einen Thread bei StackOverflow gefunden, in diesem stehen ein paar grundsätzliche Tips zur IO-Performance mit Java, vorallem in Bezug auf java.io gegen java.nio
 
Zuletzt bearbeitet:

vfl_freak

Premium-User
Moin,

bitte verwende stets Java-Tags !!
Jetzt habe ich folgendes Verhalten bemerkt. Das Programm läuft schneller, wenn ich nach jedem printWriter.println() die Methode printWriter.flush() aufrufen, als wie wenn ich nur am Ende printWriter.close() aufrufe.
Kann dies vielleicht daran liegen, dass ich eine SSD verwende?
Also mit der SSD wird es gar nicht tun haben!

Um mal die Doku zu zitieren:
"The flush method flushes the output stream and forces any buffered output bytes to be written out. The general contract of flush is that calling it is an indication that, if any bytes previously written have been buffered by the implementation of the output stream, such bytes should immediately be written to their intended destination"

Das Puffern der Daten verbessert also die I/O-Performance.
Mehr zu diesem Thema findest Du hier:
http://www.oracle.com/technetwork/articles/javase/perftuning-137844.html

Gruß Klaus
 

Schnoogle

Mitglied
Hi,

Wie hast du da die Zeit gemessen?
Wie viel Daten schreibst du?

Ich kann mir kaum vorstellen, dass ein explizites flush() das Schreiben der Daten schneller macht. SSD oder nicht, das ist hier eher weniger relevant. Das flush() schaltet vereinfacht gesagt mehr oder weniger den internen Cache des Systems ab und zwingt die Daten auf die Festplatte. Ohne flush() kümmert sich das System darum, dass die Daten so schnell und mit so wenig Zugriffen wie möglich auf der Platte landen.

Grüsse,
BK

// Edit: Habe hier noch einen Thread bei StackOverflow gefunden, in diesem stehen ein paar grundsätzliche Tips zur IO-Performance mit Java, vorallem in Bezug auf java.io gegen java.nio

Hallo,

ich habe mir vor dem Instanziieren meiner Writer die Systemzeit geholt.

Code:
final long startTimeMillis = System.currentTimeMillis();
final FileWriter fileWriter = new FileWriter(file);
final BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
final PrintWriter printWriter = new PrintWriter(bufferedWriter);

Und nach dem Schließen von meinem Writer habe ich mir wieder die Systemzeit geholt und die Differenz berechnet.

Code:
printWriter.close();
final long endTimeMillis = System.currentTimeMillis();
final long runTimeMillis = endTimeMillis = startTimeMillis;

Zwischen der Instanziierung meiner Writer und dem Schließen der Writer gibt es in einer geschachtelten Schleife sehr viele Aufrufe von folgenden Methoden des PrintWriter. Ich schreibe jeden Wert, als jede Zelle in der CSV-Datei und jeden Separator sowie jeden Zeilenumbruch separat.

Code:
printWriter.print(','); //Separator
printWriter.println(); //Zeilenumbruch
printWriter.print(value); //Byte, Short, Integer, Long
printWriter.format(Locale.GERMANY, "%f", value); //Float und Double
printWriter.write(value) //Strings

Die Größe der Dateien ist unterschiedlich. Bei meinen Tests lag die kleinste Datei bei 1.424 KB und die größte Datei lag bei 43.735 KB.

Ich war von dem Verhalten auch überrascht, da ich in der Vergangenheit durch gepuffertes Schreiben, sehr viel Schneller war. Dies war jedoch immer auf Systemen mit Festplatten.

In meinem jetzigen System ist eine Samsung SSD 840 PRO unter Windows 7 eingebaut. Ich verwende noch Java in der Version 6.
 
Zuletzt bearbeitet: