Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么LINQ在列表中搜索查询更快<&燃气轮机;与ConcurrentBag相比<&燃气轮机;_C#_Linq - Fatal编程技术网

C# 为什么LINQ在列表中搜索查询更快<&燃气轮机;与ConcurrentBag相比<&燃气轮机;

C# 为什么LINQ在列表中搜索查询更快<&燃气轮机;与ConcurrentBag相比<&燃气轮机;,c#,linq,C#,Linq,我有一个包含1亿个实体的列表集合。当我执行一个简单的LinqWhere()查询时,搜索大约需要48个刻度(10000个刻度=1ms),而将1亿个实体放入ConcurrentBag中,然后对其使用相同的搜索查询需要58个刻度 我已经重复了多次测试,但差别仍然很小。 有人能详细说明为什么会有性能差异吗?来自以下规范: 枚举表示行李内容的即时快照。它不反映调用GetEnumerator后对集合的任何更新。枚举器可以安全地与从包读取和写入包的操作同时使用 在内部,ConcurrentBag在每次枚举时创

我有一个包含1亿个实体的列表集合。当我执行一个简单的Linq
Where()
查询时,搜索大约需要48个刻度(10000个刻度=1ms),而将1亿个实体放入
ConcurrentBag
中,然后对其使用相同的搜索查询需要58个刻度

我已经重复了多次测试,但差别仍然很小。 有人能详细说明为什么会有性能差异吗?

来自以下规范:

枚举表示行李内容的即时快照。它不反映调用GetEnumerator后对集合的任何更新。枚举器可以安全地与从包读取和写入包的操作同时使用

在内部,
ConcurrentBag
在每次枚举时创建一个新的列表,并执行其他操作

发件人:

public IEnumerator GetEnumerator()
{
//如果袋子是空的,则为短路径
if(m_headList==null)
返回新列表().GetEnumerator();//空列表
bool-locktake=false;
尝试
{
冷冻袋(参考上锁);
返回ToList().GetEnumerator();
}
最后
{
解冻袋(带锁);
}
}
私人名单
{
Contract.Assert(Monitor.IsEntered(GlobalListsLock));
列表=新列表();
ThreadLocalList currentList=m_headList;
while(currentList!=null)
{
节点currentNode=currentList.m_head;
while(currentNode!=null)
{
添加(currentNode.m_值);
currentNode=currentNode.m_next;
}
currentList=currentList.m_nextList;
}
退货清单;
}

当然,这肯定比在简单列表上枚举要慢。

这真的是应用程序的性能瓶颈吗?此外,如果所有集合在所有情况下都具有相同的性能,那么我们就不会有/需要多个集合类型。所以我的问题是,为什么你希望他们在这种情况下表现相同?ConcurrentBag做的事情比列表多。为什么您认为它们应该具有相同的性能?我猜
ConcurrentBag
的线程安全可能会付出代价。
public IEnumerator<T> GetEnumerator()
{
    // Short path if the bag is empty
    if (m_headList == null)
        return new List<T>().GetEnumerator(); // empty list

    bool lockTaken = false;
    try
    {
        FreezeBag(ref lockTaken);
        return ToList().GetEnumerator();
    }
    finally
    {
        UnfreezeBag(lockTaken);
    }
}

private List<T> ToList()
{
    Contract.Assert(Monitor.IsEntered(GlobalListsLock));

    List<T> list = new List<T>();
    ThreadLocalList currentList = m_headList;
    while (currentList != null)
    {
        Node currentNode = currentList.m_head;
        while (currentNode != null)
        {
            list.Add(currentNode.m_value);
            currentNode = currentNode.m_next;
        }
        currentList = currentList.m_nextList;
    }

    return list;
}