From d7ae189ecfa82a8ee64a75a49b7b0a3f7b5f24ee Mon Sep 17 00:00:00 2001 From: Hugo Santos Date: Thu, 26 Apr 2007 12:21:38 +0000 Subject: [PATCH] slab: be smarter when picking the underlying strategy for the slab C API (based on requested object size). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20840 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/slab/Slab.cpp | 111 +++++++++++++++++++++++++++++--- 1 file changed, 102 insertions(+), 9 deletions(-) diff --git a/src/system/kernel/slab/Slab.cpp b/src/system/kernel/slab/Slab.cpp index 05ff991192..b01b216c95 100644 --- a/src/system/kernel/slab/Slab.cpp +++ b/src/system/kernel/slab/Slab.cpp @@ -36,6 +36,77 @@ static const int kMagazineCapacity = 32; static const size_t kCacheColorPeriod = 8; + +// all the AbstractCache stuff is used with the C interface, we +// should probably move this to its own file. + +class AbstractCache { +public: + virtual ~AbstractCache() {} + + virtual void *Allocate(uint32_t flags) = 0; + virtual void Return(void *object) = 0; +}; + + +typedef MergedLinkCacheStrategy SmallObjectStrategy; +typedef MergedLinkAndSlabCacheStrategy MediumObjectStrategy; +typedef HashCacheStrategy BigObjectStrategy; + +typedef Cache SmallObjectCache; +typedef Cache MediumObjectCache; +typedef Cache BigObjectCache; + + +// SmallObjectCache: one word overhead per object, needs pages to be aligned +class SmallObjectAbstractCache : public AbstractCache, + public LocalCache { +public: + typedef LocalCache Base; + + SmallObjectAbstractCache(const char *name, size_t objectSize, + size_t alignment, base_cache_constructor constructor, + base_cache_destructor destructor, void *cookie) + : Base(name, objectSize, alignment, constructor, destructor, cookie) {} + + void *Allocate(uint32_t flags) { return Base::Alloc(flags); } + void Return(void *object) { Base::Free(object); } +}; + + +// MediumObjectCache: two words overhead per object +class MediumObjectAbstractCache : public AbstractCache, + public LocalCache { +public: + typedef LocalCache Base; + + MediumObjectAbstractCache(const char *name, size_t objectSize, + size_t alignment, base_cache_constructor constructor, + base_cache_destructor destructor, void *cookie) + : Base(name, objectSize, alignment, constructor, destructor, cookie) {} + + void *Allocate(uint32_t flags) { return Base::Alloc(flags); } + void Return(void *object) { Base::Free(object); } +}; + + +// BigObjectCache: uses an hash table to map objects to links but packs +// the objects tightly in the pages. Good for power of 2 lengths. +class BigObjectAbstractCache : public AbstractCache, + public LocalCache { +public: + typedef LocalCache Base; + + BigObjectAbstractCache(const char *name, size_t objectSize, + size_t alignment, base_cache_constructor constructor, + base_cache_destructor destructor, void *cookie) + : Base(name, objectSize, alignment, constructor, destructor, cookie) {} + + void *Allocate(uint32_t flags) { return Base::Alloc(flags); } + void Return(void *object) { Base::Free(object); } +}; + + static depot_magazine *_AllocMagazine(); static void _FreeMagazine(depot_magazine *magazine); @@ -545,44 +616,66 @@ base_depot_make_empty(base_depot *depot) } -typedef MergedLinkCacheStrategy AreaMergedCacheStrategy; -typedef Cache AreaMergedCache; -typedef LocalCache AreaLocalCache; +static inline int +__Fls(size_t value) +{ + if (value == 0) + return -1; + + int bit; + for (bit = 1; value != 1; bit++) + value >>= 1; + return bit; +} + object_cache_t object_cache_create(const char *name, size_t object_size, size_t alignment, status_t (*_constructor)(void *, void *), void (*_destructor)(void *, void *), void *cookie) { - return new (std::nothrow) AreaLocalCache(name, object_size, alignment, - _constructor, _destructor, cookie); + if (object_size == 0) + return NULL; + else if (object_size < 64) + return new (std::nothrow) SmallObjectAbstractCache(name, object_size, + alignment, _constructor, _destructor, cookie); + + size_t upperBoundary = 1 << __Fls(object_size); + + if (object_size <= 256 + || (upperBoundary - object_size) >= (4 * sizeof(void *))) + return new (std::nothrow) MediumObjectAbstractCache(name, object_size, + alignment, _constructor, _destructor, cookie); + + return new (std::nothrow) BigObjectAbstractCache(name, object_size, + alignment, _constructor, _destructor, cookie); } void * object_cache_alloc(object_cache_t cache) { - return ((AreaLocalCache *)cache)->Alloc(0); + return object_cache_alloc_etc(cache, 0); } void * object_cache_alloc_etc(object_cache_t cache, uint32_t flags) { - return ((AreaLocalCache *)cache)->Alloc(flags); + return ((AbstractCache *)cache)->Allocate(flags); } void object_cache_free(object_cache_t cache, void *object) { - ((AreaLocalCache *)cache)->Free(object); + ((AbstractCache *)cache)->Return(object); } void object_cache_destroy(object_cache_t cache) { - delete (AreaLocalCache *)cache; + delete (AbstractCache *)cache; }