From 86a11b8483d0613ea3d72ea2209f35162061d4cd Mon Sep 17 00:00:00 2001 From: Csaba Kiraly Date: Wed, 17 Dec 2025 12:11:50 +0100 Subject: [PATCH] common/lru: add metered lru variant This is a drop-in replacement to add metrics to an LRU cache. Signed-off-by: Csaba Kiraly --- common/lru/metered_lru.go | 64 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 common/lru/metered_lru.go diff --git a/common/lru/metered_lru.go b/common/lru/metered_lru.go new file mode 100644 index 0000000000..7909c95a7d --- /dev/null +++ b/common/lru/metered_lru.go @@ -0,0 +1,64 @@ +// Copyright 2026 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package lru + +import ( + "github.com/ethereum/go-ethereum/metrics" +) + +// MeteredCache is an LRU cache exposing hit metrics. +// This type is safe for concurrent use. +type MeteredCache[K comparable, V any] struct { + Cache[K, V] + hit *metrics.Meter + miss *metrics.Meter +} + +// NewMeteredCache creates a new metered LRU cache. +func NewMeteredCache[K comparable, V any](capacity int, name string) *MeteredCache[K, V] { + return &MeteredCache[K, V]{ + Cache: *NewCache[K, V](capacity), + hit: metrics.NewRegisteredMeter(name+"/hit", nil), + miss: metrics.NewRegisteredMeter(name+"/miss", nil), + } +} + +// Contains reports whether the given key exists in the cache. +func (c *MeteredCache[K, V]) Contains(key K) bool { + ret := c.Cache.Contains(key) + if c.hit != nil && c.miss != nil { + if ret { + c.hit.Mark(1) + } else { + c.miss.Mark(1) + } + } + return ret +} + +// Get retrieves a value from the cache. This marks the key as recently used. +func (c *MeteredCache[K, V]) Get(key K) (value V, ok bool) { + ret, ok := c.Cache.Get(key) + if c.hit != nil && c.miss != nil { + if ok { + c.hit.Mark(1) + } else { + c.miss.Mark(1) + } + } + return ret, ok +}