add xmalloc
This commit is contained in:
parent
d6733915b0
commit
a6458a82c0
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,4 +5,3 @@
|
||||
build/
|
||||
vsxmake*/
|
||||
/tools
|
||||
engine/3rdparty/
|
||||
|
||||
24
engine/3rdparty/memalloc/include/memalloc.h
vendored
Normal file
24
engine/3rdparty/memalloc/include/memalloc.h
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#define MEMORY_BLOCK_SIZE 1048576
|
||||
#define META_BLOCK_EMEM_SIZE 16
|
||||
#define MAX_BLOCK_ELEM_SIZE_N 16
|
||||
#define MAX_BLOCK_ELEM_GROUP_N 8
|
||||
#define MEM_CALLSTACK_DEBUG_N 16
|
||||
#define MEMORY_ALIGN_N 16
|
||||
namespace pmr {
|
||||
void* meta_malloc(size_t bytes, size_t alignment = MEMORY_ALIGN_N);
|
||||
void meta_free(void* ptr);
|
||||
}
|
||||
|
||||
MEMALLOC_API void* me_malloc(size_t size);
|
||||
MEMALLOC_API void* me_malloc_nothrow(size_t size) noexcept;
|
||||
MEMALLOC_API void me_free(void* p) noexcept;
|
||||
#if (__cplusplus >= 201402L || _MSC_VER >= 1916)
|
||||
MEMALLOC_API void me_free_size(void* p, size_t size) noexcept;
|
||||
#endif
|
||||
#if (__cplusplus > 201402L || defined(__cpp_aligned_new))
|
||||
MEMALLOC_API void* me_malloc_aligned(size_t size, size_t alignment);
|
||||
MEMALLOC_API void* me_malloc_aligned_nothrow(size_t size, size_t alignment) noexcept;
|
||||
MEMALLOC_API void me_free_size_aligned(void* p, size_t size, size_t alignment) noexcept;
|
||||
MEMALLOC_API void me_free_aligned(void* p, size_t alignment) noexcept;
|
||||
#endif
|
||||
282
engine/3rdparty/memalloc/include/memory_pool.h
vendored
Normal file
282
engine/3rdparty/memalloc/include/memory_pool.h
vendored
Normal file
@ -0,0 +1,282 @@
|
||||
#pragma once
|
||||
#include "memalloc.h"
|
||||
#include <bit>
|
||||
#include <memory_resource>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <windows.h>
|
||||
constexpr inline size_t meta_align_size(size_t size, size_t alignment) {
|
||||
return (size + alignment - 1) / alignment * alignment;
|
||||
};
|
||||
namespace pmr {
|
||||
using std::pmr::memory_resource;
|
||||
class MemoryPagePool {
|
||||
public:
|
||||
static void* do_allocate(size_t bytes, size_t alignment) {
|
||||
void* ptr = (void*)VirtualAlloc(NULL, bytes, MEM_COMMIT, PAGE_READWRITE);
|
||||
return ptr;
|
||||
}
|
||||
static void do_deallocate(void* ptr) {
|
||||
if (!ptr) {
|
||||
return;
|
||||
}
|
||||
VirtualFree(ptr, 0, MEM_RELEASE);
|
||||
}
|
||||
};
|
||||
class BlockAllocator : public memory_resource {
|
||||
private:
|
||||
friend class MemoryPoolManager;
|
||||
uint16_t* m_stack;
|
||||
uint8_t* m_bitmap; // 位图起始地址
|
||||
char* m_data;
|
||||
uint16_t m_block_size;
|
||||
uint16_t m_block_count;
|
||||
uint16_t m_used_count;
|
||||
uint16_t m_head;
|
||||
public:
|
||||
struct MemBlock {
|
||||
uint16_t size;
|
||||
uint16_t begin_mask;
|
||||
uint16_t end_mask;
|
||||
uint16_t padding3;
|
||||
MemBlock(size_t bytes) : size(bytes)
|
||||
, begin_mask(0x5555)
|
||||
, end_mask(0xAAAA) {}
|
||||
operator bool() {
|
||||
return begin_mask == 0x5555 && end_mask == 0xAAAA;
|
||||
}
|
||||
};
|
||||
friend void dumpMetaMemoryLeaks(BlockAllocator* metaAlloc);
|
||||
BlockAllocator(size_t MemorySize, uint16_t block_size):m_block_size(block_size){
|
||||
uint16_t count = 8 * MemorySize / (8 * block_size + 8 * sizeof(uint16_t) + 1);
|
||||
uint16_t bitmap_size = (count + 7) / 8;
|
||||
size_t offset = meta_align_size(count * 2 + bitmap_size, MEMORY_ALIGN_N);
|
||||
if (offset + count * block_size > MemorySize) {
|
||||
count--;
|
||||
offset = meta_align_size(count * 2 + bitmap_size, MEMORY_ALIGN_N);
|
||||
}
|
||||
m_stack = (uint16_t*)MemoryPagePool::do_allocate(MemorySize, MEMORY_ALIGN_N);
|
||||
m_bitmap = (uint8_t*)m_stack + count * 2;
|
||||
m_data = (char*)m_stack + offset;
|
||||
std::memset(m_bitmap, 0, bitmap_size);
|
||||
std::iota(m_stack, m_stack + count, 0);
|
||||
m_head = 0;
|
||||
m_used_count = 0;
|
||||
m_block_count = count;
|
||||
}
|
||||
~BlockAllocator() {
|
||||
if (m_stack) {
|
||||
MemoryPagePool::do_deallocate(m_stack);
|
||||
}
|
||||
m_stack = nullptr;
|
||||
}
|
||||
bool empty() {
|
||||
return m_used_count == 0;
|
||||
}
|
||||
bool try_allocate(size_t bytes) {
|
||||
return bytes <= m_block_size || m_block_count - m_block_size >= MAX_BLOCK_ELEM_GROUP_N;
|
||||
}
|
||||
bool invert_bitmap(uint16_t bit_pos, uint8_t flag) {
|
||||
size_t index = bit_pos / 8;
|
||||
uint8_t invert_mask = 1 << (7 - bit_pos % 8);
|
||||
m_bitmap[index] ^= invert_mask;
|
||||
return flag ? (m_bitmap[index] & invert_mask) == invert_mask :
|
||||
(m_bitmap[index] & invert_mask) == 0;
|
||||
}
|
||||
bool invert_bitmap_group(uint16_t bit_pos, uint8_t count, uint8_t flag) {
|
||||
size_t index = bit_pos / 8;
|
||||
uint8_t offset = bit_pos % 8;
|
||||
uint8_t left_mask = 0xff >> offset;//00011111
|
||||
offset = (16 - offset - count) % 8;
|
||||
uint8_t right_mask = 0xff << offset;//11111110
|
||||
if (offset + count <= 8) {
|
||||
uint8_t mask = left_mask & right_mask;//00011110
|
||||
uint8_t mask_result = flag ? mask : 0;
|
||||
m_bitmap[index] ^= mask;
|
||||
return (m_bitmap[index] & mask) == mask_result;
|
||||
}
|
||||
m_bitmap[index] ^= left_mask;
|
||||
m_bitmap[index + 1] ^= right_mask;
|
||||
uint8_t left_mask_result = flag ? left_mask : 0;
|
||||
uint8_t right_mask_result = flag ? right_mask : 0;
|
||||
return (m_bitmap[index] & left_mask) == left_mask_result && (m_bitmap[index + 1] & right_mask) == right_mask_result;
|
||||
}
|
||||
void* do_allocate(size_t bytes, size_t alignment)override {
|
||||
uint16_t index = m_stack[m_head];
|
||||
uint16_t count = (bytes + m_block_size - 1) / m_block_size;
|
||||
if (count == 1 && !invert_bitmap(index, 1)) {
|
||||
invert_bitmap(index, 0);
|
||||
throw std::runtime_error("Error: Attempting to allocate an already allocated block.");
|
||||
}
|
||||
if (count > 1 && !invert_bitmap_group(index, count, 1)) {
|
||||
invert_bitmap_group(index, count, 1);
|
||||
throw std::runtime_error("Error: Attempting to allocate an already allocated block group.");
|
||||
}
|
||||
m_used_count += count;
|
||||
m_head = (m_head + count) % m_block_count;
|
||||
return m_data + m_block_size * index;
|
||||
}
|
||||
void do_deallocate(void* ptr, size_t bytes, size_t alignment) override {
|
||||
uint16_t index = size_t((char*)ptr - m_data) / m_block_size;
|
||||
uint16_t count = (bytes + m_block_size - 1) / m_block_size;
|
||||
if (count == 1) {
|
||||
if (!invert_bitmap(index, 0)) {
|
||||
invert_bitmap(index, 0);
|
||||
throw std::runtime_error("Error: Double deallocation attempt!");
|
||||
}
|
||||
m_stack[(m_head + m_block_count - m_used_count) % m_block_count] = index;
|
||||
m_used_count--;
|
||||
return;
|
||||
}
|
||||
if (count > 1 && !invert_bitmap_group(index, count, 0)) {
|
||||
invert_bitmap_group(index, count, 0);
|
||||
throw std::runtime_error("Error: Double deallocation group attempt!");
|
||||
}
|
||||
alignment = (m_head + m_block_count - m_used_count) % m_block_count;
|
||||
if (alignment + count < m_block_count) [[likely]] {
|
||||
std::iota(m_stack + alignment, m_stack + alignment + count, index);
|
||||
}
|
||||
else [[unlikely]] {
|
||||
for (uint16_t i = 0; i < count; i++) {
|
||||
m_stack[(alignment + i) % m_block_count] = index + i;
|
||||
}
|
||||
}
|
||||
m_used_count -= count;
|
||||
}
|
||||
bool do_is_equal(const memory_resource& other) const noexcept override { return this == &other; };
|
||||
};
|
||||
class MemoryPoolManager{
|
||||
public:
|
||||
struct MemBlock {
|
||||
#ifdef API_DEBUG
|
||||
void* debug_stack[MEM_CALLSTACK_DEBUG_N];
|
||||
#endif // API_DEBUG
|
||||
uint32_t begin_mask;
|
||||
uint16_t size;
|
||||
uint8_t index;
|
||||
uint8_t alloc_index;
|
||||
uint16_t size_mask;
|
||||
uint8_t index_mask;
|
||||
uint8_t alloc_index_mask;
|
||||
uint32_t end_mask;
|
||||
MemBlock(size_t bytes, uint8_t index, uint8_t alloc_index)
|
||||
: size(bytes)
|
||||
, size_mask(bytes)
|
||||
, index(index)
|
||||
, alloc_index(alloc_index)
|
||||
, begin_mask(0x55555555)
|
||||
, end_mask(0xAAAAAAAA){
|
||||
}
|
||||
operator bool() {
|
||||
return size && (uint32_t)size == (uint32_t)size_mask
|
||||
&& begin_mask == 0x55555555
|
||||
&& end_mask == 0xAAAAAAAA;
|
||||
}
|
||||
};
|
||||
struct AllocatorPtr {
|
||||
BlockAllocator* alloc;
|
||||
AllocatorPtr* next;
|
||||
AllocatorPtr() :alloc(nullptr), next(nullptr){}
|
||||
operator bool() {
|
||||
return alloc;
|
||||
}
|
||||
BlockAllocator* operator->() {
|
||||
return alloc;
|
||||
}
|
||||
~AllocatorPtr() {
|
||||
if (alloc) {
|
||||
alloc->~BlockAllocator();
|
||||
}
|
||||
if (next) {
|
||||
next->~AllocatorPtr();
|
||||
meta_free(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
private:
|
||||
AllocatorPtr mAllocators[MAX_BLOCK_ELEM_SIZE_N] = {};
|
||||
public:
|
||||
friend void dumpMemoryPoolLeaks(MemoryPoolManager* memPool);
|
||||
MemoryPoolManager(){}
|
||||
~MemoryPoolManager() {
|
||||
for (uint32_t i = 0; i < MAX_BLOCK_ELEM_SIZE_N; i++) {
|
||||
mAllocators[i].~AllocatorPtr();
|
||||
meta_free(mAllocators[i].alloc);
|
||||
}
|
||||
}
|
||||
int find_pool_index(size_t bytes) {
|
||||
size_t block_size = std::bit_ceil(bytes);
|
||||
int index = __builtin_ctz(block_size);
|
||||
if (index < MAX_BLOCK_ELEM_SIZE_N) {
|
||||
int count = ((bytes << 3) + block_size - 1) / block_size;
|
||||
if (count >= 7) {
|
||||
return index;
|
||||
}
|
||||
if (count >= 6) {
|
||||
return index - 2;
|
||||
}
|
||||
return index > 7 ? index - 3 : 4;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
void* do_allocate(size_t bytes, size_t alignment) {
|
||||
size_t bytes_block = bytes + sizeof(MemBlock);
|
||||
int index = find_pool_index(bytes_block);
|
||||
if (index < MAX_BLOCK_ELEM_SIZE_N) {
|
||||
uint16_t alloc_index = 0;
|
||||
AllocatorPtr& pAlloc = mAllocators[index];
|
||||
if (!pAlloc) {
|
||||
pAlloc.alloc = (BlockAllocator*)meta_malloc(sizeof(BlockAllocator));
|
||||
new (pAlloc.alloc) BlockAllocator(MEMORY_BLOCK_SIZE, 1 << index);
|
||||
return do_allocate_block(pAlloc.alloc, bytes_block, index, alloc_index);
|
||||
}
|
||||
while(pAlloc) {
|
||||
if (pAlloc->try_allocate(bytes_block)) {
|
||||
return do_allocate_block(pAlloc.alloc, bytes_block, index, alloc_index);
|
||||
}
|
||||
if (!pAlloc.next) {
|
||||
void* pMemory = meta_malloc(sizeof(AllocatorPtr) + sizeof(BlockAllocator));
|
||||
AllocatorPtr* next = new(pMemory) AllocatorPtr();
|
||||
next->alloc = new((char*)pMemory + sizeof(AllocatorPtr)) BlockAllocator(MEMORY_BLOCK_SIZE, 1 << index);
|
||||
pAlloc.next = next;
|
||||
return do_allocate_block(next->alloc, bytes_block, index, alloc_index);
|
||||
}
|
||||
pAlloc = *pAlloc.next;
|
||||
alloc_index++;
|
||||
}
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
return malloc(bytes);
|
||||
}
|
||||
void* do_allocate_block(BlockAllocator* alloc, size_t bytes, uint8_t index, uint8_t alloc_index) {
|
||||
MemBlock* pBlock = (MemBlock*)alloc->do_allocate(bytes, 0);
|
||||
new(pBlock)MemBlock(bytes, index, alloc_index);
|
||||
#ifdef API_DEBUG
|
||||
// 捕获当前堆栈
|
||||
uint16_t n = CaptureStackBackTrace(0, MEM_CALLSTACK_DEBUG_N, pBlock->debug_stack, nullptr);
|
||||
#endif // API_DEBUG
|
||||
return (char*)pBlock + sizeof(MemBlock);
|
||||
}
|
||||
void do_deallocate(void* ptr) {
|
||||
if (!ptr) {
|
||||
return;
|
||||
}
|
||||
MemBlock* pBlock = (MemBlock*)((char*)ptr - sizeof(MemBlock));
|
||||
if (!*pBlock) {
|
||||
free(ptr);
|
||||
return;
|
||||
}
|
||||
AllocatorPtr& pAlloc = mAllocators[pBlock->index];
|
||||
uint16_t alloc_index = pBlock->alloc_index + 1;
|
||||
while (alloc_index && pAlloc) {
|
||||
alloc_index--;
|
||||
if (!alloc_index) {
|
||||
pAlloc->do_deallocate(pBlock, pBlock->size, 0);
|
||||
return;
|
||||
}
|
||||
pAlloc = *pAlloc.next;
|
||||
}
|
||||
throw std::runtime_error("Warning: deallocate erorr!!!");
|
||||
}
|
||||
};
|
||||
}
|
||||
35
engine/3rdparty/memalloc/include/memory_pool_debug.h
vendored
Normal file
35
engine/3rdparty/memalloc/include/memory_pool_debug.h
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include "memory_pool.h"
|
||||
namespace pmr {
|
||||
inline void dumpMemoryPoolLeaks(MemoryPoolManager* memPool) {
|
||||
auto& mAllocators = memPool->mAllocators;
|
||||
for (uint32_t i = 0; i < MAX_BLOCK_ELEM_SIZE_N; i++) {
|
||||
auto& pAlloc = mAllocators[i];
|
||||
if (pAlloc && !pAlloc->empty()) {
|
||||
dumpMetaMemoryLeaks(pAlloc.alloc);
|
||||
}
|
||||
}
|
||||
}
|
||||
inline void dumpMetaMemoryLeaks(BlockAllocator* metaAlloc) {
|
||||
if (metaAlloc->empty()) {
|
||||
return;
|
||||
}
|
||||
uint64_t* bitmap = (uint64_t*)metaAlloc->m_bitmap;
|
||||
size_t use_count = (metaAlloc->m_head + 63 )/ 64;
|
||||
for (size_t i = 0; i < use_count; i++) {
|
||||
uint64_t chunk = bitmap[i];
|
||||
while (chunk != 0) {
|
||||
int offset = __builtin_ctz(chunk); // 找到最低有效位 "1" 的位置
|
||||
void* ptr = metaAlloc->m_data + metaAlloc->m_block_size * (i * 64 + 63 - offset);
|
||||
MemoryPoolManager::MemBlock* pBlock = (MemoryPoolManager::MemBlock*)((char*)ptr - sizeof(MemoryPoolManager::MemBlock));
|
||||
if (*pBlock) {
|
||||
metaAlloc->do_deallocate(pBlock, pBlock->size, 0);
|
||||
chunk = bitmap[i];
|
||||
}
|
||||
else {
|
||||
chunk &= chunk - 1; // 清除最低有效位的“1”
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
105
engine/3rdparty/memalloc/src/memalloc.cpp
vendored
Normal file
105
engine/3rdparty/memalloc/src/memalloc.cpp
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
//内存设计有问题,溜了溜了。还是先学习mimalloc吧
|
||||
#include "memory_pool_debug.h"
|
||||
namespace pmr {
|
||||
inline MemoryPoolManager* pMainPool;
|
||||
inline BlockAllocator* pMetaAlloc;
|
||||
void CleanMainMemPool() {
|
||||
if (!pMainPool) return;
|
||||
dumpMemoryPoolLeaks(pMainPool);
|
||||
pMainPool->~MemoryPoolManager();
|
||||
dumpMetaMemoryLeaks(pMetaAlloc);
|
||||
pMetaAlloc->~BlockAllocator();
|
||||
}
|
||||
void* meta_malloc(size_t bytes, size_t alignment)
|
||||
{
|
||||
if (bytes > META_BLOCK_EMEM_SIZE * MAX_BLOCK_ELEM_GROUP_N || !pMetaAlloc->try_allocate(bytes)) {
|
||||
return pMainPool->do_allocate(bytes, alignment);
|
||||
}
|
||||
using MemBlock = BlockAllocator::MemBlock;
|
||||
bytes += sizeof(MemBlock);
|
||||
MemBlock* pBlock = (MemBlock*)pMetaAlloc->do_allocate(bytes, alignment);
|
||||
new(pBlock)MemBlock(bytes);
|
||||
return (char*)pBlock + sizeof(MemBlock);
|
||||
}
|
||||
void meta_free(void* ptr)
|
||||
{
|
||||
if (!ptr) {
|
||||
return;
|
||||
}
|
||||
using MemBlock = BlockAllocator::MemBlock;
|
||||
MemBlock* pBlock = (MemBlock*)((char*)ptr - sizeof(MemBlock));
|
||||
if (!*pBlock) {
|
||||
pMainPool->do_deallocate(ptr);
|
||||
return;
|
||||
}
|
||||
pMetaAlloc->do_deallocate(ptr, pBlock->size, 0);
|
||||
}
|
||||
}
|
||||
namespace pmr {
|
||||
struct MemPoolWrap {
|
||||
inline static char AllocData[sizeof(BlockAllocator)];
|
||||
char pMemory[sizeof(MemoryPoolManager)];
|
||||
bool isMainTread;
|
||||
MemPoolWrap() {
|
||||
isMainTread = !pMainPool;
|
||||
if (isMainTread) {
|
||||
pMainPool = (MemoryPoolManager*)&pMemory;
|
||||
pMetaAlloc = (BlockAllocator*)&AllocData;
|
||||
std::construct_at(pMetaAlloc, MEMORY_BLOCK_SIZE, META_BLOCK_EMEM_SIZE);
|
||||
std::atexit(CleanMainMemPool);
|
||||
}
|
||||
std::construct_at((MemoryPoolManager*)&pMemory);
|
||||
}
|
||||
~MemPoolWrap() {
|
||||
auto pool = (MemoryPoolManager*)&pMemory;
|
||||
if (!isMainTread) {//主线程最后析构
|
||||
pool->~MemoryPoolManager();
|
||||
}
|
||||
}
|
||||
MemoryPoolManager* operator->() {
|
||||
return (MemoryPoolManager*)&pMemory;
|
||||
}
|
||||
};
|
||||
}
|
||||
thread_local pmr::MemPoolWrap MemPool;
|
||||
|
||||
MEMALLOC_API void* me_malloc(size_t size)
|
||||
{
|
||||
return MemPool->do_allocate(size, MEMORY_ALIGN_N);
|
||||
}
|
||||
|
||||
MEMALLOC_API void* me_malloc_nothrow(size_t size) noexcept
|
||||
{
|
||||
return MemPool->do_allocate(size, MEMORY_ALIGN_N);
|
||||
}
|
||||
|
||||
MEMALLOC_API void me_free(void* p) noexcept
|
||||
{
|
||||
MemPool->do_deallocate(p);
|
||||
}
|
||||
#if (__cplusplus >= 201402L || _MSC_VER >= 1916)
|
||||
MEMALLOC_API void me_free_size(void* p, size_t size) noexcept
|
||||
{
|
||||
MemPool->do_deallocate(p);
|
||||
}
|
||||
#endif
|
||||
#if (__cplusplus > 201402L || defined(__cpp_aligned_new))
|
||||
MEMALLOC_API void* me_malloc_aligned(size_t size, size_t alignment)
|
||||
{
|
||||
return MemPool->do_allocate(size, alignment);
|
||||
}
|
||||
|
||||
MEMALLOC_API void* me_malloc_aligned_nothrow(size_t size, size_t alignment) noexcept
|
||||
{
|
||||
return MemPool->do_allocate(size, alignment);
|
||||
}
|
||||
MEMALLOC_API void me_free_aligned(void* p, size_t alignment) noexcept
|
||||
{
|
||||
return MemPool->do_deallocate(p);
|
||||
}
|
||||
MEMALLOC_API void me_free_size_aligned(void* p, size_t size, size_t alignment) noexcept
|
||||
{
|
||||
MemPool->do_deallocate(p);
|
||||
}
|
||||
|
||||
#endif
|
||||
7
engine/3rdparty/memalloc/xmake.lua
vendored
Normal file
7
engine/3rdparty/memalloc/xmake.lua
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
target("memalloc")
|
||||
set_group("3rdparty")
|
||||
set_kind("shared")
|
||||
add_rules("engine.api")
|
||||
add_includedirs("include",{public = true})
|
||||
add_headerfiles("include/*.h")
|
||||
add_files("src/*.cpp")
|
||||
@ -1,6 +1,6 @@
|
||||
target("singleton")
|
||||
set_kind("shared")
|
||||
set_group("Engine/engine__comp")
|
||||
set_group("3rdparty")
|
||||
add_rules("engine.api")
|
||||
add_includedirs("include", {public = true})
|
||||
add_headerfiles("include/*.h")
|
||||
35
engine/3rdparty/xmalloc/include/xmalloc_new_delete.h
vendored
Normal file
35
engine/3rdparty/xmalloc/include/xmalloc_new_delete.h
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#if defined(__cplusplus)
|
||||
#include <new>
|
||||
#include "xmalloc_type.h"
|
||||
void operator delete(void* p) noexcept { xfree(p); };
|
||||
void operator delete[](void* p) noexcept { xfree(p); };
|
||||
|
||||
void operator delete (void* p, const std::nothrow_t&) noexcept { xfree(p); }
|
||||
void operator delete[](void* p, const std::nothrow_t&) noexcept { xfree(p); }
|
||||
|
||||
void* operator new(std::size_t n) noexcept(false) { return xmalloc(n); }
|
||||
void* operator new[](std::size_t n) noexcept(false) { return xmalloc(n); }
|
||||
|
||||
void* operator new (std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return xmalloc_nothrow(n); }
|
||||
void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return xmalloc_nothrow(n); }
|
||||
|
||||
#if (__cplusplus >= 201402L || _MSC_VER >= 1916)
|
||||
void operator delete (void* p, std::size_t n) noexcept { xfree_size(p, n); };
|
||||
void operator delete[](void* p, std::size_t n) noexcept { xfree_size(p, n); };
|
||||
#endif
|
||||
|
||||
#if (__cplusplus > 201402L || defined(__cpp_aligned_new))
|
||||
void operator delete (void* p, std::align_val_t al) noexcept { xfree_aligned(p, static_cast<size_t>(al)); }
|
||||
void operator delete[](void* p, std::align_val_t al) noexcept { xfree_aligned(p, static_cast<size_t>(al)); }
|
||||
void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept { xfree_size_aligned(p, n, static_cast<size_t>(al)); };
|
||||
void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept { xfree_size_aligned(p, n, static_cast<size_t>(al)); };
|
||||
void operator delete (void* p, std::align_val_t al, const std::nothrow_t&) noexcept { xfree_aligned(p, static_cast<size_t>(al)); }
|
||||
void operator delete[](void* p, std::align_val_t al, const std::nothrow_t&) noexcept { xfree_aligned(p, static_cast<size_t>(al)); }
|
||||
|
||||
void* operator new (std::size_t n, std::align_val_t al) noexcept(false) { return xmalloc_aligned(n, static_cast<size_t>(al)); }
|
||||
void* operator new[](std::size_t n, std::align_val_t al) noexcept(false) { return xmalloc_aligned(n, static_cast<size_t>(al)); }
|
||||
void* operator new (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return xmalloc_aligned_nothrow(n, static_cast<size_t>(al)); }
|
||||
void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return xmalloc_aligned_nothrow(n, static_cast<size_t>(al)); }
|
||||
#endif
|
||||
#endif
|
||||
13
engine/3rdparty/xmalloc/include/xmalloc_type.h
vendored
Normal file
13
engine/3rdparty/xmalloc/include/xmalloc_type.h
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
XMALLOC_API void* xmalloc(size_t size);
|
||||
XMALLOC_API void* xmalloc_nothrow(size_t size) noexcept;
|
||||
XMALLOC_API void xfree(void* p) noexcept;
|
||||
#if (__cplusplus >= 201402L || _MSC_VER >= 1916)
|
||||
XMALLOC_API void xfree_size(void* p, size_t size) noexcept;
|
||||
#endif
|
||||
#if (__cplusplus > 201402L || defined(__cpp_aligned_new))
|
||||
XMALLOC_API void xfree_size_aligned(void* p, size_t size, size_t alignment) noexcept;
|
||||
XMALLOC_API void xfree_aligned(void* p, size_t alignment) noexcept;
|
||||
XMALLOC_API void* xmalloc_aligned(size_t size, size_t alignment);
|
||||
XMALLOC_API void* xmalloc_aligned_nothrow(size_t size, size_t alignment) noexcept;
|
||||
#endif
|
||||
20
engine/3rdparty/xmalloc/src/xmalloc_me.cpp
vendored
Normal file
20
engine/3rdparty/xmalloc/src/xmalloc_me.cpp
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
#if 0
|
||||
#include "xmalloc_type.h"
|
||||
#include "memalloc.h"
|
||||
XMALLOC_API void* xmalloc(size_t size) { return mi_malloc(size); }
|
||||
XMALLOC_API void* xmalloc_nothrow(size_t size) noexcept { return mi_new_nothrow(size); }
|
||||
|
||||
XMALLOC_API void xfree(void* p) noexcept { mi_free(p); }
|
||||
|
||||
#if (__cplusplus >= 201402L || _MSC_VER >= 1916)
|
||||
XMALLOC_API void xfree_size(void* p, size_t size) noexcept { return mi_free_size(p, size); }
|
||||
#endif
|
||||
|
||||
#if (__cplusplus > 201402L || defined(__cpp_aligned_new))
|
||||
XMALLOC_API void xfree_size_aligned(void* p, size_t size, size_t alignment) noexcept { return mi_free_size_aligned(p, size, alignment); }
|
||||
XMALLOC_API void xfree_aligned(void* p, size_t alignment) noexcept { return mi_free_aligned(p, alignment); }
|
||||
|
||||
XMALLOC_API void* xmalloc_aligned(size_t size, size_t alignment) { return mi_new_aligned(size, alignment); }
|
||||
XMALLOC_API void* xmalloc_aligned_nothrow(size_t size, size_t alignment) noexcept { return mi_new_aligned_nothrow(size, alignment); }
|
||||
#endif
|
||||
#endif
|
||||
29
engine/3rdparty/xmalloc/src/xmalloc_mi.cpp
vendored
Normal file
29
engine/3rdparty/xmalloc/src/xmalloc_mi.cpp
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
#include "xmalloc_type.h"
|
||||
#include "mimalloc.h"
|
||||
void clean() {
|
||||
// 强制垃圾回收并检查未释放的内存
|
||||
mi_stats_print(NULL);
|
||||
mi_collect(true);
|
||||
}
|
||||
struct mi_exit_wrap {
|
||||
mi_exit_wrap() {
|
||||
std::atexit(clean);
|
||||
}
|
||||
};
|
||||
static mi_exit_wrap _mi_exit_wrap;
|
||||
XMALLOC_API void* xmalloc(size_t size){return mi_malloc(size);}
|
||||
XMALLOC_API void* xmalloc_nothrow(size_t size) noexcept{return mi_new_nothrow(size);}
|
||||
|
||||
XMALLOC_API void xfree(void* p) noexcept{mi_free(p);}
|
||||
|
||||
#if (__cplusplus >= 201402L || _MSC_VER >= 1916)
|
||||
XMALLOC_API void xfree_size(void* p, size_t size) noexcept{return mi_free_size(p, size);}
|
||||
#endif
|
||||
|
||||
#if (__cplusplus > 201402L || defined(__cpp_aligned_new))
|
||||
XMALLOC_API void xfree_size_aligned(void* p, size_t size, size_t alignment) noexcept{return mi_free_size_aligned(p, size, alignment);}
|
||||
XMALLOC_API void xfree_aligned(void* p, size_t alignment) noexcept{return mi_free_aligned(p, alignment);}
|
||||
|
||||
XMALLOC_API void* xmalloc_aligned(size_t size, size_t alignment) { return mi_new_aligned(size, alignment); }
|
||||
XMALLOC_API void* xmalloc_aligned_nothrow(size_t size, size_t alignment) noexcept { return mi_new_aligned_nothrow(size, alignment); }
|
||||
#endif
|
||||
8
engine/3rdparty/xmalloc/xmake.lua
vendored
Normal file
8
engine/3rdparty/xmalloc/xmake.lua
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
target("xmalloc")
|
||||
set_kind("shared")
|
||||
set_group("3rdparty")
|
||||
add_rules("engine.api")
|
||||
add_includedirs("include", {public = true})
|
||||
add_headerfiles("include/*.h")
|
||||
add_files("src/*.cpp")
|
||||
add_packages("mimalloc")
|
||||
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <memory_resource>
|
||||
#include "xmemory_type.h"
|
||||
namespace pmr {
|
||||
using std::pmr::unsynchronized_pool_resource;
|
||||
using std::pmr::memory_resource;
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
// ----------------------------------------------------------------------------
|
||||
// This header provides convenient overrides for the new and
|
||||
// delete operations in C++.
|
||||
//
|
||||
// This header should be included in only one source file!
|
||||
//
|
||||
// On Windows, or when linking dynamically with mimalloc, these
|
||||
// can be more performant than the standard new-delete operations.
|
||||
// See <https://en.cppreference.com/w/cpp/memory/new/operator_new>
|
||||
// ---------------------------------------------------------------------------
|
||||
#if defined(__cplusplus)
|
||||
extern void operator delete(void* p) noexcept;
|
||||
extern void operator delete[](void* p) noexcept;
|
||||
|
||||
extern void operator delete (void* p, const std::nothrow_t&) noexcept;
|
||||
extern void operator delete[](void* p, const std::nothrow_t&) noexcept;
|
||||
|
||||
#if (__cplusplus >= 201402L || _MSC_VER >= 1916)
|
||||
extern void operator delete (void* p, std::size_t n) noexcept;
|
||||
extern void operator delete[](void* p, std::size_t n) noexcept;
|
||||
#endif
|
||||
|
||||
#if (__cplusplus > 201402L || defined(__cpp_aligned_new))
|
||||
extern void operator delete (void* p, std::align_val_t al) noexcept;
|
||||
extern void operator delete[](void* p, std::align_val_t al) noexcept;
|
||||
extern void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept;
|
||||
extern void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept;
|
||||
extern void operator delete (void* p, std::align_val_t al, const std::nothrow_t&) noexcept;
|
||||
extern void operator delete[](void* p, std::align_val_t al, const std::nothrow_t&) noexcept;
|
||||
|
||||
extern void* operator new (std::size_t n, std::align_val_t al) noexcept(false);
|
||||
extern void* operator new[](std::size_t n, std::align_val_t al) noexcept(false);
|
||||
extern void* operator new (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept;
|
||||
extern void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept;
|
||||
#endif
|
||||
#endif
|
||||
@ -1,3 +1,4 @@
|
||||
#include "xmalloc_new_delete.h"
|
||||
#include "vkn/module.h"
|
||||
#include "vkn/loader/vulkan_glsl_loader.h"
|
||||
#include "pmr/frame_allocator.h"
|
||||
|
||||
@ -29,7 +29,7 @@ function shared_module(name, owner, opt)
|
||||
set_group("Engine/"..owner.."__dyn")
|
||||
add_rules("engine.api")
|
||||
add_includedirs("include", {public = true})
|
||||
add_rules("engine.plugin", {file = opt and opt.file or "include/" .. name .. "/module.h"})
|
||||
--add_rules("engine.plugin", {file = opt and opt.file or "include/" .. name .. "/module.h"})
|
||||
end
|
||||
function add_dependency(...)
|
||||
add_deps(...)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "engine/api.h"
|
||||
#include "os/file_manager.h"
|
||||
#include "xmalloc_new_delete.h"
|
||||
class ENGINE_API EngineModule : public api::IDynamicModule
|
||||
{
|
||||
public:
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
#include "mimalloc-new-delete.h"
|
||||
//extern void mi_stats_print(void* out);
|
||||
//extern void mi_collect(bool force);
|
||||
void clean() {
|
||||
// 在程序退出时输出内存泄漏信息
|
||||
//mi_print_stats();
|
||||
// 强制垃圾回收并检查未释放的内存
|
||||
mi_stats_print(NULL);
|
||||
mi_collect(true);
|
||||
}
|
||||
struct mi_exit_wrap {
|
||||
mi_exit_wrap() {
|
||||
std::atexit(clean);
|
||||
}
|
||||
};
|
||||
static mi_exit_wrap _mi_exit_wrap;
|
||||
@ -12,7 +12,7 @@ target("engine")
|
||||
set_group("Engine")
|
||||
add_rules("engine.api")
|
||||
add_files("src/engine/*.cpp")
|
||||
add_packages("mimalloc")
|
||||
add_deps("xmalloc", {public = true})
|
||||
includes("xmake/xmake.lua")
|
||||
includes("3rdparty/xmake.lua")
|
||||
includes("tools/xmake.lua")
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
#define ZLIB_API
|
||||
#define ZLIB_API_VAL
|
||||
#include "xmalloc_new_delete.h"
|
||||
#include "archive/pch.h"
|
||||
#include "test_refl.h"
|
||||
using namespace api;
|
||||
@ -7,7 +10,7 @@ int main() {
|
||||
{
|
||||
using T = Guid;
|
||||
T a(1,1.0);
|
||||
|
||||
auto ppp = new int(120);
|
||||
T* c = new T();
|
||||
a.view = "hello";
|
||||
auto text = TextSerialize(a);
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
#include "xmalloc_new_delete.h"
|
||||
#include "SDL.h"
|
||||
#include "engine/api.h"
|
||||
#include "zlog.h"
|
||||
|
||||
@ -9,4 +9,4 @@ target("zworld-editor")
|
||||
})
|
||||
add_files("editor/*.cpp")
|
||||
add_headerfiles("editor/*.h")
|
||||
add_deps("zlib", "core", "engine")
|
||||
add_deps("zlib", "core", "xmalloc")
|
||||
Loading…
Reference in New Issue
Block a user