2017-12-08 7 views
2

出力ストリームを2つの宛先に分割するコードがあります。両方ともファイルに行きますが、2番目の宛先はフィルタを通過します。私は、単に何らかのメソッドをオーバーライドせずにFilterOutputStreamをラップするだけで、パフォーマンスが大幅に低下する理由を理解しようとしています。私はFilterOutputStreamを削除した場合JavaのFilterOutputStreamはパフォーマンスのペナルティを追加します

1.672 seconds 

私は358メガバイトのファイル作成:

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 

結果:

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

は、それに対してこのコードを実行しました。 ..

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

...そして再びそれを実行し、その結果は次のとおりです。

0.797 seconds 

FilterOutputStreamを使用しているとき、私はパフォーマンスの低下を期待していますが、私はペナルティが2倍に期待していないです、場合は特にありません任意のメソッドをオーバーライドします。私はFilterOutputStreamのソースコードを見ましたが、このような大きなペナルティを引き起こすものは見ませんでした。

この問題の原因を説明できる人はいますか?

+0

何が起きているのかを見るには、プロファイラを使用します。 – Kayaman

+0

パイプラインにプレーンな 'FilterOutputStream'を追加して、実際にフィルタリングするためにサブクラス化することなく、何がポイントになりますか? – Andreas

+0

ポイントはありません、私は見ている問題を実証しようとしています。 – user1428945

答えて

4

FilterOutputStreamのデフォルトの実装では、ブロック処理を無効にしwrite(int b)方法、一度に一つを介してすべてのバイトを送信するので、それは遅いです。

これはdocumentedです:このメソッドは、同じ引数でその基礎となる入力ストリームのwriteメソッドを呼び出していないことを

注意。 FilterOutputStreamのサブクラスは、このメソッドのより効率的な実装を提供する必要があります。

+0

実際、write(byte b []、int off、int len)メソッドをオーバーライドした後、パフォーマンスは正常に戻ります。 – user1428945

関連する問題