私はこの質問が行われたことを知っていますが、少し違ったひねりを加えています。これは時期尚早の最適化であると指摘する人もいますが、実用性と実用性のみを求めているのであれば、これは完全に真実です。私の問題は実際的な問題に根ざしていますが、それでもまだ興味があります。
データベーススキーマ(簡単に何百ものテーブル、ビューなど)を再作成するためのスクリプトを作成する(ディスクに保存されるように)一連のSQLステートメントを作成しています。これは、私の文字列連結が追加専用であることを意味します。MSDN によると、StringBuilder は、内部バッファー (確実に char[]) を保持し、文字列文字をそこにコピーして、必要に応じて配列を再割り当てすることで機能します。
ただし、私のコードには多くの繰り返し文字列 ("CREATE TABLE ["、"GO\n" など) があります。つまり、それらがインターンされていることを利用できますが、毎回コピーされるため、StringBuilder を使用する場合はそうではありません。唯一の変数は、本質的にテーブル名であり、既にメモリ内にある他のオブジェクトの文字列として既に存在しています。
つまり、データが読み込まれ、スキーマ情報を保持するオブジェクトが作成された後、すべての文字列情報をインターンによって再利用できるということです。
それを仮定すると、インターンされた文字列へのポインターを保持するため、文字列の List または LinkedList の方が高速ではないでしょうか? 次に、正確に正しい長さの文字列全体の単一のメモリ割り当てに対して String.Concat() を 1 回呼び出すだけです。
リストはインターンされたポインターの string[] を再割り当てする必要があり、リンクされたリストはノードを作成してポインターを変更する必要があるため、「自由に」行うことはできませんが、何千ものインターンされた文字列を連結している場合、それらは彼らがより効率的であるように。
ここで、各 SQL ステートメントの文字カウントに関するヒューリスティックを考え出し、各タイプをカウントして、大まかなアイデアを得て、char[] の再割り当てを避けるために StringBuilder の容量を事前に設定できると思いますが、かなりのマージンでオーバーシュートする必要があります。再割り当ての可能性を減らします。
したがって、この場合、連結された単一の文字列を取得するのに最も速いのは次のとおりです。
- StringBuilder
- インターンされた文字列の List<string>
- インターンされた文字列の LinkedList<string>
- 容量ヒューリスティックを使用した StringBuilder
- 他の何か?
上記に対する別の質問(私は常にディスクにアクセスするとは限りません) として: 出力ファイルへの単一の StreamWriter はさらに高速でしょうか? または、List または LinkedList を使用してから、最初にメモリ内で連結する代わりに、リストからファイルに書き込みます。
編集: 要求に応じて、MSDN への参照(.NET 3.5)。「空きがある場合は新しいデータがバッファの末尾に追加されます。そうでない場合は、新しい大きなバッファが割り当てられ、元のバッファのデータが新しいバッファにコピーされ、新しいデータが新しいバッファに追加されます。バッファ。" 私にとっては、それを大きくするために再割り当てされた char[] を意味し (古いデータをサイズ変更された配列にコピーする必要があります)、追加します。