LoginSignup
35
28

More than 5 years have passed since last update.

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

Posted at

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ライブラリに肉薄。

35
28
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
28