Posted at

C/C++のファイル操作速度比較

More than 1 year has passed since last update.

C++は最速!!と思い込んでいました。ネットで「Cのべた書きとSTLはどっちが速い」なんて、C++速いぞって記事をたまに見かけるでしょう。

しかし実際にfstreamを使ったファイルコピーを書いてみたら、C++、意外に遅いか?という結果に・・・。具体的にどれぐらい違うのかC標準ライブラリとの実行速度の比較を行なってみました。


環境

使用したのはVisualStudio 2008。VS2013でもあまり変わらないみたいです。


コード

比較したコードは下記の4つ。いづれも入力ファイルから出力ファイルへバイナリコピーします。エラー処理は省いています。


1:streambuf_iteratorとcopy()を使う


C++

void CopyFile( const char *from_file_name, const char *to_file_name )

{
ifstream is( from_file_name, ios::in | ios::binary );
ofstream os( to_file_name, ios::out | ios::binary );

// ファイルコピー
istreambuf_iterator<char> iit(is);
istreambuf_iterator<char> end;
ostreambuf_iterator<char> oit(os);
copy( iit, end, oit );
}



2:fstream::rdbuf()と<<を使う


C++

void CopyFile( const char *from_file_name, const char *to_file_name )

{
ifstream is( from_file_name, ios::in | ios::binary );
ofstream os( to_file_name, ios::out | ios::binary );

// ファイルコピー
os << is.rdbuf();
}



3:fstreamとバッファ(1MB)を使う


c++

void CopyFile( const char *from_file_name, const char *to_file_name )

{
ifstream is( from_file_name, ios::in | ios::binary );
ofstream os( to_file_name, ios::out | ios::binary );

// バッファ確保
vector<char> buffer( 1024*1024 );
// ファイルコピー
while( !is.eof() )
{
size_t size = is.read( &buffer[0], buffer.size() ).gcount();
os.write( &buffer[0], size );
}
}



4:Cの標準ライブラリとバッファ(1MB)を使う


C++

void CopyFile( const char *from_file_name, const char *to_file_name )

{
FILE *fpr = fopen( from_file_name, "rb" );
FILE *fpw = fopen( to_file_name , "wb" );

// バッファ確保
vector<char> buffer( 1024*1024 );
// ファイルコピー
while( !feof( fpr ) )
{
size_t size = fread( &buffer[0], 1, buffer.size(), fpr );
fwrite( &buffer[0], 1, size, fpw );
}
fclose( fpr );
fclose( fpw );
}



結果

Cの標準ライブラリが数倍速いです。

コード
処理時間・キャッシュなし (ms)
処理時間・キャッシュあり(ms)

1:streambuf_iteratorとcopy()
2,400
2.000

2:fstream::rdbuf()と<<
2,000
1,900

3:fstreamとバッファ
1,200
500

4:Cの標準ライブラリ
650
90

「キャッシュなし」はファイルのメモリへの初回読み込み、「キャッシュあり」は2回目以降の読み込みです。「キャッシュあり」はあまり意味がないと思ったのですが、速度差が大きいので載っけておきました。

キャッシュなしで比較すると、1or2(fstream+algorithm)と3(fstream)の速度比がおおざっぱに2倍、3(fstream)と4(Cライブラリ)の速度比も2倍ですから、fstream遅いわ、copy(),<<等のアルゴリズム遅いわで、両者の共犯でこの速度差になっていると推測できます。

(測定条件)130Mバイトのファイルを使用。x86。普通のリリースモード(速度最適化)。処理時間は多少ばらつくので数回実行して目分量で丸めています。


まとめ

CとC++(fstream)で数倍の差が出たのはちょっと驚きでした。

速度を求めるときfstreamは使用できませんね。


番外:C#

C#でも同様のコードを書いて試してみました。


C#

private static void CopyFile( string from, string to )

{
using( BinaryReader br = new BinaryReader( File.OpenRead( from ) ) )
using( BinaryWriter bw = new BinaryWriter( File.OpenWrite( to ) ) )
{
// ファイルコピー
while(true)
{
byte[] buf = br.ReadBytes( 1024*1024 );
if( buf.Length == 0 )
break;
bw.Write( buf );
}
}
}

コード
処理時間・キャッシュなし(ms)
処理時間・キャッシュあり(ms)

C#
650
130

速い。Cライブラリに肉薄。