【发布时间】:2014-01-14 14:14:32
【问题描述】:
我正在编写一个专注于性能的 2D 无限地形编辑器。每次用户绘画时,他都会创建Nodes,此时将其分配给“图层”类中的字典。由于用户可以在不同图层上绘制现有节点,因此我想找到这些节点并销毁它们。根据我目前的设置,这将涉及遍历所有层并从字典中一个一个获取必要的节点。
显然,如果每帧执行数万次,这太昂贵了。所以现在我想我可以只创建一个包含列表中所有节点的字典。然而,事实证明这几乎与之前的设置一样使用了性能,因为现在我必须在实例化新节点时检查 Key 是否已经存在:
之前:
public Node(){
dic.Add(key,this);
}
现在:
public Node(){
List<Node> nodes;
if(dic.TryGetValue(key,out nodes))
nodes.Add(this);
else{
list = new List<Node>();
dic.Add(key,list);
}
}
如您所见,虽然当前设置在检查节点时节省了一些性能,但它通过将实例化时间扩大到字典查找时间而完全破坏了效果。
所以现在我正在寻找某种方法来获得与 Dictionary<Key,List<Node>> 相同的效果,但无需在字典中查找列表的成本。是否有一种不同类型的字典可以让每个键堆叠无限(或如果必要的话)数量的值?
或者,是否有可能以某种方式对字典中的值进行排序,以便我可以使用普通的Dictionary<key, Node>,然后查找第一个键并从那里循环遍历所有值,直到我点击某个不再适合的节点搜索条件?
在伪代码中,我的实例化函数如下所示:
public Node(){
dic.Add(key+LayerIndex,this);
}
我的查找函数看起来像这样
public LookUpAll(key, out list){
var o = dic[key]; // looking up just one node
list.Add(o);
var keyPosition = o.keyPosition;
while(o.position == keyPosition){ // then looping through all other nodes at that position until one comes that has a different position.
o = dic.NextValue();
list.Add(o);
}
}
现在,这在未排序的字典中不起作用,但因为我希望这里的某个人可以从中获得一些灵感并制定一个可行的解决方案。
如何在我的场景中减少查找次数,或者在不先查找键的情况下为每个键添加多个值?
【问题讨论】:
-
你确定字典查找是这个过程的瓶颈吗?
-
我现在已经运行了一些基准测试,如果我实例化 500^2 个节点,那么检查的性能成本增加在 1/2 和 1 % 之间。老实说,我希望它会更大,因为它曾经是过去的主要瓶颈,直到我覆盖了哈希函数,但即便如此,摆脱它还是不错的,特别是因为我希望进一步提高性能而且我不希望这件事在未来成为真正的瓶颈。
-
对于您的替代解决方案,请考虑使用 SortedDictionary
。然后,您将传递您自己的 IComparer 实现作为键,以便对字典进行正确排序以满足您的查找要求。我不能说这会或多或少的表现。 -
@aaron 谢谢,我会试一试的,我已经辞职重新坐在板凳上写一些 n-tree 解决方案,但是正确排序的字典会容易得多。跨度>
标签: c# .net dictionary