Skip to content

Commit

Permalink
Optimize the performance of the memory pool. (#3414)
Browse files Browse the repository at this point in the history
  • Loading branch information
caryliu1999 committed Apr 19, 2021
1 parent 372e0fc commit 3834eca
Show file tree
Hide file tree
Showing 18 changed files with 728 additions and 637 deletions.
17 changes: 14 additions & 3 deletions cocos/bindings/dop/BufferAllocator.cpp
Expand Up @@ -29,19 +29,21 @@

namespace se {

cc::map<PoolType, BufferAllocator *> BufferAllocator::_pools;
cc::vector<BufferAllocator *> BufferAllocator::pools(BUFFER_ALLOCATOR_SIZE);

BufferAllocator::BufferAllocator(PoolType type)
: _type(type) {
BufferAllocator::_pools[_type] = this;
if (IS_BUFFER_ALLOCATOR_TYPE(type)) {
BufferAllocator::pools[GET_ARRAY_POOL_ID(type)] = this;
}
}

BufferAllocator::~BufferAllocator() {
for (auto buffer : _buffers) {
buffer.second->decRef();
}
_buffers.clear();
BufferAllocator::_pools.erase(_type);
_caches.clear();
}

Object *BufferAllocator::alloc(uint index, uint bytes) {
Expand All @@ -53,6 +55,11 @@ Object *BufferAllocator::alloc(uint index, uint bytes) {
obj->incRef();
_buffers[index] = obj;

uint8_t *ret = nullptr;
size_t len;
obj->getArrayBufferData(static_cast<uint8_t **>(&ret), &len);
_caches[index] = ret;

return obj;
}

Expand All @@ -62,6 +69,10 @@ void BufferAllocator::free(uint index) {
oldObj->decRef();
_buffers.erase(index);
}

if (_caches.count(index)) {
_caches.erase(index);
}
}

} // namespace se
66 changes: 41 additions & 25 deletions cocos/bindings/dop/BufferAllocator.h
Expand Up @@ -37,42 +37,58 @@ namespace se {
class CC_DLL BufferAllocator final : public cc::Object {
public:
template <class T>
CC_INLINE static T *getBuffer(PoolType type, uint index) {
uint size = 0;
return BufferAllocator::getBuffer<T>(type, index, &size);
static T *getBuffer(PoolType type, uint index) {
index &= BUFFER_MASK;
const auto p = GET_ARRAY_POOL_ID(type);

#ifdef CC_DEBUG
CCASSERT(BufferAllocator::pools[p] != nullptr, "BufferPool: Invalid buffer pool type");
#endif

auto *const pool = BufferAllocator::pools[p];

#ifdef CC_DEBUG
CCASSERT(pool->_caches.count(index) != 0, "BufferPool: Invalid buffer pool index");
#endif

return reinterpret_cast<T *>(pool->_caches[index]);
}

template <class T>
static T *getBuffer(PoolType type, uint index, uint *size) {
index &= _bufferMask;
if (BufferAllocator::_pools.count(type) != 0) {
const auto pool = BufferAllocator::_pools[type];
if (pool->_buffers.count(index) != 0) {
T *ret = nullptr;
size_t len;
pool->_buffers[index]->getArrayBufferData((uint8_t **)&ret, &len);
*size = (uint)len;
return ret;
} else {
return nullptr;
}
} else {
return nullptr;
}
index &= BUFFER_MASK;
const auto p = GET_ARRAY_POOL_ID(type);

#ifdef CC_DEBUG
CCASSERT(BufferAllocator::pools[p] != nullptr, "BufferPool: Invalid buffer pool type");
#endif

auto *const pool = BufferAllocator::pools[p];

#ifdef CC_DEBUG
CCASSERT(pool->_buffers.count(index) != 0, "BufferPool: Invalid buffer pool index");
#endif

T * ret = nullptr;
size_t len;
pool->_buffers[index]->getArrayBufferData(static_cast<uint8_t **>(&ret), &len);
*size = static_cast<uint>(len);
return ret;
}

BufferAllocator(PoolType type);
~BufferAllocator();
explicit BufferAllocator(PoolType type);
~BufferAllocator() override;

Object *alloc(uint index, uint bytes);
void free(uint index);
void free(uint index);

private:
static cc::map<PoolType, BufferAllocator *> _pools;
static constexpr uint _bufferMask = ~(1 << 30);
static cc::vector<BufferAllocator *> pools;
static constexpr uint BUFFER_MASK = ~(1 << 30);

cc::map<uint, Object *> _buffers;
PoolType _type = PoolType::UNKNOWN;
cc::map<uint, Object *> _buffers;
cc::map<uint, uint8_t *> _caches;
PoolType _type = PoolType::UNKNOWN;
};

} // namespace se
16 changes: 6 additions & 10 deletions cocos/bindings/dop/BufferPool.cpp
Expand Up @@ -29,33 +29,29 @@

namespace se {

cc::map<PoolType, BufferPool *> BufferPool::_poolMap;
cc::vector<BufferPool *> BufferPool::poolMap(BUFFER_POOL_SIZE);

BufferPool::BufferPool(PoolType type, uint entryBits, uint bytesPerEntry)
: _allocator(type),
_entryBits(entryBits),
_bytesPerEntry(bytesPerEntry),
_type(type) {
CCASSERT(BufferPool::_poolMap.count(type) == 0, "The type of pool is already exist");

_entriesPerChunk = 1 << entryBits;
_entryMask = _entriesPerChunk - 1;
_chunkMask = 0xffffffff & ~(_entryMask | _poolFlag);
_entryMask = _entriesPerChunk - 1;
_chunkMask = 0xffffffff & ~(_entryMask | POOL_FLAG);

_bytesPerChunk = _bytesPerEntry * _entriesPerChunk;

BufferPool::_poolMap[type] = this;
BufferPool::poolMap[GET_BUFFER_POOL_ID(type)] = this;
}

BufferPool::~BufferPool() {
BufferPool::_poolMap.erase(_type);
}
BufferPool::~BufferPool() = default;

Object *BufferPool::allocateNewChunk() {
Object *jsObj = _allocator.alloc(static_cast<uint>(_chunks.size()), _bytesPerChunk);

uint8_t *realPtr = nullptr;
size_t len = 0;
size_t len = 0;
jsObj->getArrayBufferData(&realPtr, &len);
_chunks.push_back(realPtr);

Expand Down
28 changes: 14 additions & 14 deletions cocos/bindings/dop/BufferPool.h
Expand Up @@ -25,8 +25,8 @@

#pragma once

#include "PoolType.h"
#include "BufferAllocator.h"
#include "PoolType.h"
#include "cocos/base/Macros.h"
#include "cocos/base/Object.h"
#include "cocos/base/TypeDef.h"
Expand All @@ -39,11 +39,11 @@ class CC_DLL BufferPool final : public cc::Object {
public:
using Chunk = uint8_t *;

CC_INLINE static const cc::map<PoolType, BufferPool *> &getPoolMap() { return BufferPool::_poolMap; }
CC_INLINE static const uint getPoolFlag() { return _poolFlag; }
CC_INLINE static const cc::vector<BufferPool *> &getPoolMap() { return BufferPool::poolMap; }
CC_INLINE static uint getPoolFlag() { return POOL_FLAG; }

BufferPool(PoolType type, uint entryBits, uint bytesPerEntry);
~BufferPool();
~BufferPool() override;

template <class T>
T *getTypedObject(uint id) const {
Expand All @@ -56,18 +56,18 @@ class CC_DLL BufferPool final : public cc::Object {
Object *allocateNewChunk();

private:
static cc::map<PoolType, BufferPool *> _poolMap;
static constexpr uint _poolFlag = 1 << 30;
static cc::vector<BufferPool *> poolMap;
static constexpr uint POOL_FLAG = 1 << 30;

BufferAllocator _allocator;
BufferAllocator _allocator;
cc::vector<Chunk> _chunks;
uint _entryBits = 1 << 8;
uint _chunkMask = 0;
uint _entryMask = 0;
uint _bytesPerChunk = 0;
uint _entriesPerChunk = 0;
uint _bytesPerEntry = 0;
PoolType _type = PoolType::UNKNOWN;
uint _entryBits = 1 << 8;
uint _chunkMask = 0;
uint _entryMask = 0;
uint _bytesPerChunk = 0;
uint _entriesPerChunk = 0;
uint _bytesPerEntry = 0;
PoolType _type = PoolType::UNKNOWN;
};

} // namespace se
21 changes: 14 additions & 7 deletions cocos/bindings/dop/ObjectPool.cpp
Expand Up @@ -26,22 +26,29 @@
#include "ObjectPool.h"
#include "base/memory/Memory.h"

using namespace se;

cc::map<PoolType, ObjectPool *> ObjectPool::_poolMap;
namespace se {
cc::vector<ObjectPool *> ObjectPool::poolMap(CAST_POOL_TYPE(PoolType::FRAMEBUFFER));

ObjectPool::ObjectPool(PoolType type, Object *jsArr)
: _type(type),
_jsArr(jsArr) {
CCASSERT(jsArr->isArray(), "ObjectPool: It must be initialized with a JavaScript array");
CCASSERT(ObjectPool::_poolMap.count(type) == 0, "This type of ObjectPool already exists.");

_jsArr->incRef();
_indexMask = 0xffffffff & ~_poolFlag;
ObjectPool::_poolMap.emplace(type, this);
_indexMask = 0xffffffff & ~_poolFlag;
ObjectPool::poolMap[GET_OBJECT_POOL_ID(type)] = this;
}

ObjectPool::~ObjectPool() {
_jsArr->decRef();
ObjectPool::_poolMap.erase(_type);
_array.clear();
}

void ObjectPool::bind(uint id, Object *obj) {
if (id >= _array.size()) {
_array.push_back(obj);
} else {
_array[id] = obj;
}
}
} // namespace se
39 changes: 17 additions & 22 deletions cocos/bindings/dop/ObjectPool.h
Expand Up @@ -25,48 +25,43 @@

#pragma once

#include "cocos/base/Object.h"
#include "cocos/bindings/jswrapper/Object.h"
#include "cocos/base/memory/StlAlloc.h"
#include "PoolType.h"
#include "cocos/base/Macros.h"
#include "cocos/base/Object.h"
#include "cocos/base/TypeDef.h"
#include "PoolType.h"
#include "cocos/base/memory/StlAlloc.h"
#include "cocos/bindings/jswrapper/Object.h"

namespace se {

class CC_DLL ObjectPool final : public cc::Object {
public:
CC_INLINE static const cc::map<PoolType, ObjectPool *> &getPoolMap() { return ObjectPool::_poolMap; }
CC_INLINE static const cc::vector<ObjectPool *> &getPoolMap() { return ObjectPool::poolMap; }

ObjectPool(PoolType type, Object *jsArr);
~ObjectPool();
~ObjectPool() override;

template <class Type>
Type *getTypedObject(uint id) const {
id = _indexMask & id;
bool ok = true;

#ifdef CC_DEBUG
uint len = 0;
ok = _jsArr->getArrayLength(&len);
CCASSERT(ok && id < len, "ObjectPool: Invalid buffer pool entry id");
CCASSERT(id < _array.size(), "ObjectPool: Invalid buffer pool entry id");
#endif

se::Value jsEntry;
ok = _jsArr->getArrayElement(id, &jsEntry);
if (!ok || !jsEntry.isObject()) {
return nullptr;
}
Type *entry = (Type *)jsEntry.toObject()->getPrivateData();
return entry;
return static_cast<Type *>(_array[id]->getPrivateData());
}

void bind(uint id, Object *);

private:
static cc::map<PoolType, ObjectPool *> _poolMap;
static cc::vector<ObjectPool *> poolMap;

PoolType _type = PoolType::SHADER;
Object *_jsArr = nullptr;
uint _poolFlag = 1 << 29;
uint _indexMask = 0;
cc::vector<Object *> _array;
PoolType _type = PoolType::SHADER;
Object * _jsArr = nullptr;
uint _poolFlag = 1 << 29;
uint _indexMask = 0;
};

} // namespace se
20 changes: 19 additions & 1 deletion cocos/bindings/dop/PoolType.h
Expand Up @@ -26,6 +26,24 @@
#pragma once

namespace se {

#define CAST_POOL_TYPE(type) static_cast<uint>(type)

#define BUFFER_POOL_BEGIN CAST_POOL_TYPE(se::PoolType::PASS)
#define ARRAY_POOL_BEGIN CAST_POOL_TYPE(se::PoolType::SUB_MODEL_ARRAY)
#define RAW_BUFFER_BEGIN CAST_POOL_TYPE(se::PoolType::RAW_BUFFER)

#define OBJECT_POOL_SIZE CAST_POOL_TYPE(se::PoolType::FRAMEBUFFER) + 1
#define BUFFER_POOL_SIZE CAST_POOL_TYPE(se::PoolType::PIPELINE_SHARED_SCENE_DATA) - BUFFER_POOL_BEGIN + 1
#define ARRAY_POOL_SIZE CAST_POOL_TYPE(se::PoolType::UI_BATCH_ARRAY) - ARRAY_POOL_BEGIN + 1
#define RAW_BUFFER_SIZE CAST_POOL_TYPE(se::PoolType::RAW_BUFFER) - CAST_POOL_TYPE(se::PoolType::RAW_BUFFER) + 1
#define BUFFER_ALLOCATOR_SIZE (ARRAY_POOL_SIZE + RAW_BUFFER_SIZE)

#define GET_OBJECT_POOL_ID(type) CAST_POOL_TYPE(type)
#define GET_BUFFER_POOL_ID(type) CAST_POOL_TYPE(type) - BUFFER_POOL_BEGIN
#define GET_ARRAY_POOL_ID(type) CAST_POOL_TYPE(type) >= RAW_BUFFER_BEGIN ? (CAST_POOL_TYPE(type) - RAW_BUFFER_BEGIN + ARRAY_POOL_SIZE) : CAST_POOL_TYPE(type) - ARRAY_POOL_BEGIN
#define IS_BUFFER_ALLOCATOR_TYPE(type) CAST_POOL_TYPE(type) >= ARRAY_POOL_BEGIN

enum class PoolType {
// objects
ATTRIBUTE,
Expand Down Expand Up @@ -76,4 +94,4 @@ enum class PoolType {
RAW_BUFFER = 300,
UNKNOWN
};
}
} // namespace se

0 comments on commit 3834eca

Please sign in to comment.