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
This commit is contained in:
Hugo Santos
2007-04-26 12:21:38 +00:00
parent e6fb3d3947
commit d7ae189ecf
+102 -9
View File
@@ -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<AreaBackend> SmallObjectStrategy;
typedef MergedLinkAndSlabCacheStrategy<AreaBackend> MediumObjectStrategy;
typedef HashCacheStrategy<AreaBackend> BigObjectStrategy;
typedef Cache<SmallObjectStrategy> SmallObjectCache;
typedef Cache<MediumObjectStrategy> MediumObjectCache;
typedef Cache<BigObjectStrategy> BigObjectCache;
// SmallObjectCache: one word overhead per object, needs pages to be aligned
class SmallObjectAbstractCache : public AbstractCache,
public LocalCache<SmallObjectCache> {
public:
typedef LocalCache<SmallObjectCache> 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<MediumObjectCache> {
public:
typedef LocalCache<MediumObjectCache> 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<BigObjectCache> {
public:
typedef LocalCache<BigObjectCache> 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<AreaBackend> AreaMergedCacheStrategy;
typedef Cache<AreaMergedCacheStrategy> AreaMergedCache;
typedef LocalCache<AreaMergedCache> 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;
}