在列表中查找复杂类型的最快方法(向量、数组、字典,无论哪种更快)

发布于 2024-11-01 13:22:17 字数 577 浏览 1 评论 0原文

冰雹,斯塔克!

我需要知道在复杂类型(对象和精灵的扩展)列表(向量、数组、字典,任何更快的)中查找项目的最佳方法。
我用过“大海捞针”的方法,但似乎速度不够快。


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

有时我会调用一个方法来将精灵添加到舞台上。
如果该精灵已经死亡,则该精灵可以是旧精灵;如果池中没有任何空闲精灵,则该精灵可以是新精灵。


促使我提出这个问题的场景之一是粒子系统。
一个“头部”粒子每帧都会留下一条粒子“踪迹”,然后爆炸成大量华丽的粒子...每一帧...

有时这会计算出多达 50.000 个 PNG,包括运动、旋转、Alpha、事件调度、缩放、等等...
但是,这只是一种情况...


目前我正在尝试使用带有链接列表的对象池...
希望运行整个数组/向量或每帧创建新实例并让它们用垃圾收集染色会更快。

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

Hail, Stack!

I need to know the best method to find an item inside a list (Vector, Array, Dictionary, whatever is faster) of complex type (extensions of Objects and Sprites).
I've used "Needle in Haystack" method, but it seems that it isn't fast enough.


E.g.
Suppose that I have a collection of Sprites (a pool, in fact).
Each sprite will be added to the stage and perform some action. After that, it will die.
I don't want to pay the cost to dispose it (garbage collect) and create another (new) one every time so I'll keep the dead sprites in a collection.

Sometimes times I'll call a method that will add a sprite to the stage.
This sprite can be a old one, if it is already dead, or a new one, if the pool don't have any free sprite.


One of the scenarios that pushed me to this question was a Particle System.
A "head" particle leaving a "trail" of particles every frame and exploding into a flashy multitude of particles... Every frame...

Some times this counts up to 50.000 PNGs with motion, rotation, alpha, event dispatching, scale, etc...
But, this is JUST ONE scenario...


At the moment I'm trying to use a Object Pool with a Linked List...
Hopes that it will be faster that running a whole Array/Vector or create new instances every frame an let them dye with Garbage Collection.

Someone knows a better/faster way to do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

记忆消瘦 2024-11-08 13:22:17

我不确定您正在搜索什么以及您想用它做什么。
如果您尝试确定字符串是否在列表中,最快的解决方案是字典。我做了一些基准测试。

/**
* 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


    }
}

干杯!

I'm not sure about what you are searching and what you want to do with it.
If you are trying to determine if a string is in a list, the fastest solution is the Dictionnary. I've done a little benchmark.

/**
* 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


    }
}

Cheers!

Spring初心 2024-11-08 13:22:17

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

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

从这个答案中得到的关键点是,每次您需要找到一个死的物品来重复使用时,您不应该循环遍历所有物品,您应该在它们死后将它们拉出来并将其保留为一个单独的池。

Based on your revised question, I don't see this as a search optimization issue unless we're talking about thousands of objects. When one of your objects from the pool "dies", it could notify your code that is managing the objects (by event or callback) and you then null out its entry in your Dictionary of active items (or splice it from Array, or kill it with a flag, more on this below**), and push it onto another Array, which is a stack of objects waiting to be reused. When you need a new object, you first check if there is anything in your recycle stack, and if there is, you pop one of those and re-initialize it. If the stack is empty, you construct a new one.

**The best choice of which data structure you use for holding your active objects list (Array/Vector/Dictionary) will probably depend on the nature of your list--I'd be willing to bet that the data structure that is quickest to loop over (for example if you need to do it every frame to update them) is not necessarily the one that is cheapest to delete from. Which one you go with should be whichever works best for the number of objects you've got and the frequency with which they get removed, re-added or updated. Just do a little benchmarking, it's easy enough to test them all. If you have relatively few objects, and don't need to loop over them continuously, I'd put my money on the Dictionary for the active pool.

The key point to get from this answer is that you should not be looping through all the items each time you need to find a dead one to re-use, you should pull them out when they die and keep that as a separate pool.

栖竹 2024-11-08 13:22:17

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

假设引用,您应该使用 Array 和 Array 上找到的内置方法。向量。随着列表中项目数量的增加,线性搜索(例如循环整个列表)会变慢。内置解决方案将使用更快的非线性搜索算法。例如:

myList.indexOf(myObject);

您能做的最快的事情就是直接访问。如果您使用对象或字典,则可以使用对象或唯一 ID 作为键,这样您就可以直接访问。但如果您需要列表中的对象位置,这并没有帮助。例如:

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

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

This is really going to depend on how you need to identify the object. Are you comparing some value of it or comparing references?

Assuming references, you should be using the built in methods found on both Array & Vector. Linear searches (like looping over the entire list) grow slower as the number of items in the list increases. The built in solutions will use faster non-linear search algorithms. For example:

myList.indexOf(myObject);

The fastest thing you can do is direct access. If you are using either an Object or Dictionary you can use the object or a unique id as the key, this gives you direct access. But this doesn't help if you need the objects position in the list. eg:

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

//then later
var myObject = map[THE KEY]
隔纱相望 2024-11-08 13:22:17

你有任何类型的键可以归因于对象吗?(或者可能使用对象作为键)

我相信字典查找可能是最快的,因为它的完成方式类似于Java的HashMap。

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

Do you have any sort of key that can be attributed to the objects?(or possibly use the object as a key)

I believe that a Dictionary look up would probably be the fastest since it is done similar to Java's HashMap.

In that case you could have the object as the key and just do
myDictionary[complexObject] != null
(it will be null if there is no entry of that object)
Although if you could specify further what it is you need to lookup I might be able to offer further application of this

∞觅青森が 2024-11-08 13:22:17

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

Vector 或 Array 上的平均搜索最多花费 O(log(n)) 时间。不过,只有在 Vector 已排序的情况下才能实现这一点,这意味着要花时间在其他地方以确保它保持排序。如果不排序就必须扫描,这意味着 O(n)。

字典(也称为哈希表、映射)在正确实现时(我只能假设 Actionscript 提供的内容实现正确)保证 O(1) 访问时间。你为此付出了更多内存的代价。 O(1) 隐藏了一些比向量搜索更高的常数时间,因此对于较小的项目列表,向量会更有效。然而,从你的问题描述来看,这听起来是理所当然的。

If your sprites have unique IDs, and you can use a Dictionary, then what's the question? Dictionary is definitely faster.

The average search on a Vector or Array takes, at best, O(log(n)) time. Though you can only achieve that if your Vector is sorted, which means spending time elsewhere to ensure it stays sorted. If you don't sort it then you have to scan, which means O(n).

Dictionaries (variously known as hashtables, maps), when implemented right (and I can only assume that what Actionscript provides is implemented right) guarantee O(1) access time. You pay for that in more memory. The O(1) hides some constant times that are higher than those of Vector searches, so for small lists of items Vector would be more efficient. However, from the description of your problem it sounds like a no-brainer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文