add custom slab allocator for stlredblack

This commit is contained in:
Sears Russell 2010-11-13 06:08:57 +00:00
parent 0d5c22991d
commit 1708a716e1
6 changed files with 197 additions and 3 deletions

View file

@ -47,7 +47,7 @@ ADD_LIBRARY(stasis crc32.c redblack.c tsearchcompat.c lhtable.c concurrentHash.c
bufferManager/bufferHash.c replacementPolicy/lru.c
replacementPolicy/lruFast.c replacementPolicy/threadsafeWrapper.c replacementPolicy/concurrentWrapper.c
util/log2.c util/histogram.c util/hashFunctions.c
util/multiset.c
stlredblack.cpp)
util/multiset.c util/slab.c
stlredblack.cpp util/stlslab.cpp)
INSTALL(TARGETS stasis LIBRARY DESTINATION lib)

View file

@ -11,6 +11,9 @@
#include <stasis/redblack.h>
#include <stdio.h>
#undef end
#undef try
#undef catch
#include <stasis/util/stlslab.h>
extern "C" {
typedef int (*c_cmp_t)(const void*, const void*, const void*);
@ -26,7 +29,7 @@ class MyCompare {
MyCompare(c_cmp_t cmp, int dummy) : cmp_(cmp), arg_(NULL) {}
};
typedef std::set<const void*,MyCompare> rb;
typedef std::set<const void*,MyCompare, stlslab<const void *> > rb;
extern "C" {

90
src/stasis/util/slab.c Normal file
View file

@ -0,0 +1,90 @@
#include <stasis/common.h>
#include <stasis/util/slab.h>
#include <assert.h>
#include <stdio.h>
/**
* @file A simple (single-threaded) slab allocator
*
* Created on: Nov 12, 2010
* Author: sears
*/
struct stasis_util_slab_t {
byte ** blocks;
void * freelist_ptr;
uint32_t obj_sz;
uint32_t block_sz;
uint32_t objs_per_block;
uint32_t this_block_count;
uint32_t this_block;
uint32_t refcount; // the #*%(^!!! stl wants to copy-construct us to %$!! and back, so we need a way to refcount...
};
/**
* Create a slab allocator
* @param the size of each object to be allocated
* @return a slab allocator. Calling stasis_util_slab_destroy() will deallocate it all-at-once.
*/
stasis_util_slab_t * stasis_util_slab_create(uint32_t obj_sz, uint32_t block_sz) {
stasis_util_slab_t* ret = malloc(sizeof(*ret));
// printf("slab init: obj siz = %lld, block_sz = %lld\n", (long long)obj_sz, (long long)block_sz);
ret->blocks = malloc(sizeof(ret->blocks[0]));
ret->blocks[0] = malloc(block_sz);
ret->freelist_ptr = 0;
ret->obj_sz = obj_sz;
ret->block_sz = block_sz;
ret->objs_per_block = block_sz / obj_sz;
ret->this_block_count = 0;
ret->this_block = 0;
ret->refcount = 1;
return ret;
}
void stasis_util_slab_ref(stasis_util_slab_t * slab) {
(slab->refcount)++;
}
void stasis_util_slab_destroy(stasis_util_slab_t * slab) {
(slab->refcount)--;
if(!slab->refcount) {
for(int i = 0; i <= slab->this_block; i++) {
free(slab->blocks[i]);
}
free(slab->blocks);
fprintf(stderr, "Deallocated slab (obj_sz = %lld). Was using %lld bytes\n",
(long long) (uint64_t)slab->obj_sz,
(long long int)
((uint64_t)slab->this_block + 1) * (uint64_t)slab->block_sz);
free(slab);
}
}
// XXX get rid of multiplications! Store next free byte instead of obj count!
void* stasis_util_slab_malloc(stasis_util_slab_t * slab) {
if(slab->freelist_ptr) {
void * ret = slab->freelist_ptr;
slab->freelist_ptr = *(void**)slab->freelist_ptr;
assert(ret);
// printf("ALLOC %llx\n", (long long) ret);
return ret;
} else if(slab->this_block_count == slab->objs_per_block) {
(slab->this_block_count) = 0;
(slab->this_block) ++;
slab->blocks = realloc(slab->blocks, (slab->this_block+1) * sizeof(slab->blocks[0]));
assert(slab->blocks);
slab->blocks[slab->this_block] = malloc(slab->block_sz);
assert(slab->blocks[slab->this_block]);
}
slab->this_block_count ++;
void * ret = (void*) &(slab->blocks[slab->this_block][(slab->this_block_count-1) * slab->obj_sz]);
assert(ret);
// printf("ALLOC %llx\n", (long long) ret);
return ret;
}
void stasis_util_slab_free(stasis_util_slab_t * slab, void * ptr) {
// printf("FREE %llx\n", (long long) ptr);
assert(ptr);
*((void**)ptr) = slab->freelist_ptr;
slab->freelist_ptr = ptr;
}

View file

@ -0,0 +1,8 @@
/*
* stlslab.cpp
*
* Created on: Nov 12, 2010
* Author: sears
*/
#include <stasis/util/stlslab.h>

24
stasis/util/slab.h Normal file
View file

@ -0,0 +1,24 @@
/*
* slab.h
*
* Created on: Nov 12, 2010
* Author: sears
*/
#ifndef SLAB_H_
#define SLAB_H_
#include <stasis/common.h>
BEGIN_C_DECLS
typedef struct stasis_util_slab_t stasis_util_slab_t;
stasis_util_slab_t * stasis_util_slab_create(uint32_t obj_sz, uint32_t block_sz);
void stasis_util_slab_ref(stasis_util_slab_t * slab);
void stasis_util_slab_destroy(stasis_util_slab_t * slab);
void* stasis_util_slab_malloc(stasis_util_slab_t * slab);
void stasis_util_slab_free(stasis_util_slab_t * slab, void * ptr);
END_C_DECLS
#endif /* SLAB_H_ */

69
stasis/util/stlslab.h Normal file
View file

@ -0,0 +1,69 @@
/*
* stlslab.h
*
* Created on: Nov 12, 2010
* Author: sears
*/
#ifndef STLSLAB_H_
#define STLSLAB_H_
#include <algorithm>
#include <stdio.h>
#include <stasis/util/slab.h>
#include <assert.h>
template <class T>
class stlslab {
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef const T* const_pointer;
typedef const T& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
stlslab ( ) throw() {
alloc = stasis_util_slab_create(sizeof(T), 65536);
}
stlslab ( const stlslab& s) throw() {
printf("Expensive!!\n");
alloc = stasis_util_slab_create(sizeof(T), /*sizeof(U),*/ 65536);
// alloc = s.alloc;
// assert(alloc);
stasis_util_slab_ref(alloc);
}
template <class U>
stlslab( const stlslab<U>& s) throw() {
// printf("sizeof U %lld\n", (long long)sizeof(U));
alloc = s.alloc;
//assert(alloc);
stasis_util_slab_ref(alloc);
}
~stlslab () {
stasis_util_slab_destroy(alloc);
}
pointer address ( reference x ) const { return &x; }
const_pointer address ( const_reference x ) const { return &x; }
template<typename _Tp1>
struct rebind
{ typedef stlslab<_Tp1> other; };
pointer allocate (size_type n, stlslab::const_pointer hint=0) {
assert(n == 1);
return (T*) stasis_util_slab_malloc(alloc);
}
void deallocate (pointer p, size_type n) {
assert(n == 1);
stasis_util_slab_free(alloc, p);
}
size_type max_size() const throw() { return 1; }
void construct ( pointer p, const_reference val ) { new ((void*)p) T (val); }
void destroy (pointer p) {((T*)p)->~T(); }
stasis_util_slab_t * alloc;
};
#endif /* STLSLAB_H_ */