2

関数型プログラミングを始めて、クラス/プロパティをいつ変更可能にするべきかを理解しようとしています。

多数の文字列連結を処理する場合、たとえば次のようにStringBuilderを使用する方がよいことがわかります。

using System;
using System.Diagnostics;
using System.Text;

namespace ConsoleApplication3
{
    internal class Program
    {
        private static string myStr;
        private static readonly StringBuilder mySb = new StringBuilder();

        private static void Main(string[] args)
        {
            Profile("+", 100000, () => myStr = myStr + "a"); // Takes 2236 ms
            Profile("SB", 100000, () => mySb.Append("a")); // Takes 1 ms
        }

        private static void Profile(string description, int iterations, Action func)
        {
            // clean up
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();

            // warm up 
            func();

            Stopwatch watch = Stopwatch.StartNew();
            for (int i = 0; i < iterations; i++)
            {
                func();
            }
            watch.Stop();
            Console.Write(description);
            Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
        }
    }
}

これは一般的に知られているケースであり、演算子を介して文字列を連結する方がはるかにパフォーマンスが高くなります。私の想定では、作成する文字列の数を減らすことでパフォーマンスが向上します。StringBuilder+StringBuilder

パフォーマンスと不変性のバランスはありますか、それともこの場合は何らかの理由で例外ですか?

4

1 に答える 1

6

文字列を効率的に結合することは、可変構造と不変構造ではなく、O(1)追加をサポートするための適切なデータ構造と評価戦略を選択することです。

通常、さまざまな種類のツリーを使用して、共有を最大化し、コピーを最小化する高速追加をサポートします。構造の例には、ロープフィンガーツリーが含まれます。

遅延評価も場合によっては役立ちます(たとえば、連結にコピーが含まれる場合、文字列の末尾が実際に必要な場合に遅延する可能性があります)。このような場合、厳密なデータ構造では追加のコピーオーバーヘッドが発生し、必要以上の作業が発生する可能性があります。

あなたの場合、+引数の厳密なコピー(つまり、O(n + m))が必要であると思われますが、文字列ビルダーは、文字列バッファーの再割り当てを償却することで(ツリーのようなパフォーマンスを提供し、構造の線形使用を必要とし、スレッドセーフを失うという犠牲を払って)。

于 2012-07-03T15:46:55.800 に答える