最近、私が行っていたファイルの読み取りを最適化することにしました。なぜなら、誰もが言うように、大量の小さな読み取りを使用するよりも、大量のデータをバッファーに読み取ってから操作する方が速いからです。そして、私のコードは確かに今でははるかに高速ですが、いくつかのプロファイリングを行った後、memcpy に多くの時間がかかっているようです。
私のコードの要点は...
ifstream file("some huge file");
char buffer[0x1000000];
for (yada yada) {
int size = some arbitrary size usually around a megabyte;
file.read(buffer, size);
//Do stuff with buffer
}
私はVisual Studio 11を使用していますが、コードをプロファイリングした後、内部バッファからバッファにコピーするifstream::read()
呼び出しが最終的に表示されます。xsgetn()
この操作は時間の 80% 以上を占めます。2 位はuflow()
10% の時間を占めています。
このコピーを回避する方法はありますか? ifstream
必要なサイズをバッファに直接バッファするようにどうにかして伝えることはできますか? C スタイルFILE*
もそのような内部バッファを使用しますか?
更新: cstdio を使用するように言われたので、ベンチマークを行いました。
編集: 残念ながら、古いコードは失敗に満ちていました (ファイル全体を読み取ることすらできませんでした!)。ここで見ることができます:http: //pastebin.com/4dGEQ6S7
これが私の新しいベンチマークです。
const int MAX = 0x10000;
char buf[MAX];
string fpath = "largefile";
int main() {
{
clock_t start = clock();
ifstream file(fpath, ios::binary);
while (!file.eof()) {
file.read(buf, MAX);
}
clock_t end = clock();
cout << end-start << endl;
}
{
clock_t start = clock();
FILE* file = fopen(fpath.c_str(), "rb");
setvbuf(file, NULL, _IOFBF, 1024);
while (!feof(file)) {
fread(buf, 0x1, MAX, file);
}
fclose(file);
clock_t end = clock();
cout << end-start << endl;
}
{
clock_t start = clock();
HANDLE file = CreateFile(fpath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, NULL, NULL);
while (true) {
DWORD used;
ReadFile(file, buf, MAX, &used, NULL);
if (used < MAX) break;
}
CloseHandle(file);
clock_t end = clock();
cout << end-start << endl;
}
system("PAUSE");
}
時間:
185
80
78
ええと... C スタイルの fread を使用すると、ifstream::read よりも高速に見えます。同様に、Windows ReadFile を使用しても無視できるわずかな利点しかありません (私はコードを見て、基本的に fread は ReadFile のラッパーです)。結局フレッドに乗り換えそうです。
このことを実際に正しくテストするベンチマークを書くのは混乱します。
結論: を使用した<cstdio>
方が より高速です<fstream>
。fstream が遅い理由は、c++ ストリームに独自の内部バッファーがあるためです。これにより、読み取り/書き込みのたびに余分なコピーが発生し、このコピーが fstream にかかる余分な時間全体を占めます。さらに衝撃的なのは、実際にファイルを読み取るのにかかる時間よりも余分にかかる時間が長いということです。