相关疑难解决方法(0)

为什么ConcurrentBag <T>在.Net(4.0)中这么慢?我做错了吗?

在我开始一个项目之前,我编写了一个简单的测试来比较来自(System.Collections.Concurrent)的ConcurrentBag相对于锁定和列表的性能.我非常惊讶ConcurrentBag比使用简单的List锁定慢10倍.据我所知,当读写器是同一个线程时,ConcurrentBag效果最好.但是,我没想到它的性能会比传统的锁更糟糕.

我已经运行了一个测试,其中有两个Parallel for循环写入和读取列表/包.然而,写入本身显示了巨大的差异:

private static void ConcurrentBagTest()
   {
        int collSize = 10000000;
        Stopwatch stopWatch = new Stopwatch();
        ConcurrentBag<int> bag1 = new ConcurrentBag<int>();

        stopWatch.Start();


        Parallel.For(0, collSize, delegate(int i)
        {
            bag1.Add(i);
        });


        stopWatch.Stop();
        Console.WriteLine("Elapsed Time = {0}", 
                          stopWatch.Elapsed.TotalSeconds);
 }
Run Code Online (Sandbox Code Playgroud)

在我的盒子上,这需要3-4秒才能运行,相比之下这段代码的0.5-0.9秒:

       private static void LockCollTest()
       {
        int collSize = 10000000;
        object list1_lock=new object();
        List<int> lst1 = new List<int>(collSize);

        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();


        Parallel.For(0, collSize, delegate(int i)
            {
                lock(list1_lock)
                {
                    lst1.Add(i);
                }
            });

        stopWatch.Stop();
        Console.WriteLine("Elapsed = {0}", 
                          stopWatch.Elapsed.TotalSeconds);
       }
Run Code Online (Sandbox Code Playgroud)

正如我所提到的,进行并发读写并不能帮助并发包测试.我做错了什么还是这个数据结构真的很慢?

[编辑] - …

.net c# concurrency locking concurrent-collections

42
推荐指数
5
解决办法
3万
查看次数

为什么Queue(T)和Stack(T)没有实现ICollection(T)?

之前,我甚至问,让我得到了明显的答案的方式进行:ICollection<T>接口包括Remove删除任意元素,该方法Queue<T>Stack<T>不能真正支持(因为他们只能删除"结束"元素).

好的,我意识到了.实际上,我的问题并不是关于Queue<T>Stack<T>收集类型; 更确切地说,它是关于不执行的设计决定ICollection<T>任何泛型类型是基本的集合T值.

这是我觉得奇怪的事情.假设我有一个接受任意集合的方法T,并且出于我正在编写的代码的目的,知道集合的大小会很有用.例如(以下代码是微不足道的,仅供参考!):

// Argument validation omitted for brevity.
static IEnumerable<T> FirstHalf<T>(this ICollection<T> source)
{
    int i = 0;
    foreach (T item in source)
    {
        yield return item;
        if ((++i) >= (source.Count / 2))
        {
            break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,除了那些类型没有实现之外,没有理由为什么这个代码不能在a Queue<T>或a 上运行.当然,他们确实实现了 - 我主要是为了单独测试属性 - 但是这会导致像这样的奇怪的优化代码:Stack<T>ICollection<T>ICollectionCount

// OK, so to accommodate …
Run Code Online (Sandbox Code Playgroud)

.net queue stack interface icollection

15
推荐指数
1
解决办法
1377
查看次数