4

私は最近、C# で C5 コレクションをテストしており、その機能が気に入っています。大規模なコレクションの場合、パフォーマンスは一般的なコレクションと同等のようです。ただし、小さなコレクションの場合は、大幅に遅くなります。相対速度の劇的な低下は、C5 コレクションによって実行される一定時間の操作に起因すると思われます。私が知っている 1 つの操作は、イベントの発生です。これが小さなコレクションのパフォーマンス低下の原因でしょうか? これは、一部の機能をオフにすることで解決できるでしょうか? パフォーマンステストは次のとおりです。

//Two containers to be tested. 'Test' is a wrapper over decimal.
var arrayList = new C5.ArrayList<Test>();
var genericList = new System.Collections.Generic.List<Test>();

var toBeAdded = new List<Test>();
var watch = new Stopwatch();

//Fill both tested containers
for (int i = 10; i > 0; i--)
{
    var test = new Test(i);
    genericList.Add(test);
    arrayList.Add(test);
}

//Fill the container the range of which will be inserted to the tested containers
for (int i = 5; i > 0; i--)
{
    toBeAdded.Add(new Test(i+0.5m));
}


//Test the speed of adding a range of values and sorting for both containers
watch.Start();
genericList.AddRange(toBeAdded);
Console.WriteLine("Adding values for generic list: {0} ticks", watch.ElapsedTicks);
watch.Restart();
genericList.Sort();
Console.WriteLine("Sorting for generic list: {0} ticks", watch.ElapsedTicks);

watch.Restart();
arrayList.AddAll(toBeAdded);
Console.WriteLine("Adding values for C5 ArrayList: {0} ticks", watch.ElapsedTicks);
watch.Restart();
arrayList.Sort();
Console.WriteLine("Sorting for C5 ArrayList: {0} ticks", watch.ElapsedTicks);

そしてテストクラス:

class Test : IComparable
{
    private decimal _number;
    internal Test(decimal aNumber)
    {
        _number = aNumber;
    }        
    public int CompareTo(object obj)
    {
        var test = (Test) obj;
        return _number.CompareTo(test._number);
    } 
}

出力は次のとおりです。

Adding values for generic list: 56 ticks
Sorting for generic list: 770 ticks
Adding values for C5 ArrayList: 3575 ticks
Sorting for C5 ArrayList: 4815 ticks

C5 とテストは両方ともリリース ビルドです。挿入の約 60 倍と並べ替えの約 6 倍の速度の比率は、テスト実行間で一貫しています。

編集: 上記のテストは VS 内から実行されました。VS の外部で実行した結果は次のとおりです。

Adding values for generic list: 54 ticks
Sorting for generic list: 2135 ticks
Adding values for C5 ArrayList: 5765 ticks
Sorting for C5 ArrayList: 5198 ticks

繰り返しますが、挿入の場合は約 100 倍、並べ替えの場合は 2 倍の速度の比率は、テスト実行間で一貫しています。

私のプロジェクトには小さなコンテナの操作が多く含まれており、そのパフォーマンスが最も重要です。C5 コンテナーの機能は素晴らしく、ぜひ使用したいと思っていますが、現時点ではパフォーマンス上の理由から使用できません。この問題に関する洞察をいただければ幸いです。

EDIT2: Iridium の回答に従って、テストをループで実行し (コンテナーの作成を含むロジック全体をループに入れて、コンパイラーの最適化のトリックを除外します)、最初の 2 つの結果を破棄し、その後の 1000 の結果を平均しました。どうぞ:

Adding values for generic list: 1.09 ticks
Sorting for generic list: 14.07 ticks
Adding values for C5 ArrayList: 1.92 ticks
Sorting for C5 ArrayList: 13.69 ticks

現在、C5 の挿入は 76% 遅くなり、並べ替えは List と同等になりました。それは私の目的には十分です。Iridiumの回答を受け入れています。それでも、遅い挿入について誰かが洞察を持っている場合は、それを共有してください. 助けてくれてありがとう。

4

1 に答える 1

5

あなたの結果が少し誤解を招くかどうか、そして C5 で見られる違いは実際には (おそらく) add/sort メソッドを最初に使用する際のアセンブリの読み込み/JIT コンパイルのオーバーヘッドによるものではないかと思います。システム アセンブリが既にロード/NGen されているため、ジェネリック コレクションはこれに悩まされていません。

C5 2.1.4596.30350 を使用してテストを繰り返しましたが、テスト全体を複数回実行しました (1 回限りのオーバーヘッドを避けるために、アプリケーションを再起動せずに)。この結果は、C5 コレクションの最初の使用時に (JIT コンパイルのような 1 回限りのオーバーヘッドと一致する) 時間のペナルティがあることを示唆しているように思われます。

反復実行でのジェネリックと C5 の追加と並べ替えのグラフ]

于 2012-10-03T07:51:41.540 に答える