Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.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# GetOrAdd新产品与出厂性能_C#_Performance_Concurrentdictionary - Fatal编程技术网

C# GetOrAdd新产品与出厂性能

C# GetOrAdd新产品与出厂性能,c#,performance,concurrentdictionary,C#,Performance,Concurrentdictionary,以下哪两段代码在不同的情况下性能更好?为什么 1 private readonly ConcurrentDictionary<int, List<T>> _coll; _coll.GetOrAdd(1, new List<T>()); private readonly ConcurrentDictionary<int, List<T>> _coll; _coll.GetOrAdd(1, (val) => new List<

以下哪两段代码在不同的情况下性能更好?为什么

1

private readonly ConcurrentDictionary<int, List<T>> _coll;
_coll.GetOrAdd(1, new List<T>());
private readonly ConcurrentDictionary<int, List<T>> _coll;
_coll.GetOrAdd(1, (val) => new List<T>());

这只会按需创建
列表,但有一个委托调用。

我无法想象您会看到性能上的很大差异,除非您使用的是非常大的数据集。这还取决于你的每件物品被击中的可能性。泛型在运行时级别得到了非常好的优化,使用委托会导致分配


我的建议是使用
Enumerable.Empty()
为每个数组项保存分配。

就内存而言,第一种方法每次都会导致分配,而第二种方法将使用缓存的委托对象,因为它不捕获任何变量。编译器处理缓存委托的生成。容量设置为零的第一种情况没有区别,因为
List
的默认构造函数在初始化时使用空数组,与显式容量0相同

就执行指令而言,由于未使用第二个参数,因此在找到键时它们是相同的。如果找不到键,第一种方法只需读取一个局部变量,而第二种方法将有一个间接层来调用委托。此外,带有工厂的GetOrAdd似乎会执行额外的查找(通过TryGetValue),以避免调用工厂。委托也可能被执行多次。GetOrAdd只保证在字典中看到一个条目,而不是只调用一次工厂

总之,如果通常找不到密钥,那么第一种方法的性能可能更高,因为无论如何都需要进行分配,并且没有通过委托进行间接寻址。但是,如果通常可以找到密钥,则第二种方法的性能更高,因为分配更少。对于缓存中的实现,您通常希望有大量的命中率,因此如果是这样,我建议使用第二种方法。实际上,两者之间的区别取决于整个应用程序对该代码路径中的分配的敏感程度


另外,无论使用此函数的实现是什么,都可能需要在返回的
列表
周围实现锁定,因为它不是线程安全的。

我使用了
列表
作为示例,它所在的实际集合是线程安全的。此外,根据Joseph的建议,
()=>Enumerable.Empty()
是否有助于提高性能?此外,它似乎取决于使用的框架版本(以及是否实现了新行为),就像.NET 4.5中的情况一样,在.NET 4.5中,更改会产生一些不希望的副作用。如果要使用
Enumerable.Empty()
则不需要委托,请参阅@Hele Well
Enumerable.Empty()
只读取一个静态只读字段。但是我不知道为什么要使用像
IEnumerable
这样的只读接口。我怀疑这会使更新更加困难,但我需要看到更多的代码。@Alex有趣。。。我想深入研究一下代码,getoraddwithfactory包含了一些额外的查找。我可以补充一点。