Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize the performance of the memory pool. #3414

Merged
merged 6 commits into from Apr 19, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 15 additions & 4 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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think _buffers.clear() and _caches.clear() is not needed in destructor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think _buffers.clear() and _caches.clear() is not needed in destructor.

Ok, I delete them.

}

Object *BufferAllocator::alloc(uint index, uint bytes) {
Expand All @@ -52,7 +54,12 @@ Object *BufferAllocator::alloc(uint index, uint bytes) {
Object *obj = Object::createArrayBufferObject(nullptr, bytes);
obj->incRef();
_buffers[index] = obj;


uint8_t *ret = nullptr;
size_t len;
obj->getArrayBufferData((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
60 changes: 38 additions & 22 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 &= _bufferMask;
const auto p = GET_ARRAY_POOL_ID(type);

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

const auto 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;
}
const auto p = GET_ARRAY_POOL_ID(type);

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

const auto 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((uint8_t **)&ret, &len);
*size = (uint)len;
return ret;
}

BufferAllocator(PoolType type);
~BufferAllocator();

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;
minggo marked this conversation as resolved.
Show resolved Hide resolved
static constexpr uint _bufferMask = ~(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
12 changes: 5 additions & 7 deletions cocos/bindings/dop/BufferPool.cpp
Expand Up @@ -29,33 +29,31 @@

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 | _poolFlag);

_bytesPerChunk = _bytesPerEntry * _entriesPerChunk;

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

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

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
26 changes: 13 additions & 13 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,8 +39,8 @@ 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 const uint getPoolFlag() { return _poolFlag; }

BufferPool(PoolType type, uint entryBits, uint bytesPerEntry);
~BufferPool();
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 _poolFlag = 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
17 changes: 12 additions & 5 deletions cocos/bindings/dop/ObjectPool.cpp
Expand Up @@ -28,20 +28,27 @@

using namespace se;

cc::map<PoolType, ObjectPool *> ObjectPool::_poolMap;
cc::vector<ObjectPool *> ObjectPool::_poolMap(static_cast<uint>(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;
}
}
38 changes: 17 additions & 21 deletions cocos/bindings/dop/ObjectPool.h
Expand Up @@ -25,48 +25,44 @@

#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();

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 (Type *)_array[id]->getPrivateData();
}

public:
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