2017-12-08 3 views
2

Ich habe ein Stück Code, der einen Ausgabestrom auf zwei Ziele aufteilt. Sie gehen beide zu einer Datei, aber das zweite Ziel wird durch einen Filter gehen. Ich versuche herauszufinden, warum das einfache Umschließen eines FilterOutputStream ohne Überschreiben irgendwelcher Methoden eine große Leistungseinbuße hinzufügt.Java FilterOutputStream fügt eine Leistungseinbuße hinzu

habe ich eine Datei, die 358 Megabyte ist:

dd if=/dev/zero of=dummyfile.txt count=700000 bs=512 

Ran diesen Code dagegen:

private OutputStream getFilteredStream(OutputStream out1, OutputStream out2) { 
    return new TeeOutputStream(out1, new FilterOutputStream(out2)); 
} 
private OutputStream getDestination(String name) { 
    return new BufferedOutputStream(new FileOutputStream(new File(name))); 
} 
... 
InputStream in = new FileInputStream(new File("dummyfile.txt")); 
OutputStream out = getFilteredStream(getDestination("dest1"), getDestination("dest2")); 
long start = System.currentTimeMillis(); 
IOUtils.copy(in, out); 
out.flush(); 
long end = System.currentTimeMillis(); 
System.err.println(((end - start)/1000.0) + " seconds"); 
// close the files 

Das Ergebnis:

1.672 seconds 

Wenn ich die FilterOutputStream entfernen. ..

private OutputStream getFilteredStream(OutputStream out1, OutputStream out2) { 
    return new TeeOutputStream(out1, out2); 
} 

... und wieder läuft, ist das Ergebnis:

0.797 seconds 

ich eine Leistungseinbuße erwarten, wenn eine FilterOutputStream, aber ich erwarte nicht die Strafe doppelt zu sein, vor allem, wenn sie nicht überschreibt alle Methoden. Ich habe mir den Quellcode von FilterOutputStream angesehen, aber nichts gesehen, was eine so große Strafe verursacht hätte.

Kann jemand erklären, was dieses Problem verursachen könnte?

+0

Verwenden Sie einen Profiler, um zu sehen, was passiert. – Kayaman

+0

Was ist der Sinn des Hinzufügens eines einfachen 'FilterOutputStream' zu der Pipeline, ohne diese zu einer tatsächlichen Filterung zu untergliedern? – Andreas

+0

Es hat keinen Sinn, ich versuche nur, das Problem zu demonstrieren, das ich sehe. – user1428945

Antwort

4

Es ist langsamer, da die Standardimplementierung in FilterOutputStream Blockverarbeitung deaktiviert und sendet alle Bytes durch die write(int b) Methode, einen nach dem anderen.

Dies ist documented:

Beachten Sie, dass diese Methode nicht mit den gleichen Argumenten der Schreibmethode des zugrunde liegenden Eingangsstrom nicht nennen. Unterklassen von FilterOutputStream sollten eine effizientere Implementierung dieser Methode bereitstellen.

+0

Nach dem Überschreiben der Methode write (byte b [], int off, int len) ist die Leistung wieder normal. – user1428945

Verwandte Themen