Skip to content
Permalink
Browse files

block_cache: Use an object_cache for the cache_notifications.

cache_listeners are (following packagefs changes) the second-most
allocated object during the boot process, with 20799 on a
*minimum* image. Since they are used so extensively in BFS I/O,
making them object_cached for both performance and memory reasons
seems to make a lot of sense.

Change-Id: I6ef6c3e811c0c4189fea45ee7920131796c9e7c8
Reviewed-on: https://review.haiku-os.org/c/1577
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
Reviewed-by: Stephan Aßmus <superstippi@gmx.de>
  • Loading branch information...
waddlesplash committed Jul 10, 2019
1 parent 7a2f744 commit 0e6ece91c81de4bb1056c4743c09d40d6106c4a1
Showing with 41 additions and 13 deletions.
  1. +41 −13 src/system/kernel/cache/block_cache.cpp
@@ -114,6 +114,9 @@ typedef DoublyLinkedList<cached_block,
&cached_block::link> > block_list;

struct cache_notification : DoublyLinkedListLinkImpl<cache_notification> {
static inline void* operator new(size_t size);
static inline void operator delete(void* block);

int32 transaction_id;
int32 events_pending;
int32 events;
@@ -124,6 +127,38 @@ struct cache_notification : DoublyLinkedListLinkImpl<cache_notification> {

typedef DoublyLinkedList<cache_notification> NotificationList;

static object_cache* sCacheNotificationCache;

struct cache_listener;
typedef DoublyLinkedListLink<cache_listener> listener_link;

struct cache_listener : cache_notification {
listener_link link;
};

typedef DoublyLinkedList<cache_listener,
DoublyLinkedListMemberGetLink<cache_listener,
&cache_listener::link> > ListenerList;

void*
cache_notification::operator new(size_t size)
{
// We can't really know whether something is a cache_notification or a
// cache_listener at runtime, so we just use one object_cache for both
// with the size set to that of the (slightly larger) cache_listener.
// In practice, the vast majority of cache_notifications are really
// cache_listeners, so this is a more than acceptable trade-off.
ASSERT(size <= sizeof(cache_listener));
return object_cache_alloc(sCacheNotificationCache, 0);
}

void
cache_notification::operator delete(void* block)
{
object_cache_free(sCacheNotificationCache, block, 0);
}


struct BlockHash {
typedef off_t KeyType;
typedef cached_block ValueType;
@@ -219,18 +254,6 @@ struct block_cache : DoublyLinkedListLinkImpl<block_cache> {
cached_block* _GetUnusedBlock();
};

struct cache_listener;
typedef DoublyLinkedListLink<cache_listener> listener_link;

struct cache_listener : cache_notification {
listener_link link;
};

typedef DoublyLinkedList<cache_listener,
DoublyLinkedListMemberGetLink<cache_listener,
&cache_listener::link> > ListenerList;


struct cache_transaction {
cache_transaction();

@@ -963,7 +986,7 @@ add_transaction_listener(block_cache* cache, cache_transaction* transaction,
}
}

cache_listener* listener = new(std::nothrow) cache_listener;
cache_listener* listener = new cache_listener;
if (listener == NULL)
return B_NO_MEMORY;

@@ -2662,6 +2685,11 @@ block_cache_init(void)
if (sBlockCache == NULL)
return B_NO_MEMORY;

sCacheNotificationCache = create_object_cache("cache notifications",
sizeof(cache_listener), 8, NULL, NULL, NULL);
if (sCacheNotificationCache == NULL)
return B_NO_MEMORY;

new (&sCaches) DoublyLinkedList<block_cache>;
// manually call constructor

0 comments on commit 0e6ece9

Please sign in to comment.
You can’t perform that action at this time.