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
|
#define _BLOCK_CACHE_H
|
||||||
|
|
||||||
|
|
||||||
#include <Locker.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -31,16 +31,18 @@ private:
|
|||||||
BBlockCache &operator=(const BBlockCache &);
|
BBlockCache &operator=(const BBlockCache &);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct _FreeBlock;
|
struct _FreeBlock;
|
||||||
|
|
||||||
_FreeBlock* fFreeList;
|
_FreeBlock* fFreeList;
|
||||||
size_t fBlockSize;
|
const size_t fBlockSize;
|
||||||
int32 fFreeBlocks;
|
void* (*fAlloc)(size_t size);
|
||||||
int32 fBlockCount;
|
void (*fFree)(void *pointer);
|
||||||
BLocker fLocker;
|
|
||||||
void* (*fAlloc)(size_t size);
|
pthread_mutex_t fLock;
|
||||||
void (*fFree)(void *pointer);
|
int32 fFreeBlocks;
|
||||||
uint32 _reserved[2];
|
int32 fBlockCount;
|
||||||
|
|
||||||
|
uint32 _reserved[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef __HAIKU__
|
#ifdef __HAIKU__
|
||||||
@@ -39,11 +40,10 @@ BBlockCache::BBlockCache(uint32 blockCount, size_t blockSize,
|
|||||||
:
|
:
|
||||||
fFreeList(0),
|
fFreeList(0),
|
||||||
fBlockSize(blockSize),
|
fBlockSize(blockSize),
|
||||||
|
fAlloc(NULL),
|
||||||
|
fFree(NULL),
|
||||||
fFreeBlocks(0),
|
fFreeBlocks(0),
|
||||||
fBlockCount(blockCount),
|
fBlockCount(blockCount)
|
||||||
fLocker("some BBlockCache lock"),
|
|
||||||
fAlloc(0),
|
|
||||||
fFree(0)
|
|
||||||
{
|
{
|
||||||
switch (allocationType) {
|
switch (allocationType) {
|
||||||
case B_OBJECT_CACHE:
|
case B_OBJECT_CACHE:
|
||||||
@@ -61,6 +61,8 @@ BBlockCache::BBlockCache(uint32 blockCount, size_t blockSize,
|
|||||||
if (heap_debug_get_allocation_info != NULL)
|
if (heap_debug_get_allocation_info != NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
pthread_mutex_init(&fLock, NULL);
|
||||||
|
|
||||||
// To properly maintain a list of free buffers, a buffer must be
|
// To properly maintain a list of free buffers, a buffer must be
|
||||||
// large enough to contain the _FreeBlock struct that is used.
|
// large enough to contain the _FreeBlock struct that is used.
|
||||||
if (blockSize < sizeof(_FreeBlock))
|
if (blockSize < sizeof(_FreeBlock))
|
||||||
@@ -87,7 +89,7 @@ BBlockCache::BBlockCache(uint32 blockCount, size_t blockSize,
|
|||||||
BBlockCache::~BBlockCache()
|
BBlockCache::~BBlockCache()
|
||||||
{
|
{
|
||||||
// walk the free list and deallocate all blocks
|
// walk the free list and deallocate all blocks
|
||||||
fLocker.Lock();
|
pthread_mutex_lock(&fLock);
|
||||||
while (fFreeList) {
|
while (fFreeList) {
|
||||||
ASSERT(fFreeList->magic1 == MAGIC1);
|
ASSERT(fFreeList->magic1 == MAGIC1);
|
||||||
ASSERT(fFreeList->magic2 == MAGIC2 + (uint32)(addr_t)fFreeList->next);
|
ASSERT(fFreeList->magic2 == MAGIC2 + (uint32)(addr_t)fFreeList->next);
|
||||||
@@ -96,7 +98,8 @@ BBlockCache::~BBlockCache()
|
|||||||
DEBUG_ONLY(memset(pointer, 0xCC, sizeof(_FreeBlock)));
|
DEBUG_ONLY(memset(pointer, 0xCC, sizeof(_FreeBlock)));
|
||||||
fFree(pointer);
|
fFree(pointer);
|
||||||
}
|
}
|
||||||
fLocker.Unlock();
|
|
||||||
|
pthread_mutex_destroy(&fLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -106,8 +109,7 @@ BBlockCache::Get(size_t blockSize)
|
|||||||
if (heap_debug_get_allocation_info != NULL)
|
if (heap_debug_get_allocation_info != NULL)
|
||||||
return fAlloc(blockSize);
|
return fAlloc(blockSize);
|
||||||
|
|
||||||
if (!fLocker.Lock())
|
pthread_mutex_lock(&fLock);
|
||||||
return 0;
|
|
||||||
void *pointer;
|
void *pointer;
|
||||||
if (blockSize == fBlockSize && fFreeList != 0) {
|
if (blockSize == fBlockSize && fFreeList != 0) {
|
||||||
// we can take a block from the list
|
// we can take a block from the list
|
||||||
@@ -117,14 +119,16 @@ BBlockCache::Get(size_t blockSize)
|
|||||||
fFreeList = fFreeList->next;
|
fFreeList = fFreeList->next;
|
||||||
fFreeBlocks--;
|
fFreeBlocks--;
|
||||||
DEBUG_ONLY(memset(pointer, 0xCC, sizeof(_FreeBlock)));
|
DEBUG_ONLY(memset(pointer, 0xCC, sizeof(_FreeBlock)));
|
||||||
|
pthread_mutex_unlock(&fLock);
|
||||||
|
return pointer;
|
||||||
} else {
|
} else {
|
||||||
|
pthread_mutex_unlock(&fLock);
|
||||||
if (blockSize < sizeof(_FreeBlock))
|
if (blockSize < sizeof(_FreeBlock))
|
||||||
blockSize = sizeof(_FreeBlock);
|
blockSize = sizeof(_FreeBlock);
|
||||||
pointer = fAlloc(blockSize);
|
pointer = fAlloc(blockSize);
|
||||||
DEBUG_ONLY(if (pointer) memset(pointer, 0xCC, sizeof(_FreeBlock)));
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fLocker.Lock())
|
pthread_mutex_lock(&fLock);
|
||||||
return;
|
|
||||||
if (blockSize == fBlockSize && fFreeBlocks < fBlockCount) {
|
if (blockSize == fBlockSize && fFreeBlocks < fBlockCount) {
|
||||||
// the block needs to be returned to the cache
|
// the block needs to be returned to the cache
|
||||||
_FreeBlock *block = reinterpret_cast<_FreeBlock *>(pointer);
|
_FreeBlock *block = reinterpret_cast<_FreeBlock *>(pointer);
|
||||||
@@ -146,11 +149,13 @@ BBlockCache::Save(void *pointer, size_t blockSize)
|
|||||||
fFreeBlocks++;
|
fFreeBlocks++;
|
||||||
DEBUG_ONLY(block->magic1 = MAGIC1);
|
DEBUG_ONLY(block->magic1 = MAGIC1);
|
||||||
DEBUG_ONLY(block->magic2 = MAGIC2 + (uint32)(addr_t)block->next);
|
DEBUG_ONLY(block->magic2 = MAGIC2 + (uint32)(addr_t)block->next);
|
||||||
|
pthread_mutex_unlock(&fLock);
|
||||||
} else {
|
} else {
|
||||||
|
pthread_mutex_unlock(&fLock);
|
||||||
DEBUG_ONLY(memset(pointer, 0xCC, sizeof(_FreeBlock)));
|
DEBUG_ONLY(memset(pointer, 0xCC, sizeof(_FreeBlock)));
|
||||||
fFree(pointer);
|
fFree(pointer);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
fLocker.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user