2017-12-30 43 views
5

私の場合は、次のとおりです。C++のstd ::にstringstreamオペレーションの最適化を次のように

  1. 私はSTDとから読んでいるバイナリファイルを持っている:: fstreamのは、(のchar *)としての動作を読ん
  2. 私の目標でありますファイル、進フォーマット済みのすべてのバイトを取り、その後、変数文字列に追加する
  3. さんが言わせて、例えば2

項目ごとにフォーマットされたファイルの内容全体を保持する必要がある文字列変数私は次のビンを持っています進ファイルの内容:

D0 46 98 57 A0 24 99 56 A3

次のように私は、各バイトの書式を設定しています方法は次のとおりです。

stringstream fin;; 

for (size_t i = 0; i < fileb_size; ++i) 
{ 
fin << hex << setfill('0') << setw(2) << static_cast<uint16_t>(fileb[i]); 
} 

// this would yield the output "D0469857A0249956A3" 

return fin.str(); 

アプローチ上記期待通りに動作します、しかし、それはあります私が理解している大容量のファイルでは非常に遅いです。 stringstreamは入力フォーマット用です!

私の質問は、そのようなコードを最適化する方法はあるのでしょうか?私の唯一の制約は、上記のように出力が文字列形式であることです。

ありがとうございます。

+3

iostreamsは効率を考慮して設計されていません。特定のユースケースでは、ネイティブ実装固有のファイルI/Oに勝ることはできません。あるいは、悪い場合には、Cの 'FILE *'を取り出して、手作業で最適化された16進変換コードをロールバックします。効率化のためにそれを打つことはできませんでした。ロケット科学ではありません。少なくとも私がCとC++を学んだ時代には、これは典型的な宿題でした:16進数を読み、それを変換します。 –

+1

「非常に遅い」と比較して何か? –

+1

出力文字列の[予約サイズ](https://stackoverflow.com/q/1941064/995714)を試しましたか?あなたはすでに入力のサイズを知っているので、出力のサイズを簡単に計算し、配列を何度も再割り当てすることは避けてください。 –

答えて

4

std::stringstreamはかなり遅いです。これはあらかじめ割り当てられておらず、文字列を少なくとも1回はコピーして取り出します。また、16進数への変換は、より高速になるように手作業でコード化することもできます。

私はこのようなものは、よりパフォーマンスかもしれないと思う:

// Quick and dirty 
char to_hex(unsigned char nibble) 
{ 
    assert(nibble < 16); 

    if(nibble < 10) 
     return char('0' + nibble); 

    return char('A' + nibble - 10); 
} 

std::string to_hex(std::string const& filename) 
{ 
    // open file at end 
    std::ifstream ifs(filename, std::ios::binary|std::ios::ate); 

    // calculate file size and move to beginning 
    auto end = ifs.tellg(); 
    ifs.seekg(0, std::ios::beg); 
    auto beg = ifs.tellg(); 

    // preallocate the string 
    std::string out; 
    out.reserve((end - beg) * 2); 

    char buf[2048]; // larger = faster (within limits) 

    while(ifs.read(buf, sizeof(buf)) || ifs.gcount()) 
    { 
     for(std::streamsize i = 0; i < ifs.gcount(); ++i) 
     { 
      out += to_hex(static_cast<unsigned char>(buf[i]) >> 4); // top nibble 
      out += to_hex(static_cast<unsigned char>(buf[i]) & 0b1111); // bottom nibble 
     } 
    } 

    return out; 
} 

それはコピーを最小限にし、再配分を避けるために事前に割り当てられた文字列を追加します。

+0

詳しい解決策は@Galikに感謝します。このアプローチでは、どんな驚異的なパフォーマンス向上が見られますか? – Xigma

関連する問題