GameObjectPool fixes
This commit is contained in:
parent
3df4361779
commit
47574e9b30
@ -11,10 +11,19 @@ GameObject::GameObject(Mono::Object managed_obj, GameObject *parent)
|
||||
: object_handle(managed_obj), parent(parent)
|
||||
{}
|
||||
|
||||
GameObject &GameObject::operator=(GameObject &&o){
|
||||
GameObject::GameObject(GameObject &&o) :
|
||||
transform(o.transform),
|
||||
components(std::move(o.components)),
|
||||
object_handle(std::move(o.object_handle)),
|
||||
parent(o.parent)
|
||||
{
|
||||
}
|
||||
|
||||
GameObject &GameObject::operator=(GameObject &&o){
|
||||
transform = o.transform;
|
||||
components = std::move(o.components);
|
||||
object_handle = std::move(o.object_handle);
|
||||
parent = o.parent;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@ -32,10 +32,15 @@ class GameObject {
|
||||
GameObject* parent;
|
||||
public:
|
||||
GameObject(Mono::Object managed_obj, GameObject* parent);
|
||||
GameObject(const GameObject& o) = delete;
|
||||
GameObject(GameObject&& o);
|
||||
|
||||
GameObject& operator=(GameObject&& o);
|
||||
|
||||
inline Transform& getTransform(){ return transform; }
|
||||
inline Transform& getTransform() { return transform; }
|
||||
inline const Transform& getTransform() const { return transform; }
|
||||
inline Mono::ObjectHandle& getObjectHandle() { return object_handle; }
|
||||
inline const Mono::ObjectHandle& getObjectHandle() const { return object_handle; }
|
||||
bool tryGetComponent(const std::u16string& name, Component** out_component);
|
||||
bool tryAddComponent(const std::u16string& name, Component&& component);
|
||||
};
|
||||
|
||||
@ -9,7 +9,7 @@ GameObjectPool::GameObjectPool(u32 size)
|
||||
first_unused_index = 0;
|
||||
buffer = new char[size*sizeof(GameObject)];
|
||||
used_indices = new u64[size/64];
|
||||
std::memset(buffer, 0, size*sizeof(GameObject));
|
||||
// std::memset(buffer, 0, size*sizeof(GameObject));
|
||||
std::memset(used_indices, 0, size/8);
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ GameObjectPool::~GameObjectPool()
|
||||
|
||||
bool GameObjectPool::isIndexUsed(u32 index)
|
||||
{
|
||||
return ( used_indices[index/64] & (1<<(index%64)) ) != 0;
|
||||
return ( used_indices[index/64] & (u64(1)<<(index%64)) ) != 0;
|
||||
}
|
||||
|
||||
u32 GameObjectPool::getNearestUnusedIndex(u32 startIndex)
|
||||
@ -38,7 +38,7 @@ u32 GameObjectPool::getNearestUnusedIndex(u32 startIndex)
|
||||
|
||||
u32 i = startIndex/64;
|
||||
// mark previous bits as used
|
||||
u64 u = used_indices[i] | ( (1<<startIndex%64) -1 );
|
||||
u64 u = used_indices[i] | ( (u64(1)<<startIndex%64) -1 );
|
||||
while(u == u64(-1)){
|
||||
i++;
|
||||
if(i == size/64)
|
||||
@ -61,7 +61,7 @@ u32 GameObjectPool::getNearestUsedIndex(u32 startIndex)
|
||||
|
||||
u32 i = startIndex/64;
|
||||
// mark previous bits as unused
|
||||
u64 u = used_indices[i] & !( (1<<startIndex%64) -1 );
|
||||
u64 u = used_indices[i] & !( (u64(1)<<startIndex%64) -1 );
|
||||
while(u == 0){
|
||||
i++;
|
||||
if(i == size/64)
|
||||
@ -84,25 +84,25 @@ GameObject& GameObjectPool::get(u32 index)
|
||||
return ((GameObject*)buffer)[index];
|
||||
}
|
||||
|
||||
std::pair<u32, GameObject&> GameObjectPool::put_new(GameObject&& new_obj)
|
||||
std::pair<u32, GameObject&> GameObjectPool::emplace(GameObject&& new_obj)
|
||||
{
|
||||
u32 i = first_unused_index;
|
||||
if(i == (u32)-1)
|
||||
if(i == u32(-1))
|
||||
throw UsefulException("can't put new GameObject to GameObjectPool because it's full");
|
||||
GameObject& r = ( ((GameObject*)buffer)[i] = std::move(new_obj) );
|
||||
used_indices[i] |= 1<<(i%64); // mark index bit as used
|
||||
used_indices[i/64] |= u64(1)<<(i%64); // mark index bit as used
|
||||
first_unused_index = getNearestUnusedIndex(i+1);
|
||||
return std::pair<u32, GameObject&>(i, r);
|
||||
}
|
||||
|
||||
void GameObjectPool::remove(u32 index)
|
||||
void GameObjectPool::erase(u32 index)
|
||||
{
|
||||
if(index >= size)
|
||||
throw UsefulException(format("index %i is out of size %i", index, size));
|
||||
if(!isIndexUsed(index))
|
||||
throw UsefulException(format("there is no object at index %i", index));
|
||||
((GameObject*)buffer)[index].~GameObject();
|
||||
used_indices[index/64] ^= ~(1<<(index%64)); // mark index bit as unused
|
||||
used_indices[index/64] &= ~(u64(1)<<(index%64)); // mark index bit as unused
|
||||
if(index < first_unused_index)
|
||||
first_unused_index = index;
|
||||
}
|
||||
|
||||
@ -1,5 +1,32 @@
|
||||
#include "GameObject.hpp"
|
||||
|
||||
/*
|
||||
Fixed array stkring deleted elements indices as bits in array of u64.
|
||||
Fast emplace, erase and lookup.
|
||||
|
||||
------------------------[construct]------------------------
|
||||
operation 'GameObjectPool::GameObjectPool()' took 1.0549 ms
|
||||
operation 'other_collections_construct' took 0.0133 ms
|
||||
-------------------------[emplace]-------------------------
|
||||
operation 'GameObjectPool::emplace' took 8.0557 ms
|
||||
operation 'vector::emplace_back' took 11.3735 ms
|
||||
operation 'set::emplace' took 80.5633 ms
|
||||
operation 'list::emplace_front' took 18.1442 ms
|
||||
operation 'forward_list::emplace_front' took 11.5467 ms
|
||||
--------------------------[erase]--------------------------
|
||||
operation 'GameObjectPool::erase' took 0.2745 ms
|
||||
operation 'vector::erase' took 15790.6 ms
|
||||
operation 'set::erase' took 1.2697 ms
|
||||
operation 'list::erase_after' took 0.93 ms
|
||||
operation 'forward_list::erase_after' took 1.1127 ms
|
||||
-------------------------[iterate]-------------------------
|
||||
operation 'GameObjectPool::iterate' took 1.1166 ms
|
||||
operation 'vector::iterate' took 0.8883 ms
|
||||
operation 'set::iterate' took 2.8011 ms
|
||||
operation 'list::iterate' took 2.0766 ms
|
||||
operation 'forward_list::iterate' took 2.0823 ms
|
||||
*/
|
||||
|
||||
class GameObjectPool {
|
||||
void* buffer;
|
||||
u64* used_indices;
|
||||
@ -9,16 +36,14 @@ class GameObjectPool {
|
||||
bool isIndexUsed(u32 index);
|
||||
u32 getNearestUnusedIndex(u32 startIndex);
|
||||
u32 getNearestUsedIndex(u32 startIndex);
|
||||
|
||||
friend class iterator;
|
||||
public:
|
||||
|
||||
///@param size must be a multiple of 64
|
||||
GameObjectPool(u32 size);
|
||||
~GameObjectPool();
|
||||
GameObject& get(u32 index);
|
||||
std::pair<u32, GameObject&> put_new(GameObject&& new_obj);
|
||||
void remove(u32 index);
|
||||
std::pair<u32, GameObject&> emplace(GameObject&& new_obj);
|
||||
void erase(u32 index);
|
||||
|
||||
class iterator {
|
||||
GameObjectPool* p;
|
||||
@ -34,4 +59,6 @@ public:
|
||||
|
||||
inline iterator begin() { return iterator(this, 0); }
|
||||
inline iterator end() { return iterator(this, -1); }
|
||||
|
||||
friend class iterator;
|
||||
};
|
||||
|
||||
@ -128,13 +128,12 @@ class ObjectHandle {
|
||||
Object object;
|
||||
u32 gc_handle;
|
||||
public:
|
||||
inline ObjectHandle() : object(nullptr), gc_handle(0) {}
|
||||
inline ObjectHandle(Object obj) : object(obj) { gc_handle = mono_gchandle_new(obj, false); }
|
||||
inline ObjectHandle(const ObjectHandle& o) = delete;
|
||||
inline ObjectHandle(ObjectHandle&& o) {
|
||||
object = o.object;
|
||||
gc_handle = o.gc_handle;
|
||||
o.gc_handle = 0;
|
||||
};
|
||||
inline ObjectHandle(ObjectHandle&& o)
|
||||
: object(o.object), gc_handle(o.gc_handle)
|
||||
{ o.gc_handle = 0; };
|
||||
inline ObjectHandle& operator=(ObjectHandle&& o) {
|
||||
object = o.object;
|
||||
gc_handle = o.gc_handle;
|
||||
@ -142,7 +141,8 @@ public:
|
||||
return *this;
|
||||
};
|
||||
inline ~ObjectHandle() { if(gc_handle) mono_gchandle_free(gc_handle); }
|
||||
inline Object getObject() { return object; }
|
||||
inline Object getObject() const { return object; }
|
||||
inline u32 getGCHandle() const { return gc_handle; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
24
src/main.cpp
24
src/main.cpp
@ -8,11 +8,22 @@
|
||||
#include "UsefulException.hpp"
|
||||
#include "Mono/Mono.hpp"
|
||||
#include "Game/GameObjectPool.hpp"
|
||||
#include <bitset>
|
||||
#include <bit>
|
||||
|
||||
using namespace ougge;
|
||||
|
||||
#define GAMEOBJECTPOOL_SIZE 64*1024
|
||||
|
||||
#define optime(N, LABEL, CODE) {\
|
||||
nsec_t b = getMonotonicTimeNsec();\
|
||||
for(u32 i = 0; i < (u32)N; i++) {\
|
||||
CODE ;\
|
||||
}\
|
||||
nsec_t e = getMonotonicTimeNsec();\
|
||||
nsec_t t = e-b;\
|
||||
std::cout<<"operation '"<<LABEL<<"' took "<<t/1e6f<<" ms"<<std::endl;\
|
||||
}\
|
||||
|
||||
|
||||
std::vector<GUI::UpdateFunc_t> updateCallbacks;
|
||||
|
||||
void update(f64 deltaTime){
|
||||
@ -28,15 +39,16 @@ int main(int argc, const char** argv){
|
||||
|
||||
Mono::RuntimeJIT mono;
|
||||
std::cout<<"initialized mono jit runtime"<<std::endl;
|
||||
GameObjectPool p(64*512);
|
||||
GameObjectPool p(GAMEOBJECTPOOL_SIZE);
|
||||
|
||||
auto a = mono.loadAssembly("Ougge.dll");
|
||||
auto gameObjectClass = a->getClass("Ougge", "GameObject");
|
||||
for(int i = 0; i < 32*1024; i++){
|
||||
for(int i = 0; i < GAMEOBJECTPOOL_SIZE; i++){
|
||||
Mono::Object gameObjectManaged = mono_object_new(mono.getDomain(), gameObjectClass);
|
||||
p.put_new(GameObject(gameObjectManaged, nullptr));
|
||||
p.emplace(GameObject(gameObjectManaged, nullptr));
|
||||
GameObject& o = p.get(0);
|
||||
std::cout<<'['<<i<<"] "<<o.getTransform()<<std::endl;
|
||||
if(i+1 % 8192 == 0)
|
||||
std::cout<<'['<<i<<"] "<<o.getTransform()<<std::endl;
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user