如何提高C#中的contrentDictionary.count的性能



最近,我需要在使用SortedDictionarySortedList之间进行选择,然后在SortedList上解决。

但是,现在我发现我的c#程序在执行sortedlist.count时爬行速度放慢,我使用称为数千次的函数/方法对其进行检查。

通常,我的程序将在35毫秒内调用10,000次功能,但是在使用SortedList.Count时,它会减慢到300-400 ms,基本上慢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>>();而且我在各个地方都有各种各样的计数,有时会在列表中检查列表中的项目,而其他时间则是汇总的。因此,该问题适用于汇总介绍,我编写了快速测试代码以确认这一点,而无需并发就需要350毫秒。这是带有均值的测试,显示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();
}

本文建议改用以下方式:

dictionary.Skip(0).Count()

一旦方法返回呼叫,计数就可能无效。例如,如果要将计数写入日志以进行跟踪目的,例如,您可以使用替代方法,例如无锁定枚举器

好吧, ConcurrentDictionary<TKey, TValue>必须一次与许多线程正常工作,因此需要一些同步开销。

Count属性的源代码:https://referencesource.microsoft.com/#mscorlib/system/collections/collections/concurrent/concurrent/concurrentdictionary.cs,40c23c8c8c36011117

    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;
        }
    }

看来您需要重构现有代码。由于您没有提供任何代码,我们无法告诉您您可以优化什么。

对于性能敏感代码,我不建议使用ConcurrentDictionary.Count属性,因为它具有锁定实现。您可以使用Interlocked.Increment代替自己进行计数。

相关内容

  • 没有找到相关文章

最新更新