2016年6月18日土曜日

ofstreamのバッファサイズ

以前から思っていたんですが、c++のプログラムで1つのファイルの中のデータを複数のデータに分類して出力するプログラムが、どうにも時間がかかると。

まあ、100MB以上のファイルを数百のデータに分類する場合などかなり処理が重いとはわかっているんですが、にしても耐え難くなってきました。色々、ぐぐってみるとやはりofstreamは昔のcのfwrite()に比べるとかなり遅いようです。(持っている機能が段違いなので、プログラム作成の手間を考えると今更ofstreamをfwrite()に戻す気にはなりませんが)

そんななか、ofstreamのバッファを大きくすると速くなるとの話を見つけました。ちょっと試してみます。(10MBのテキストファイルを作成するだけです)

#include <iostream>
#include <fstream>
using namespace std;
int main(void)
{
const int bufsize=100000;
char buf[bufsize];
ofstream os;
os.rdbuf()->pubsetbuf(buf,bufsize);
os.open("test.txt", ios::out);
for (int i=0; i<10000000; i++)
{
os << "a";
}
os.close();
return 0;
}
view raw test1.cpp hosted with ❤ by GitHub
実行してみると、一瞬で終わります。そこで、わざとバッファサイズを小さくしてみます。

include <iostream>
#include <fstream>
using namespace std;
int main(void)
{
const int bufsize=2;
char buf[bufsize];
ofstream os;
os.rdbuf()->pubsetbuf(buf,bufsize);
os.open("test.txt", ios::out);
for (int i=0; i<10000000; i++)
{
os << "a";
}
os.close();
return 0;
}
view raw test2.cpp hosted with ❤ by GitHub
極端ですが、いきなり10秒以上処理に時間がかかるようになりました。

ところでデフォルトのバッファサイズはどれくらいになっているんでしょう?あとどのくらい大きくしても大丈夫なんだろ?(実は大きいほどいいかと最初は思い、bufsizeを100MBなんてやったら、プログラムが動かなくなりました。それもファイル出力をしているサブルーチンに入ったところで異常終了!全然理由がわかりませんが、どうもサブルーチンのローカル変数としてバッファを定義したので、スタックエリアに問題が出たんでしょう。)このあたりは、プログラムやそれを動かすシステムの性能にもよるでしょうから、一口には中々言えないところでしょう。