39

StringBuilderについて疑問に思っていたのですが、コミュニティが説明できるようになることを望んでいた質問があります。

コードの読みやすさを忘れましょう。これらのうちどれが速いのか、そしてその理由は何ですか?

StringBuilder.Append

StringBuilder sb = new StringBuilder();
sb.Append(string1);
sb.Append("----");
sb.Append(string2);

StringBuilder.AppendFormat

StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}----{1}",string1,string2);
4

9 に答える 9

45

string1とのサイズがわからないと言うことは不可能string2です。

を呼び出すとAppendFormat、フォーマット文字列と挿入される文字列の長さが指定された場合に1回だけバッファが事前に割り当てられ、すべてが連結されてバッファに挿入されます。非常に大きな文字列の場合、これはAppend、バッファが複数回拡張される可能性のある個別の呼び出しよりも有利です。

ただし、への3回の呼び出しAppendは、バッファーの拡張をトリガーする場合とトリガーしない場合があり、そのチェックは呼び出しごとに実行されます。AppendFormat文字列が十分に小さく、バッファ拡張がトリガーされない場合は、置換を行う場所を特定するためにフォーマット文字列を解析する必要がないため、呼び出しよりも高速になります。

決定的な答えを得るには、より多くのデータが必要です

クラスで静的ConcatメソッドStringを使用することについてはほとんど議論されていないことに注意してください(Jonの答えはこれをAppendWithCapacity思い出させました)。彼のテスト結果は、最良のケースであることを示しています(特定のフォーマット指定子を利用する必要がないと仮定した場合)。 String.Concatバッファを連結して事前に割り当てる文字列の長さを事前に決定するという点で同じことを行います(パラメータを介して構造をループするため、オーバーヘッドがわずかに増加します)。AppendWithCapacityその性能はジョンの方法に匹敵するでしょう。

または、単純な加算演算子です。String.Concatとにかく呼び出しにコンパイルされるため、すべての加算が同じ式であることに注意してください。

// One call to String.Concat.
string result = a + b + c;

いいえ

// Two calls to String.Concat.
string result = a + b;
result = result + c;

テストコードを提出するすべての人のために

テストケースを別々の実行で実行する必要があります(または、少なくとも、別々のテスト実行の測定の間にGCを実行します)。これは、1,000,000回実行すると、StringBuilder1つのテストのループの各反復で新しいテストが作成され、次に同じ回数ループする次のテストを実行して、追加の1,000,000StringBuilderインスタンスであるGCが作成されるためです。 2回目のテスト中に介入し、そのタイミングを妨げる可能性が高くなります。

于 2009-04-02T16:32:58.730 に答える
24

casperOne は正しいです。特定のしきい値に達すると、Append()メソッドは より遅くなりますAppendFormat()。各メソッドの 100,000 回の反復のさまざまな長さと経過したティックは次のとおりです。

長さ: 1

Append()       - 50900
AppendFormat() - 126826

長さ: 1000

Append()       - 1241938
AppendFormat() - 1337396

長さ: 10,000

Append()       - 12482051
AppendFormat() - 12740862

長さ: 20,000

Append()       - 61029875
AppendFormat() - 60483914

20,000に近い長さの文字列が導入されると、AppendFormat()関数は.Append()

なぜこれが起こるのですか?casperOne の回答を参照してください。

編集:

リリース構成で各テストを個別に再実行し、結果を更新しました。

于 2009-04-02T16:46:05.253 に答える
6

Appendコンパイラが正しいメソッドを呼び出すことを可能にするそのメソッドへの多くのオーバーロードがあるため、ほとんどの場合、より高速になります。Stringsを使用しているので、のオーバーロードをStringBuilder使用できます。 StringAppend

AppendFormatString次にaを取ります。Object[]これは、フォーマットを解析する必要がありObject、配列内のそれぞれを内部配列ToString'dに追加する前に解析する必要があることを意味します。StringBuilder's

注: casperOneの要点として、より多くのデータがなければ正確な答えを出すことは困難です。

于 2009-04-02T16:32:40.930 に答える
2

StringBuilderまた、カスケードされた appends:自体をAppend()返すStringBuilderため、次のようにコードを記述できます。

StringBuilder sb = new StringBuilder();
sb.Append(string1)
  .Append("----")
  .Append(string2);

クリーンで、生成される IL コードが少なくなります (ただし、これは実際にはマイクロ最適化です)。

于 2009-04-02T17:14:59.770 に答える
1

もちろん、それぞれの場合に確実に知っておくべきプロファイル。

とはいえ、フォーマット文字列を繰り返し解析しないので、一般的には前者になると思います。

ただし、その差は非常に小さいでしょう。AppendFormatとにかくほとんどの場合、実際に使用することを検討する必要がある点まで。

于 2009-04-02T16:31:15.193 に答える
0

あなたの場合、より速いのは1ですが、それは公正な比較ではありません。あなたはvs-に尋ねるべきですStringBuilder.AppendFormat()-charStringBuilder.Append(string.Format())配列での内部作業のために最初のものがどこでより速いか。

ただし、2番目のオプションの方が読みやすくなります。

于 2009-04-02T16:35:34.293 に答える
0

作業量が最も少なかったのは電話だったと思います。Appendは文字列を連結するだけで、AppendFormatは文字列の置換を行います。もちろん、最近では、あなたは決して言うことができません...

于 2009-04-02T16:31:30.200 に答える
0

1は単に文字列を追加するだけなので、より高速であるはずですが、2はフォーマットに基づいて文字列を作成してから、文字列を追加する必要があります。したがって、そこには追加のステップがあります。

于 2009-04-02T16:31:50.963 に答える