Я использую систему компонент-сущность.
Давным-давно я хотел улучшить его, чтобы использовать пул памяти.
Для простоты вот мой древний кодекс:
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%)
Теперь у меня есть сильное желание адаптировать пул памяти Концепция везде.
Однако в случаях, когда задействованы некоторые структуры данных, это сложно.
Вот пример функции, которая возвращает все физические тела (по умолчанию) определенного объекта.
Это не совсем полный код, но достаточно хороший, чтобы показать проблемную часть:
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
)
Память снова фрагментирована.
Должны ли общие структуры данных использовать концепцию пула памяти?
Если да, то как профессионально интегрировать концепцию пула памяти в структуру данных?
Я просто хочу грубую идею.
Решение, которое не содержало кода вообще, является приемлемым.
Есть 2 типа проблем MyArray<T>
: —
MyArray<T>
как поле компонента (например, Com_Physic
).MyArray<T>
как временное сообщение, которое передается из системы в другую систему. Он создан быстро, быстро удалить. (> 70%, время жизни = 1 шаг по времени) У меня есть идея разделить его на 2 случая, ShortLife_MyArray<T>
& LongLife_MyArray<T>
,
… но я думаю, что я делаю это слишком сложным и гораздо труднее поддерживать.
Чтобы усугубить проблему, в реальной игре есть также много видов структур данных, кроме MyArray<T>
например, MyArray<T1,T2>
,MyMap<T1,T2>
,MySet<T1,&FunctionPointer>
, так далее.
Это просто показывает список моих догадок.
Создать поле статического пула в MyArray<T>
, MyArray<T1,T2>
,MyMap<T1,T2>
, так далее.
Все типы структур данных должны использовать этот статический пул для выделения памяти при необходимости.
GlobalDataStructure::staticPool=topLevel()->poolPtr;
//called only once before everything start
Недостаток:-
mutex
заблокировать пул, если моя игра многопоточная.Создать нестатическое поле пула в MyArray<T>
, MyArray<T1,T2>
,MyMap<T1,T2>
, так далее.
Всякий раз, когда я хочу создать новую структуру данных,
… Мне пришлось проходить общий пул (из игровой логики верхнего уровня).
MyArray<T> arr=MyArray<T>(topLevel()->poolPtr); //messy
Может быть много пулов для разных ситуаций. Это, наверное, хорошо.
Когда структуры данных хотят выделить, он должен использовать этот пул.
Недостаток:-
mutex
заблокировать пул, если моя игра многопоточная. Ничего не делать, пулов для сущности и компонента должно быть достаточно.
Другие решения чрезмерно инженерные.
Задача ещё не решена.
Других решений пока нет …