BBlockCache: Use a pthread_mutex instead of BLocker.
The lighter "struct mutex" is in a private header, so we can't inline it in a public one, so just use pthread_mutex here. By adjusting padding, the class size stays the same (72 bytes on 32-bit, 96 bytes on 64-bit; confirmed via static_assert.) A quick benchmark running "new/delete BMessage" in a loop on 4 threads at once goes from 30-36 seconds before this commit to around 13-17 seconds, sometimes as low as 3 seconds, afterwards, so clearly this is a significant improvement. This also eliminates another BLocker allocated on application startup.
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
#define _BLOCK_CACHE_H
|
||||
|
||||
|
||||
#include <Locker.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
enum {
|
||||
@@ -31,16 +31,18 @@ private:
|
||||
BBlockCache &operator=(const BBlockCache &);
|
||||
|
||||
private:
|
||||
struct _FreeBlock;
|
||||
struct _FreeBlock;
|
||||
|
||||
_FreeBlock* fFreeList;
|
||||
size_t fBlockSize;
|
||||
int32 fFreeBlocks;
|
||||
int32 fBlockCount;
|
||||
BLocker fLocker;
|
||||
void* (*fAlloc)(size_t size);
|
||||
void (*fFree)(void *pointer);
|
||||
uint32 _reserved[2];
|
||||
_FreeBlock* fFreeList;
|
||||
const size_t fBlockSize;
|
||||
void* (*fAlloc)(size_t size);
|
||||
void (*fFree)(void *pointer);
|
||||
|
||||
pthread_mutex_t fLock;
|
||||
int32 fFreeBlocks;
|
||||
int32 fBlockCount;
|
||||
|
||||
uint32 _reserved[6];
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <new>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
#ifdef __HAIKU__
|
||||
@@ -39,11 +40,10 @@ BBlockCache::BBlockCache(uint32 blockCount, size_t blockSize,
|
||||
:
|
||||
fFreeList(0),
|
||||
fBlockSize(blockSize),
|
||||
fAlloc(NULL),
|
||||
fFree(NULL),
|
||||
fFreeBlocks(0),
|
||||
fBlockCount(blockCount),
|
||||
fLocker("some BBlockCache lock"),
|
||||
fAlloc(0),
|
||||
fFree(0)
|
||||
fBlockCount(blockCount)
|
||||
{
|
||||
switch (allocationType) {
|
||||
case B_OBJECT_CACHE:
|
||||
@@ -61,6 +61,8 @@ BBlockCache::BBlockCache(uint32 blockCount, size_t blockSize,
|
||||
if (heap_debug_get_allocation_info != NULL)
|
||||
return;
|
||||
|
||||
pthread_mutex_init(&fLock, NULL);
|
||||
|
||||
// To properly maintain a list of free buffers, a buffer must be
|
||||
// large enough to contain the _FreeBlock struct that is used.
|
||||
if (blockSize < sizeof(_FreeBlock))
|
||||
@@ -87,7 +89,7 @@ BBlockCache::BBlockCache(uint32 blockCount, size_t blockSize,
|
||||
BBlockCache::~BBlockCache()
|
||||
{
|
||||
// walk the free list and deallocate all blocks
|
||||
fLocker.Lock();
|
||||
pthread_mutex_lock(&fLock);
|
||||
while (fFreeList) {
|
||||
ASSERT(fFreeList->magic1 == MAGIC1);
|
||||
ASSERT(fFreeList->magic2 == MAGIC2 + (uint32)(addr_t)fFreeList->next);
|
||||
@@ -96,7 +98,8 @@ BBlockCache::~BBlockCache()
|
||||
DEBUG_ONLY(memset(pointer, 0xCC, sizeof(_FreeBlock)));
|
||||
fFree(pointer);
|
||||
}
|
||||
fLocker.Unlock();
|
||||
|
||||
pthread_mutex_destroy(&fLock);
|
||||
}
|
||||
|
||||
|
||||
@@ -106,8 +109,7 @@ BBlockCache::Get(size_t blockSize)
|
||||
if (heap_debug_get_allocation_info != NULL)
|
||||
return fAlloc(blockSize);
|
||||
|
||||
if (!fLocker.Lock())
|
||||
return 0;
|
||||
pthread_mutex_lock(&fLock);
|
||||
void *pointer;
|
||||
if (blockSize == fBlockSize && fFreeList != 0) {
|
||||
// we can take a block from the list
|
||||
@@ -117,14 +119,16 @@ BBlockCache::Get(size_t blockSize)
|
||||
fFreeList = fFreeList->next;
|
||||
fFreeBlocks--;
|
||||
DEBUG_ONLY(memset(pointer, 0xCC, sizeof(_FreeBlock)));
|
||||
pthread_mutex_unlock(&fLock);
|
||||
return pointer;
|
||||
} else {
|
||||
pthread_mutex_unlock(&fLock);
|
||||
if (blockSize < sizeof(_FreeBlock))
|
||||
blockSize = sizeof(_FreeBlock);
|
||||
pointer = fAlloc(blockSize);
|
||||
DEBUG_ONLY(if (pointer) memset(pointer, 0xCC, sizeof(_FreeBlock)));
|
||||
return pointer;
|
||||
}
|
||||
fLocker.Unlock();
|
||||
return pointer;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,8 +140,7 @@ BBlockCache::Save(void *pointer, size_t blockSize)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fLocker.Lock())
|
||||
return;
|
||||
pthread_mutex_lock(&fLock);
|
||||
if (blockSize == fBlockSize && fFreeBlocks < fBlockCount) {
|
||||
// the block needs to be returned to the cache
|
||||
_FreeBlock *block = reinterpret_cast<_FreeBlock *>(pointer);
|
||||
@@ -146,11 +149,13 @@ BBlockCache::Save(void *pointer, size_t blockSize)
|
||||
fFreeBlocks++;
|
||||
DEBUG_ONLY(block->magic1 = MAGIC1);
|
||||
DEBUG_ONLY(block->magic2 = MAGIC2 + (uint32)(addr_t)block->next);
|
||||
pthread_mutex_unlock(&fLock);
|
||||
} else {
|
||||
pthread_mutex_unlock(&fLock);
|
||||
DEBUG_ONLY(memset(pointer, 0xCC, sizeof(_FreeBlock)));
|
||||
fFree(pointer);
|
||||
return;
|
||||
}
|
||||
fLocker.Unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user