개체 풀링을 사용하면 얻을 수있는 이점을 알 수 있으며이를 벡터와 결합하려고합니다. 그러나 Vectors에 관해서는 컴파일시에만 정의 할 수 있다는 것을 알았습니다. 즉, 각각의 풀링 된 클래스에 대해 별도의 풀러 클래스가 필요하다는 것을 의미합니다. 다른 한편으로는 런타임에 풀에서 풀 (임의의 클래스를 확장)하는 무작위 클래스 인스턴스를 갖고 싶습니다. 따라서 어떤 객체 풀이 호출되는지 정확히 알지 못합니다. 그리고 풀러 클래스의 코드 시퀀스를 곱하지 않으려면 모든 풀을 UniversalPooler 클래스에 결합하여 var foo:SomeClass=UniversalPool.getFromPool(SomeClass);
과 같은 요청을 처리 할 수 있습니다. 문제는 가능한 경우 벡터를 사용하여 임의의 하위 클래스 선택을 사용하여 범용 풀러 성능을 효과적으로 구현할 수있는 방법입니다.범용 개체 풀
Q
범용 개체 풀
1
A
답변
1
예, 불행히도 Vectors
을 사용할 수 없으므로 AS3의 제네릭 구현이 매우 부족합니다.
package util.pool
{
import flash.utils.Dictionary;
public class ObjectPool
{
private var storage:Dictionary = new Dictionary();
public function ObjectPool()
{
}
private function createNew(constructor:Class, ...args):Object
{
//as3 - (facepalm), why there isn't API to path array of params to constructor
switch (args.length) {
case 0:return new constructor();
case 1:return new constructor(args[0]);
case 2:return new constructor(args[0], args[1]);
case 3:return new constructor(args[0], args[1], args[2]);
case 4:return new constructor(args[0], args[1], args[2], args[3]);
case 5:return new constructor(args[0], args[1], args[2], args[3], args[4]);
case 6:return new constructor(args[0], args[1], args[2], args[3], args[4], args[5]);
case 7:return new constructor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
case 8:return new constructor(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
case 9:return new constructor(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
case 10:return new constructor(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
default: throw new Error("too much arguments for constructor, add more switch cases :))");
}
}
public function create(constructor:Class, ...args):Object
{
var pool:Array = getOrCreatePool(constructor);
var res:*;
if(pool.length > 0)
{
res = pool.pop();
}else
{
args.unshift(constructor);
res = createNew.apply(null, args);
}
return res;
}
public function destroy(obj:Object):void
{
if(!obj) return;
if(!(obj is Object)) return;
var constructor:Class = obj["constructor"];
var pool:Array = getOrCreatePool(constructor);
pool[pool.length] = obj;
}
public function destroyArr(objs:Object):void
{
for each(var obj:Object in objs)
destroy(obj);
}
private function getOrCreatePool(constructor:Class):Array
{
var pool:Array = storage[constructor];
if(!pool)
{
pool = [];
storage[constructor] = pool;
}
return pool;
}
}
}
그것은 하나 개의 글로벌 풀로 사용할 수 있습니다 : 나는 객체 저장에 대한 클래스지도 Dictionary
및 Arrays
에 따라 다음 풀링을 사용합니다. 그리고 나는 훨씬 더 효과적인 구현이있을 수 있다고 생각하지 않는다. 그것은 일반적으로 매우 단순한 특징이다.
실제로 Dictionary + 배열을 통해 풀을 만드는 것을 고려하고있었습니다. 이것은 unresizing 배열로 바뀔 수 있다고 생각합니다. IIRC는'pop()'또는'shift()'를 호출하고'push'와'unshift'는 알려진 인덱스에 할당하는 것보다 비용이 많이 듭니다. 그러나 인덱스는 풀과 함께 저장되어야하고 우리는 이미'Dictionary [constructor] '를 한 번 호출하고 있으므로 다른 호출 또는 중첩 된 Object {a : Array, i : 현재 인덱스}는 시프트/터지는 것은 GC로 간다. 이것은 현재의 프로젝트에서는별로 중요하지 않지만 생각과 테스트가 필요합니다. – Vesper
네, 맞아요, 추가 할 때'push' 대신에 인덱스로 지정하지만, 제거를 위해서'pop'을 사용합니다. (현재 인덱스를 유지하고있을 수도 있습니다. 마지막 요소가 null 일 때 더 효과적입니다.). 이러한 테스트를 수행하려는 경우 가장 빠른 풀링 클래스를 기대합니다. – fsbmain
일반 풀 클래스의 구현에 결함이 있습니다.이 목적은 인스턴스가 필요할 때마다 실제로 새 인스턴스를 만드는 것을 방지하기위한 것입니다. ... 각 객체 생성에 대해 args를 사용하면 실제로 객체 인스턴스를 다른 것으로 대체하기 위해 Array를 만듭니다. 구현을 벤치마킹 해 보았고 고정 된 수의 args를 가진 유사한 버전과 비교 했습니까? args의 각 수에 대한 메소드를 복제하는 것이 가장 우아한 해결책은 아니지만 성능을 향하고 있다면 가치가 있어야합니다. – jauboux