2012-04-25 6 views
8

Linuxのパイプにデータを書き込むには、関数呼び出しfwrite()を使用しています。fwrite()のバッファリング動作の理解

これまでのところ、小さなチャンクのデータ(平均20バイト)に対してはfwrite()が呼び出され、バッファリングはfwrite()のままでした。プロセス上のstraceは、一度に4096バイトのデータが書き込まれていることを示しました。

この書き込みプロセスが私のプログラムのボトルネックであることが判明しました。だから私はコード内のデータを64KBのブロックにバッファリングし、ブロック全体を一度にfwrite()を使って書き込むことにしました。私はsetvbuf()を使用して、FILE *ポインタを 'No Buffering'に設定しました。

パフォーマンスの向上は期待したほどではありませんでした。

さらに重要なことに、straceの出力では、一度に4096バイトのデータがまだ書き込まれていました。誰かがこの行動を私に説明してもらえますか?私がfwrite()に64KBのデータを呼び出すと、一度に4096バイトしか書き込まないのはなぜですか?

FILE *ポインタを使用してパイプにデータを書き込むためのfwrite()の代替品はありますか?

+0

コードを表示できますか? – tuxuday

+1

@Shailesh_Tainwala:C++でコードを書くかもしれませんが、これはC++ではなくcです。 'fwrite()'はc関数であり、C++関数ではありません。私はあなたの質問にcタグを追加したので、より多くの聴衆を得ることができます。 –

答えて

8

4096は、パイプラインの基盤となるLinuxのマシンに由来します。それは2つの場所が発生します。 1つはパイプラインの容量です。容量は、古いバージョンのLinuxでは1システムページで、32ビットのi386マシンでは4096バイトです。 (現代版のLinuxでは、容量は64Kです。)

この4096バイトの問題に対処する他の場所は、定義された定数PIPE_BUFです。アトミックに扱われることが保証されているバイト数です。 Linuxでは4096バイトです。この制限が意味することは、パイプラインをブロックまたは非ブロックに設定したかどうかによって異なります。すべての詳細については、man -S7 pipeを実行してください。

大量のデータを高速で交換しようとしている場合は、パイプの使用を再考することをおすすめします。あなたはLinuxボックスを利用しているので、共有メモリはオプションです。パイプを使用して、シグナリングメカニズムとして比較的少量のデータを送信することができます。

+0

Linuxのみの別のオプションは、fwrite()の代わりにopen()とsplice()を使うことです。 –

4

あなたがバッファリング動作を変更したい場合は、(標準のファイルハンドルstdinstdoutstderrのために、または任意のI/Oの前に)すぐにfopen後に行う必要があります。また、バッファリングを無効にして、バッファを自分で管理したくない場合もあります。むしろ、適切に使用できるように、あなたの64Kバッファーをsetvbufに指定してください。

実際にバッファリングを手動で管理する場合は、stdioを使用しないでください。 openwrite、およびcloseの呼び出しを使用します。

関連する問題