Skip to content

Commit

Permalink
add slab allocator
Browse files Browse the repository at this point in the history
Signed-off-by: wineway <wangyuweihx@gmail.com>
  • Loading branch information
wineway committed Aug 29, 2024
1 parent abf4de9 commit 699c78d
Show file tree
Hide file tree
Showing 12 changed files with 263 additions and 120 deletions.
17 changes: 8 additions & 9 deletions src/common/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
project(common)
add_subdirectory(tlsf)

add_library(${PROJECT_NAME} INTERFACE)
add_library(${PROJECT_NAME} SHARED)

target_include_directories(${PROJECT_NAME}
INTERFACE
$<INSTALL_INTERFACE:include>
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)

target_link_libraries(${PROJECT_NAME} INTERFACE tlsf)
target_link_libraries(${PROJECT_NAME} PUBLIC tlsf)

target_sources(${PROJECT_NAME}
INTERFACE FILE_SET HEADERS
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}
FILES ring.hpp)
PRIVATE tlsf_allocator.cc)

if(APPLE)
execute_process(COMMAND sysctl -n hw.cachelinesize
Expand All @@ -26,11 +25,11 @@ elseif(UNIX)
OUTPUT_VARIABLE CACHE_LINESIZE
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
target_compile_definitions(${PROJECT_NAME} INTERFACE SQK_CACHE_LINESIZE=${CACHE_LINESIZE})
target_compile_definitions(${PROJECT_NAME} PUBLIC SQK_CACHE_LINESIZE=${CACHE_LINESIZE})

if (WITH_SPDLOG)
target_include_directories(${PROJECT_NAME}
INTERFACE
PUBLIC
${spdlog_SOURCE_DIR}/include
)
endif()
Expand Down
98 changes: 0 additions & 98 deletions src/common/allocator.hpp

This file was deleted.

162 changes: 162 additions & 0 deletions src/common/include/allocator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#ifndef SQK_COMMON_ALLOCATOR_HPP_
#define SQK_COMMON_ALLOCATOR_HPP_

#include <cstdint>
#include <new>
#include <stack>

#include "log.hpp"
#include "utilty.h"

namespace sqk::common {

template <typename T>
struct PoolAllocatable {
inline void* operator new(std::size_t size) {
return T::operator new(size);
}

inline void* operator new[](std::size_t size) {
return T::operator new[](size);
}

inline void*
operator new(std::size_t size, const std::nothrow_t& nothrow) noexcept {
return T::operator new(size, nothrow);
}

inline void*
operator new[](std::size_t size, const std::nothrow_t& nothrow) noexcept {
return T::operator new[](size, nothrow);
}

inline void operator delete(void* ptr) noexcept {
T::operator delete(ptr);
}

inline void operator delete[](void* ptr) noexcept {
T::operator delete[](ptr);
}

inline void operator delete(void* ptr, const std::nothrow_t& nothrow) noexcept {
T::operator delete(ptr, nothrow);
}

inline void operator delete[](void* ptr, const std::nothrow_t& nothrow) noexcept {
T::operator delete[](ptr, nothrow);
}

// void* operator new(std::size_t size, std::align_val_t);
// void*
// operator new(std::size_t size, std::align_val_t, const std::nothrow_t&) noexcept;
// void* operator new[](std::size_t size, std::align_val_t);
// void* operator new
// [](std::size_t size, std::align_val_t, const std::nothrow_t&) noexcept;
// void operator delete(void* ptr, std::align_val_t) noexcept;
// void
// operator delete(void* ptr, std::align_val_t, const std::nothrow_t&) noexcept;
// void
// operator delete(void* ptr, std::size_t size, std::align_val_t al) noexcept;
// void operator delete[](void* ptr, std::align_val_t) noexcept;
// void operator delete
// [](void* ptr, std::align_val_t, const std::nothrow_t&) noexcept;
// void operator delete[](
// void* ptr,
// std::size_t size,
// std::align_val_t al
// ) noexcept;
};

struct TlsfPoolAllocator: public PoolAllocatable<TlsfPoolAllocator> {
void* operator new(std::size_t size);
void* operator new[](std::size_t size);
void* operator new(std::size_t size, const std::nothrow_t&) noexcept;
void* operator new[](std::size_t size, const std::nothrow_t&) noexcept;
void operator delete(void* ptr) noexcept;
void operator delete[](void* ptr) noexcept;
void operator delete(void* ptr, const std::nothrow_t&) noexcept;
void operator delete[](void* ptr, const std::nothrow_t&) noexcept;
};

#define ROUNDUP(_x, _v) ((((~(_x)) + 1) & ((_v) - 1)) + (_x))

struct SlabPoolAllocator: public PoolAllocatable<SlabPoolAllocator> {
void* operator new(std::size_t size) {
void *ptr;
ptr = slab_alloc(size);
if (unlikely(!ptr)) {
throw std::bad_alloc();
}
return ptr;
}
void* operator new[](std::size_t size) { return ::operator new[](size); }
void* operator new(std::size_t size, const std::nothrow_t&) noexcept {
return slab_alloc(size);
}
void* operator new[](std::size_t size, const std::nothrow_t& nothrow) noexcept { return ::operator new[](size, nothrow); }
void operator delete(void* ptr) noexcept {
slab_dealloc(ptr);
}
void operator delete[](void* ptr) noexcept { return ::operator delete[](ptr); }
void operator delete(void* ptr, const std::nothrow_t&) noexcept {
slab_dealloc(ptr);
}
void operator delete[](void* ptr, const std::nothrow_t& nothrow) noexcept { return ::operator delete[](ptr, nothrow); }
private:
static constexpr uint16_t SLAB_MAGIC = 0b1010101001010101;
static constexpr uint32_t MAX_CLASS_SHIFT = 9;
struct SlabHeader {
std::size_t ind_: MAX_CLASS_SHIFT;
std::size_t magic_: 16;
};
static void *slab_alloc(std::size_t size) noexcept {
void* ptr;
auto rsize = roundup(size);
auto ind = size2ind(rsize);
// fast path
if (likely(ind < LOOKUP_MAX_CLASS && !tcache_[ind].empty())) {
ptr = tcache_[ind].top();
tcache_[ind].pop();
} else {
ptr = static_cast<uint8_t*>(::operator new(rsize + SLAB_OVERHEAD)) + SLAB_OVERHEAD;
SlabHeader* header = ptr2header(ptr);
header->ind_ = ind;
#ifndef NDEBUG
header->magic_ = SLAB_MAGIC;
#endif // !NDEBUG
}
return ptr;
}

static void slab_dealloc(void* ptr) noexcept {
SlabHeader* header = ptr2header(ptr);
S_ASSERT(header->magic_ == SLAB_MAGIC);
auto ind = header->ind_;
if (likely(ind < LOOKUP_MAX_CLASS)) {
tcache_[ind].push(ptr);
} else {
::operator delete(header);
}
}
constexpr static std::allocator<uint8_t> allocator {};
static constexpr std::size_t MAX_FRAME_SIZE = 4UL << 10;
static constexpr std::size_t BASE_SHIFT = 3;
static constexpr std::size_t BASE_SIZE = 1UL << BASE_SHIFT;
static constexpr std::size_t SLAB_OVERHEAD = sizeof(SlabHeader);
static_assert(sizeof(SlabHeader) == sizeof(uint64_t), "");
static constexpr uint32_t LOOKUP_MAX_CLASS = MAX_FRAME_SIZE >> BASE_SHIFT;
static_assert(1UL << MAX_CLASS_SHIFT == LOOKUP_MAX_CLASS, "");
static inline thread_local std::stack<void*> tcache_[LOOKUP_MAX_CLASS];
static inline std::size_t roundup(std::size_t size) {
return ROUNDUP(size, BASE_SIZE);
}
static inline uint32_t size2ind(std::size_t size) {
return size >> BASE_SHIFT;
}
static inline SlabHeader* ptr2header(void* ptr) {
return reinterpret_cast<SlabHeader*>(static_cast<uint8_t*>(ptr) - SLAB_OVERHEAD);
}
};

} // namespace sqk::common
#endif // !SQK_COMMON_ALLOCATOR_HPP_
File renamed without changes.
8 changes: 1 addition & 7 deletions src/common/ring.hpp → src/common/include/ring.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <cstdint>

#include "log.hpp"
#include "utilty.h"
#include "ring_generic_allocator.hpp"

static_assert(sizeof(std::atomic<uint32_t>) == sizeof(uint32_t), "");
Expand All @@ -28,13 +29,6 @@ static inline void sqk_pause(void) {
_mm_pause();
}

#ifndef likely
#define likely(x) __builtin_expect((x), 1)
#endif
#ifndef unlikely
#define unlikely(x) __builtin_expect((x), 0)
#endif

#define SQK_CACHELINE_ALIGNED alignas(SQK_CACHE_LINESIZE)

/**
Expand Down
File renamed without changes.
12 changes: 12 additions & 0 deletions src/common/include/utilty.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef SQK_COMMON_UTILTY_H_
#define SQK_COMMON_UTILTY_H_

#ifndef likely
#define likely(x) __builtin_expect((x), 1)
#endif
#ifndef unlikely
#define unlikely(x) __builtin_expect((x), 0)
#endif

#endif // !SQK_COMMON_UTILTY_H_

3 changes: 0 additions & 3 deletions src/common/tlsf/tlsf.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,9 +453,6 @@ static __inline__ bhdr_t *process_area(void *area, size_t size)
return ib;
}

char * init() {
return NULL;
}
/******************************************************************/
/******************** Begin of the allocator code *****************/
/******************************************************************/
Expand Down
Loading

0 comments on commit 699c78d

Please sign in to comment.