查找列表中复杂类型的最快方法(Vector,Array,Dictionary,更快)

时间:2011-04-12 15:48:02

标签: actionscript-3 performance object-pooling

冰雹,堆叠!

我需要知道在复杂类型(对象和精灵的扩展)中找到列表中的项目(Vector,Array,Dictionary,更快)的最佳方法。
我曾经使用过“Haystack中的针”方法,但似乎它还不够快。


E.g。 假设我有一个 Sprites 的集合(实际上是一个池) 每个精灵都将被添加到舞台并执行一些动作。在那之后,它会死 我不想支付处理它的费用(垃圾收集)并且每次都创建另一个(新的),所以我会将死亡的精灵保存在一个集合中。

有时候我会调用一个方法来为舞台添加一个精灵 如果它没有任何可用的精灵,那么这个精灵可能是旧的,如果它已经死了,或者是一个新精灵。


让我想到这个问题的一个场景是粒子系统 一个“头”粒子,每一帧都留下一条粒子的“痕迹”,并爆炸成一团华丽的粒子......每一帧......

有时这会产生50.000个PNG,包括运动,旋转,alpha,事件调度,比例等...... 但是,这只是一个场景......


目前我正在尝试使用带有链接列表的对象池...
希望运行整个Array / Vector或者每帧创建新实例会更快,让它们用Garbage Collection染色。

有人知道更好/更快的方法吗?

6 个答案:

答案 0 :(得分:2)

我不确定你在搜索什么以及你想用它做什么。 如果您要确定字符串是否在列表中,则最快的解决方案是Dictionnary。我做了一点基准。

/**
* Determine which is the fastest to find a key between array, object, vector and dictionnary
**/
public class FlashTest extends Sprite {
    public function FlashTest() {
        var array:Array = new Array();
        var object:Object = new Object();
        var dictionary:Dictionary = new Dictionary();
        var vector:Vector.<String> = new Vector.<String>();

        for (var i:int=0; i < 10000; i++)
        {
            array.push(i.toString());
            object[i.toString()] = 1;
            vector.push(i.toString());
            dictionary[i.toString()] = 1;
        }

        var time:uint = getTimer();
        for (i=0; i < 10000; i++)
        {
            array.indexOf(i.toString());
        }

        trace("array"+(getTimer()-time)); //2855

        time = getTimer();
        for (i=0; i < 10000; i++)
        {
            vector.indexOf(i.toString());
        }

        trace("vector"+(getTimer()-time)); //3644


        time = getTimer();
        for (i=0; i < 10000; i++)
        {
            object.hasOwnProperty(i.toString());
        }

        trace("object"+(getTimer()-time)); //48


        time = getTimer();
        for (i=0; i < 10000; i++)
        {
            dictionary.hasOwnProperty(i.toString());
        }

        trace("dictionary"+(getTimer()-time)); //35


    }
}

干杯!

答案 1 :(得分:1)

这实际上取决于您需要如何识别对象。您是在比较它的某些价值还是比较参考文献?

假设引用,您应该使用Array&amp; amp;向量。随着列表中项目数量的增加,线性搜索(如遍历整个列表)变得越来越慢。内置解决方案将使用更快的非线性搜索算法。例如:

myList.indexOf(myObject);

您可以做的最快的事情是直接访问。如果您使用的是对象或词典,则可以使用该对象或唯一ID作为键,这样您就可以直接访问。但是,如果您需要列表中的对象位置,这无济于事。例如:

//when setting it
var map = {};
map[myObject] = myObject;
//or
map[myObject.id] = myObject;

//then later
var myObject = map[THE KEY]

答案 2 :(得分:1)

您是否有任何可归因于对象的键?(或可能将对象用作键)

我相信字典查找可能是最快的,因为它与Java的HashMap类似。

在这种情况下,您可以将对象作为键,然后执行 myDictionary[complexObject] != null (如果没有该对象的条目,它将为null)
虽然如果您可以进一步指定您需要查找的内容,我可以提供此

的进一步应用

答案 3 :(得分:1)

根据您修改过的问题,我不认为这是一个搜索优化问题,除非我们讨论的是数千个对象。当你的一个来自池中的对象“死”时,它可以通知管理对象的代码(通过事件或回调),然后在活动项的字典中将其条目清零(或者将它从数组中拼接,或者杀死它)它带有一个标志,下面有更多内容**),并将其推送到另一个数组,这是一堆等待重用的对象。当您需要一个新对象时,首先检查您的回收堆栈中是否有任何内容,如果有,则弹出其中一个并重新初始化它。如果堆栈为空,则构造一个新堆栈。

**用于保存活动对象列表(数组/向量/字典)的数据结构的最佳选择可能取决于列表的性质 - 我愿意打赌那个数据结构最快的循环(例如,如果你需要每帧都要更新它们)不一定是最便宜的删除。您使用哪一个应该是最适合您所拥有的对象数量以及它们被删除,重新添加或更新的频率。只需做一点基准测试,就可以轻松测试它们。如果你有相对较少的对象,并且不需要连续循环它们,我会把钱放在活动池的字典上。

从这个答案得到的关键点是,你不应该在每次需要找到一个可以重复使用的死项时循环遍历所有项目,你应该在它们死亡时将它们拉出来并将其保持为单独的池。

答案 4 :(得分:0)

我会说Vector,但似乎有一些混合的结果。

Vector.<> vs array

http://impossiblearts.com/blog/2008/06/fp10-vector-vs-array/

答案 5 :(得分:0)

如果您的精灵有唯一的ID,并且您可以使用词典,那么问题是什么?字典肯定更快。

对Vector或Array的平均搜索最多需要O(log(n))时间。虽然如果您的Vector被排序,您只能实现这一点,这意味着在其他地方花费时间来确保它保持排序。如果你不对它进行排序,那么你必须扫描,这意味着O(n)。

字典(不同地称为哈希表,映射),当正确实现时(我只能假设ActionScript提供的内容正确实现)保证O(1)访问时间。你在更多的记忆中付出代价。 O(1)隐藏了一些高于Vector搜索的常数,因此对于小项目列表,Vector会更有效。但是,从您对问题的描述来看,这听起来很简单。