1

我一直在使用组件实体系统。
很久以前,我想改进它以使用内存池

阶段1

为简单起见,这是我的古老代码:-

Entity* entity      =new Entity();             
Com_Physic* comPhys =new Com_Physic();  

这是重构的结果:-

Ptr<Entity> entity=centerPool()->createEntity();                   //use pool
Ptr<Com_Physic> comPhys=centerPool()->create<Com_Physic>(entity);  //use pool

它真的很好用。(每个时间步使用的时间-=10%)

阶段2

现在我有强烈的愿望在任何地方都适应内存池的概念。
但是,在涉及一些数据结构的情况下,这很难。

这是一个示例函数,它返回某个实体的所有(默认)物理体。
它不是真正完整的代码,但足以显示有问题的部分:-

class SystemPhysic : public basicSystem {
    //..... other function / field .....
    public: MyArray<PhysicObject*> getAllPhysicBody(Ptr<Entity> entity){
        Ptr<Com_Physic> comPhysic=entity->get<Com_Physic>();
        MyArray<PhysicObject*> allPhy=comPhysic->physicsList; 
                                   //^ #problem
        return allPhy;
    }
};

MyArray<T>是一个类似于 的自定义数组std::vector。它使用自己的分配器。

这是它的核心:-

void reserve(int expectedSize){
    //......
    void* databaseNew=operator new [](expectedSize*sizeof(T));
    //......
}

因此,每当我调用MyArray<PhysicObject*>::operator=(),
... 粗略地说,operator new[]都会被调用。( #problem)

记忆再次碎片化。

问题

通用数据结构应该使用内存池概念吗?
如果是这样,如何专业地将内存池概念集成到数据结构中?

我只是想要一个粗略的想法。
完全不包含代码的解决方案是可以接受的。

更多技术信息

有两种类型的问题MyArray<T>:-

  1. MyArray<T>作为 Component 的一个字段(例如Com_Physic)。
  2. MyArray<T>作为从一个系统传递到另一个系统的临时消息。它创建快,删除快。(>70% , 寿命 = 1 个时间步长)

我有一个想法将它分为两​​种情况,ShortLife_MyArray<T>& LongLife_MyArray<T>,
...但我认为我让它太复杂且难以维护。

更糟糕的是,在真正的游戏中,除了 之外,还有很多种数据结构MyArray<T>,例如MyArray<T1,T2>MyMap<T1,T2>MySet<T1,&FunctionPointer>等。

我糟糕的解决方案

到目前为止,这仅显示了我的猜测列表。

解决方案 1(单例,静态)

MyArray<T>在, MyArray<T1,T2>,MyMap<T1,T2>等 中创建一个静态池字段。

所有类型的数据结构都必须在需要时使用该静态池来分配内存。

GlobalDataStructure::staticPool=topLevel()->poolPtr; 
//called only once before everything start

坏处:-

  • 它是一个静态变量。(意义不大)
  • 很难找到应该调用全局设置语句的位置。
  • (弱)我只能使用 1 个池。(我不确定这是否有问题。)
  • mutex(弱)如果我的游戏是多线程的,我必须使用锁定池。

解决方案2(占上风)

MyArray<T>在, MyArray<T1,T2>,MyMap<T1,T2>等 中创建一个非静态池字段。

每当我想创建一个新的数据结构时,
......我必须通过共享池(来自顶级游戏逻辑)。

MyArray<T> arr=MyArray<T>(topLevel()->poolPtr);  //messy

对于不同的情况,可以有许多池。这可能是好的。

当数据结构要分配时,它必须使用该池。

坏处:-

  • 我必须为所有类型的数据结构重构所有代码。
  • 我必须通过游泳池。代码会更脏一点。
  • mutex(弱)如果我的游戏是多线程的, 我必须使用锁定池。

解决方案3(懒惰的方式)

不要做任何事情,实体和组件的池应该足够了。
其他解决方案是过度工程。

4

0 回答 0