2016-09-05 6 views
-5
while(true) 
{ 
    std::wstring insert; 
    //... 
    if (insert.empty()){ 
    //... 
    } 
    else if (insert.substr(0, 3) == L"`/`"){ 
    //... 
    } 
    else if (insrtttt.at(0) == '\t'){ 
    //... 
    } 
    else if (insrtttt.at(0) == L'#') break; 
    else { /*...*/ } 
} 

私のプログラムでは、ブレークが実行される前に約50ティック(私はそのように名前を付けることができます)を要します。私はパフォーマンスについて心配しています:私はちょうど使用した場合、それが良いでしょうwhile(true)と(else)を使用しています(...)break;場合によっては「より良い」?

while(insrtttt.at(0) != L'#') 

+0

あなたがあなたの目標について詳しく説明できますか?あなたは何を目指していますか? – Charles

+1

CタグをC++の質問に載せないでください。 –

+1

std :: stringview in C++ 17では、これはかなり高速になります。 –

答えて

0

'#'に、すべての繰り返しで確認しているため、パフォーマンスが悪化する可能性があります。

これまで通り、は、のプロファイルです。これらの質問は要約では答えられません。

実行時間のほとんどは、そのsubstrコールから新鮮なstd::stringを生成するのに費やされている可能性があります。動的割り当てが含まれています。あなたは、個々のキャラクターを個別に調べる方がはるかに良いでしょう。おそらく比較機能を備えたある種の「文字列ビュー」クラスでそれをラップしています。

+0

私が知っているほとんどのSSO実装では、3文字の文字列を扱うことができます。 –

+0

@ T.C。あなたがCOWを許可しているのでなければ、それはせいぜい各反復で "スタックメモリ"(ugh)への不要なコピーです。しかし、それはIIRCに準拠せず、GCCはもはやIIRCをもはやしません。あるいはSSOの歴史をCOWの歴史と混同していますか?まあ、いずれにせよ、あなたは既に存在する文字を比較する方が良いです。 –

0

ない(おそらくunanswerable)の質問に直接答えが、あなたが興味があるかもしれない。

std::stringは、短い文字列に使用する(ご使用の場合)スタック上のメモリを事前に割り当てるいくつかのヒント。文字列が長すぎる場合は、ヒープからメモリを割り当てます(パフォーマンスの低下)。

文字列がさらに大きくなると、再割り当てが必要になることがあります。

ループ内のバッファとして文字列(または任意のコンテナ)を使用する場合、1つのオブジェクトを割り当てて再利用する方がはるかに意味があります。これは、文字列の概念がcapacity()(つまり、どれくらいのメモリを所有しているか)とsize()(私が使用しているメモリの量)という概念があるからです。

clear()文字列の場合、capacity()は縮小されません。つまり、同じループ内で1回または2回だけメモリ割り当てコストを支払うことになります。

さらに、substr()は新しい文字列を割り当てます。短い3文字の文字列については、これは問題ではありませんが(上記を参照してください)、長い文字列の場合はメモリ割り当てコストが発生します。

ので(パフォーマンスがあなたの#1の目標である場合)、タイトなループ内:

  1. 反復あたり1つの文字列バッファを再使用します。

  2. substrを避け、明示的に範囲を比較します。

ので、このような何か:

#include <string> 

extern void build_string(std::wstring& target); 

void foo() 
{ 
    std::wstring insert; 
    insert.reserve(10000); // or however long you anticipate the longest string to be. 
    //this is a very minor optimisation. don't worry if you get it wrong 

    for(;;) // more idiomatic 
    { 
     static constexpr auto sequence = L"`/`"; 
     static constexpr auto sequence_length = std::extent<decltype(sequence)>::value - 1; 

     insert.clear();  // assuming we don't want residue from the previous iteration 
     build_string(insert); // pass a reference 
     //... 
     if (insert.empty()){ 
     //... 
      break; // ? 
     } 
     else if (insert.size() >= sequence_length    // important! 
       and std::equal(insert.begin(), 
           std::next(insert.begin(), sequence_length), 
           sequence))   // will compile to memcmp 
     { 
     } 
     else if (insert[0] == L'\t'){ 
     //... 
     } 
     else if (insert[0] == L'#') { 
      break; 
     } 
     else { /*...*/ } 
    } 
} 
+0

それは非常に役に立ちましたが、最初に私が知りたいと思ったものを正確に説明しました(私の質問を正しく指定しなかったのは残念です)。もう1つ質問: 'size()'またはunsigned int value(constなので)の代わりに 'std :: extent :: value'を使う目的は何ですか? – LightTab2

+0

@ LightTab2あなたが喜んで尋ねました。 extent <>は、配列内の要素の数を返します。 sizeof(バイト)の配列の場合にのみsizeofと同じです。あなたのケースでは、実装に依存するサイズを持つwchar_tを使用しています。エクステント<>はポータブルです。 –

+0

'sequence_length = std :: extent :: value'の結果は、効果があっても常に0です。私はVisual Studio 2013で作業していますので、 'constexpr'は私にとってはアクセスできません(私のバージョンは問題ですか?)。代わりに 'const'と' 'normal ''変数を使用しようとしました。私はおそらく愚かな間違いをしたと思うが、分析の2時間後に私はそれを見つけることができなかった。私が 'sizeof'を使っているので問題にはなりません。それが原因で何が起こるか不思議です。私はあなたに多くの時間を無駄にせず、すべての助けを感謝します。) – LightTab2

関連する問題