3

文字列を多用するWindowsCプロジェクトに取り組んでいます。マークアップされた文字列をある形式から別の形式に変換する必要があります。基本的なフローは次のようなものです。

DWORD convert(char *point, DWORD extent)
{
   char *point_end = point + extent;
   char *result = memory_alloc(1);
   char *p_result = result;

   while (point < point_end)
   {
      switch (*point)
      {
        case FOO:
          result_extent = p_result - result;
          result = memory_realloc(12);
          result += result_extent;
          *p_result++ = '\n';
          *p_result++ = '\t';
          memcpy(result, point, 10);
          point += 10;
          result += 10;
          break;
        case BAR:
          result_extent = p_result - result;
          result = memory_realloc(1);
          result += result_extent;
          *result++ = *point++;
          break;          
        default:
          point++;
          break;
      }
   }

   // assume point is big enough to take anything I would copy to it
   memcpy(point, result, result_extent);

   return result_extent;
}

memory_alloc()とmemory_realloc()は、私の質問の目的を強調するための偽の関数です。結果の「文字列」がどれくらい大きくなるかは事前にわかりません(技術的には、これは私が使用しているCスタイル/ null終端文字列ではなく、メモリアドレスと長さ/範囲へのポインタだけです)。結果の文字列のサイズを動的に変更する必要があります(入力よりも大きい場合もあれば、小さい場合もあります)。

最初のパスでは、malloc()を使用して最初のバイト/バイト用のスペースを作成し、その後、別のバイト/少数のバイトを追加する必要があるときはいつでもrealloc()を使用しました...それは機能しますが、このアプローチは不必要になりそうですOSを叩きのめすと、メモリ内のバイトが何度もシフトする可能性があります。

そこで、2番目のパスを作成しました。これは、変換の個々のユニット(FOOとBARの場合で上に示したもの)の後のresult_stringの長さを決定し、「推奨される割り当てサイズ」、たとえば256バイトを選択します。たとえば、result_extentが250バイトで、FOOの場合、メモリを12バイト(改行、タブ、入力文字列から10バイト)増やす必要があることはわかっています。260バイトのメモリを再割り当てするのではなく、 512バイトに到達し、さらにデータを追加し続ける可能性が高いという私の賭けをヘッジします(したがって、reallocへの呼び出しを数回節約できます)。

私の質問に移ります:この後者の考え方は正しいですか、それともコンパイラ/ OSがおそらくすでに私のために世話をしているのは時期尚早の最適化ですか?メモリスペースを無駄にしない以外に、必要に応じてメモリを数バイト再割り当てすることには利点がありますか?

私は、単一の変換インスタンス中に何を期待できるかについていくつかの大まかな考えを持っています。たとえば、最悪のシナリオは、結果に50〜100バイトのデータが追加される数百バイトのマークアップを含む2MBの入力文字列である可能性があります文字列、マークアップインスタンスごと(たとえば、マークアップとは別に、入力文字列から結果文字列にデータをコピーするだけで、文字列を50〜100バイト拡張する200の再割り当てと100の再割り当て)。

この件についてのご意見をいただければ幸いです。ありがとう

4

1 に答える 1

2

ご存知かもしれませんが、realloc呼び出しごとにデータを移動できます。これにより、追加のコピーが作成されます。このような場合は、操作に十分な可能性が高い大きなバッファ(上限)を割り当てる方がはるかに良いと思います。最終的に、結果に正確な金額を割り当てて、最終的なコピー/無料を行うことができます。これはより優れており、時期尚早の最適化ではありません。この場合、reallocを使用するIMOは時期尚早の最適化と見なされる可能性があります。

于 2013-01-10T03:21:05.677 に答える