From 2f2e04142e80e6762761cb90522b8276a13bdeab Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Wed, 14 May 2025 22:05:53 +0000 Subject: [PATCH] libutil: Simplify LRUCache::get by using list splice Splicing the list element to the back can be done in a much simpler and concise way without the need for erasing and re-inserting the element. Doing it this way is equivalent to just moving node pointers around, whereas inserting/erasing allocates/deallocates new nodes. --- src/libutil/include/nix/util/lru-cache.hh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libutil/include/nix/util/lru-cache.hh b/src/libutil/include/nix/util/lru-cache.hh index 20891a086..686b73149 100644 --- a/src/libutil/include/nix/util/lru-cache.hh +++ b/src/libutil/include/nix/util/lru-cache.hh @@ -93,12 +93,16 @@ public: /** * Move this item to the back of the LRU list. + * + * Think of std::list iterators as stable pointers to the list node, + * which never get invalidated. Thus, we can reuse the same lru list + * element and just splice it to the back of the list without the need + * to update its value in the key -> list iterator map. */ - lru.erase(i->second.first.it); - auto j = lru.insert(lru.end(), i); - i->second.first.it = j; + auto & [it, value] = i->second; + lru.splice(/*pos=*/lru.end(), /*other=*/lru, it.it); - return i->second.second; + return value; } size_t size() const