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:
@@ -36,6 +36,77 @@ static const int kMagazineCapacity = 32;
|
|||||||
|
|
||||||
static const size_t kCacheColorPeriod = 8;
|
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 depot_magazine *_AllocMagazine();
|
||||||
static void _FreeMagazine(depot_magazine *magazine);
|
static void _FreeMagazine(depot_magazine *magazine);
|
||||||
|
|
||||||
@@ -545,44 +616,66 @@ base_depot_make_empty(base_depot *depot)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef MergedLinkCacheStrategy<AreaBackend> AreaMergedCacheStrategy;
|
static inline int
|
||||||
typedef Cache<AreaMergedCacheStrategy> AreaMergedCache;
|
__Fls(size_t value)
|
||||||
typedef LocalCache<AreaMergedCache> AreaLocalCache;
|
{
|
||||||
|
if (value == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int bit;
|
||||||
|
for (bit = 1; value != 1; bit++)
|
||||||
|
value >>= 1;
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
object_cache_t
|
object_cache_t
|
||||||
object_cache_create(const char *name, size_t object_size, size_t alignment,
|
object_cache_create(const char *name, size_t object_size, size_t alignment,
|
||||||
status_t (*_constructor)(void *, void *), void (*_destructor)(void *,
|
status_t (*_constructor)(void *, void *), void (*_destructor)(void *,
|
||||||
void *), void *cookie)
|
void *), void *cookie)
|
||||||
{
|
{
|
||||||
return new (std::nothrow) AreaLocalCache(name, object_size, alignment,
|
if (object_size == 0)
|
||||||
_constructor, _destructor, cookie);
|
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 *
|
void *
|
||||||
object_cache_alloc(object_cache_t cache)
|
object_cache_alloc(object_cache_t cache)
|
||||||
{
|
{
|
||||||
return ((AreaLocalCache *)cache)->Alloc(0);
|
return object_cache_alloc_etc(cache, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void *
|
void *
|
||||||
object_cache_alloc_etc(object_cache_t cache, uint32_t flags)
|
object_cache_alloc_etc(object_cache_t cache, uint32_t flags)
|
||||||
{
|
{
|
||||||
return ((AreaLocalCache *)cache)->Alloc(flags);
|
return ((AbstractCache *)cache)->Allocate(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
object_cache_free(object_cache_t cache, void *object)
|
object_cache_free(object_cache_t cache, void *object)
|
||||||
{
|
{
|
||||||
((AreaLocalCache *)cache)->Free(object);
|
((AbstractCache *)cache)->Return(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
object_cache_destroy(object_cache_t cache)
|
object_cache_destroy(object_cache_t cache)
|
||||||
{
|
{
|
||||||
delete (AreaLocalCache *)cache;
|
delete (AbstractCache *)cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user