4

最近、 と のどちらを使用するかを選択する必要がSortedDictionaryありSortedList、 に落ち着きましたSortedList

ただし、SortedList.Count を実行すると、C# プログラムの速度が低下することがわかりました。これは、何千回も呼び出された関数/メソッドを使用して確認しています。

通常、私のプログラムは 35 ミリ秒以内に関数を 10,000 回呼び出しますが、 を使用している間SortedList.Countは 300 ~ 400 ミリ秒に遅くなり、基本的には 10 倍遅くなりました。

も試しSortedList.Keys.Countましたが、これによりパフォーマンスがさらに 10 倍低下し、3000 ミリ秒を超えました。

I have only ~5000 keys/objects in SortedList<DateTime, object_name>. ソートされたリストから簡単かつ瞬時にデータを取得できるSortedList[date] (in 35 ms)ので、リスト構造や保持しているオブジェクトに問題はありません。

この性能は正常ですか?

リスト内のレコード数を取得するため、またはリストにデータが入力されていることを確認するために、他に何が使用できますか? (別の追跡フラグを追加する以外に、今のところそうするかもしれません)

訂正: 申し訳ありませんが、私は実際に使用して ConcurrentDictionary<string, SortedList<DateTime, string>> dict_list = new ConcurrentDictionary<string, SortedList<DateTime, string>>(); います: そして、さまざまな場所でさまざまなカウントがあり、リスト内のアイテムをチェックしたり、ConcurrentDicitonary でアイテムをチェックしたりしました。したがって、問題は ConcurrentDicitonary に適用され、これを確認するための簡単なテスト コードを作成しました。これには、同時実行性を使用せずに 350 ミリ秒かかります。これは ConcurrentDicitonary を使用したテストで、350 ミリ秒を示しています。

public static void CountTest()
{
    //Create test ConcurrentDictionary
    ConcurrentDictionary<int, string> test_dict = new ConcurrentDictionary<int, string>();
    for (int i = 0; i < 50000; i++)
    {
        test_dict[i] = "ABC";
    }

    //Access .Count property 10,000 times
    int tick_count = Environment.TickCount;
    for (int i = 1; i <= 10000; i++)
    {
        int dict_count = test_dict.Count;
    }

    Console.WriteLine(string.Format("Time: {0} ms", Environment.TickCount - tick_count));
    Console.ReadKey();
}
4

3 に答える 3

2

まあ、ConcurrentDictionary<TKey, TValue>一度に多くのスレッドで適切に動作する必要があるため、同期のオーバーヘッドが必要です。

Countプロパティのソース コード: https://referencesource.microsoft.com/#mscorlib/system/Collections/Concurrent/ConcurrentDictionary.cs,40c23c8c36011417

    public int Count
    {
        [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
        get
        {
            int count = 0;

            int acquiredLocks = 0;
            try
            {
                // Acquire all locks
                AcquireAllLocks(ref acquiredLocks);

                // Compute the count, we allow overflow
                for (int i = 0; i < m_tables.m_countPerLock.Length; i++)
                {
                    count += m_tables.m_countPerLock[i];
                }

            }
            finally
            {
                // Release locks that have been acquired earlier
                ReleaseLocks(0, acquiredLocks);
            }

            return count;
        }
    }

既存のコードをリファクタリングする必要があるようです。コードが提供されていないため、何を最適化できるかはわかりません。

于 2016-12-23T10:05:34.793 に答える