C++でファイルの内容をメモリ上に読み出すコードを書いてみたところ、 書き方によって結構性能に差がありました。そこでちょっと性能を調べてみましたのでまとめておきます。
C++では、メモリ上でのデータ保持方法は色々ありそうですが、
代表的なものということで、std::stringとstd::vector
1つめのコード。Case1とします。
// Case1 using namespace std; string Data(istreambuf_iterator<char>(ifstream(FileName, ios::in | ios::binary)), istreambuf_iterator<char>());一行でも書ける短いコードです。
2つめのコード。Case2とします。
// Case2 using namespace std; vector<char> Data(istreambuf_iterator<char>(ifstream(FileName, ios::in | ios::binary)), istreambuf_iterator<char>());std::vectorを使ったこと以外はCase1と同じです。
3つ目のコード。Case3とします。
// Case3 using namespace std; vector<char> Data; copy(istreambuf_iterator<char>(ifstream(FileName, ios::in | ios::binary)), istreambuf_iterator<char>(), back_inserter(Data));std::back_inserterを使ったC++らしいコードです。
最後のコード。Case4とします。
// Case4 using namespace std; vector<char> Data; std::ifstream Input(FileName, std::ios::in | std::ios::binary); Data.resize(Input.seekg(0, std::ios::end).tellg()); Input.seekg(0, std::ios::beg).read(&Data[0], static_cast<std::streamsize>(Data.size()));C言語に近い古い書き方。 シークしてファイルサイズを求めたら一気に読みだしています。
大きなファイルであれば何でも良いと思いましたので、 makedummyというツールを使って作った100MB(104,857,600 Bytes)のファイルを使いました。データはランダムです。
測定環境は以下の通りです。
コンパイラ | Visual C++.NET 2003デフォルトコンパイラ |
OS | Windows XP Professional SP2 |
CPU | AMD Athlon 64 3700+ |
メモリ | 2GB |
HDD | Seagate ST3300622AS |
ファイルシステム | NTFS |
プロジェクト設定 | デフォルトRelease構成 |
100MB位だとディスクキャッシュに格納されてしまうみたいなので、OS起動直後のファイルキャッシュに格納される前の読み出し時間を測るようにしました。
結果は以下の通り。
時間を速度に変換してみました。1MB/s=1024×1024Byte/s です。
分かったこと。
とんでもなく遅レスで申し訳ありません。
stlのファイルロードで探しているうちにココにたどり着きました。
測定結果の差は、恐らくvectorの領域限界がくると
メモリの再確保→コピーを繰り返しているか否かだと思われます。
(内部実装的にvectorは2の階乗で領域を確保していたと思います。)
back_inserterの事はよく知りませんが、Case4に関しては
vector.resizeでその手間が省かれた分が速度に反映されたのでは、と思います。
貴重な情報ありがとうございました。
Posted by: 通りすがり : 2008年07月08日 17:19