帮助C#.NET通用集合的性能和优化
我试图优化一段.NET 2.0 C#代码,如下所示:帮助C#.NET通用集合的性能和优化,c#,.net,performance,generics,dictionary,C#,.net,Performance,Generics,Dictionary,我试图优化一段.NET 2.0 C#代码,如下所示: Dictionary<myType, string> myDictionary = new Dictionary<myType, string>(); // some other stuff // inside a loop check if key is there and if not add element if(!myDictionary.ContainsKey(currentKey)) { myDict
Dictionary<myType, string> myDictionary = new Dictionary<myType, string>();
// some other stuff
// inside a loop check if key is there and if not add element
if(!myDictionary.ContainsKey(currentKey))
{
myDictionary.Add(currentKey, "");
}
Dictionary myDictionary=newdictionary();
//一些其他的东西
//在循环内部,检查键是否存在,如果不存在,则添加元素
如果(!myDictionary.ContainsKey(currentKey))
{
myDictionary.Add(currentKey,“”);
}
似乎编写这段代码的人已经使用过字典,即使不需要(只有键用于存储唯一值列表),因为它比用于搜索的myType对象列表快。
这似乎显然是错误的,因为这只是字典的关键,但我正在努力理解什么是修复它的最佳方法
问题:
1)我似乎明白,即使只使用.NET 3.5哈希集,我也能获得很好的性能提升。这是正确的吗?
2)在.NET 2.0中优化上述代码的最佳方法是什么?为什么?
编辑:
这是我正在尝试优化的现有代码,它在成千上万个项目中循环,每一个项目都调用一个ContainsKey。一定有更好的方法(即使是在.NET2.0中)!:) 我想你需要把这个问题分解成两个问题
Dictionary
是否是此场景的最佳可用类型
不可以。根据您的细分,HashSet
显然是更好的选择,因为它的使用模式更符合场景
切换到Hashset
会提高性能吗?
这是非常主观的,只有剖析者才能给你这个问题的答案。您可能会看到集合中每个元素的内存大小都有很小的改进。但就原始计算能力而言,我怀疑你会看到巨大的差异。只有探查器才能告诉您是否有
在对代码进行与性能相关的更改之前,请记住黄金法则
在分析器准确地告诉您代码的错误之前,不要进行任何与性能相关的更改
做出违反此规则的更改只是猜测。探查器是衡量性能修复成功与否的唯一方法 1)否。字典对键进行哈希运算,因此您的查找应该是O(1)。不过,哈希集应该会减少所需的内存。但老实说,这并没有让你真正看到性能的提升
2) 请给我们更多的细节,告诉我们你想要完成什么。你发布的代码非常简单。你量过尺寸了吗?你看到这个方法很慢吗?不要忘记“我们应该忘记小效率,比如说97%的时间:过早优化是万恶之源。”——Donald Knuth
如果该键已经存在,则该值将被替换,不会引发任何异常。此外,如果该值根本没有使用,我个人将使用空值来填充它。我看不出有任何理由在那里使用任何字符串常量。scottm提到的可能性能降低不是因为进行简单的查找。它是针对c的计算两个集合之间的交集。HashSet的查找速度确实比Dictionary快一些。不过,正如大家所说,性能差异实际上非常小——查找占用了大部分时间&创建KeyValuePair只需很少的时间 对于2.0,可以将“值”对象设置为以下对象之一:
public struct Empty {}
它可能比“”略胜一筹
或者您可以尝试在2.0项目中引用System.Core.dll,以便使用哈希集
另外,请确保GetHashCode和Equals对MyType尽可能有效。我曾经因为在GetHashCode非常慢的事情上使用字典而被咬过(我相信我们试图使用委托作为键或类似的东西)。@Rex,我把它做得更大了一点:)+1同意。最后一句话是帖子中最重要的部分如果这是.NET 2.0,那么
字典
可能是最好的选择,因为哈希集
仅在.NET 3.5中添加。@divo,这取决于您添加的键的数量以及您是否计划使用重复的键。ContainsKey()方法每次都会迭代字典中的每一项,因此随着字典的增长,“simple if”可能会成为一大亮点。如果您不打算拥有副本,那么就不会对控制流使用异常,因为您不希望抛出异常。在这种情况下,它可能比if更便宜。我期待重复,我需要过滤掉它们-捕获异常,即使将其用于流控制是错误的,听起来比每次调用ContainsKey要好(大多数项目不会重复),但是它会提高性能吗?你应该遵循JaredPar在这个问题上的建议。如果这部分代码已经明显影响了性能,您可以尝试更改,看看是否有收获。谢谢-我知道过早优化是不好的。这是我正在尝试优化的现有代码,它在成千上万个项目中循环,每一个项目都调用一个ContainsKey。一定有更好的方法做这件事!:)你应该进一步完善你的编辑。你为什么要在成千上万的物品中循环?你能把它并行化吗?我从一堆文件中得到一个可能有重复的对象列表,然后循环遍历这些项目并将它们添加到
public struct Empty {}