From e44cfc7128397a5eef782d0e3e45598b5ecea99d Mon Sep 17 00:00:00 2001 From: xfy Date: Thu, 4 Jun 2026 00:13:29 +0800 Subject: [PATCH] perf(handler): eliminate read-lock upgrade in FileInfoCache.Get with approximate LRU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FileInfoCache.Get previously acquired TWO locks on every cache hit: 1. RLock → check existence + TTL 2. Release RLock → Lock → MoveToFront (LRU update) → Unlock The MoveToFront on every hit forced a read-to-write lock upgrade, creating contention under concurrent reads. Apply approximate LRU: skip MoveToFront on Get (read) path entirely. LRU position is only updated in Set (write) path. This is the same pattern already used by internal/cache/file_cache.go. Result: Get fast path reduced from 2 lock acquisitions to 1 RLock. TTL-expired entries still use double-check locking for safe removal. --- internal/handler/fileinfo_cache.go | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/internal/handler/fileinfo_cache.go b/internal/handler/fileinfo_cache.go index cd77ae1..e7e0e3c 100644 --- a/internal/handler/fileinfo_cache.go +++ b/internal/handler/fileinfo_cache.go @@ -47,32 +47,20 @@ func (c *FileInfoCache) Get(filePath string) (os.FileInfo, bool) { return nil, false } - // 检查 TTL(只读检查) if time.Since(entry.cachedAt) > fileInfoCacheTTL { c.mu.RUnlock() - // 升级为写锁删除过期条目 c.mu.Lock() - // double-check:可能已被其他请求删除或更新 - if entry, ok := c.entries[filePath]; ok && time.Since(entry.cachedAt) > fileInfoCacheTTL { - c.lruList.Remove(entry.element) + if e, ok := c.entries[filePath]; ok && time.Since(e.cachedAt) > fileInfoCacheTTL { + c.lruList.Remove(e.element) delete(c.entries, filePath) } c.mu.Unlock() return nil, false } + info := entry.info c.mu.RUnlock() - - // LRU 移动需要写锁 - c.mu.Lock() - // double-check:条目可能已被删除 - if entry, ok := c.entries[filePath]; ok { - c.lruList.MoveToFront(entry.element) - c.mu.Unlock() - return entry.info, true - } - c.mu.Unlock() - return nil, false + return info, true } // Set 缓存 FileInfo