From 0e6ece91c81de4bb1056c4743c09d40d6106c4a1 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Wed, 10 Jul 2019 19:21:14 -0400 Subject: [PATCH] block_cache: Use an object_cache for the cache_notifications. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Stephan Aßmus --- src/system/kernel/cache/block_cache.cpp | 54 +++++++++++++++++++------ 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/src/system/kernel/cache/block_cache.cpp b/src/system/kernel/cache/block_cache.cpp index a81b9c2476..37147582ca 100644 --- a/src/system/kernel/cache/block_cache.cpp +++ b/src/system/kernel/cache/block_cache.cpp @@ -114,6 +114,9 @@ typedef DoublyLinkedList > block_list; struct cache_notification : DoublyLinkedListLinkImpl { + 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 { typedef DoublyLinkedList NotificationList; +static object_cache* sCacheNotificationCache; + +struct cache_listener; +typedef DoublyLinkedListLink listener_link; + +struct cache_listener : cache_notification { + listener_link link; +}; + +typedef DoublyLinkedList > 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 @@ private: cached_block* _GetUnusedBlock(); }; -struct cache_listener; -typedef DoublyLinkedListLink listener_link; - -struct cache_listener : cache_notification { - listener_link link; -}; - -typedef DoublyLinkedList > 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; // manually call constructor