⚠ SPEED CAVEAT: All Gemma 4 models ran abnormally slow (GPU offload appeared inactive despite being set), so tok/sec and TTFT are NOT representative of the model itself — likely an LM Studio/GGUF config issue. Treat speed numbers for the Gemma 4 batch as suspect.
tok/sec10.09
tokens4536
TTFT4.39s
▮ PILLAR BREAKDOWN
Complexity (O(1))
17/20
Concurrency / Races
16/20
Tx Isolation
14/20
Memory & Edges
15/20
Test Integrity
16/20
✓ WENT RIGHT
Complexity (O(1)) (17/20)
Concurrency / Races (16/20)
Test Integrity (16/20)
✗ WENT WRONG
No pillar fell below 14 — solid across the board.
▮ CRITICAL BUGS
Isolation leak: Transaction.get falls back to the PUBLIC cache.get, which calls _update_frequency — so reading a key inside a transaction mutates GLOBAL frequency state before commit, leaking uncommitted access patterns into global eviction order. Spec requires tx reads not to alter global freq.
Uses time.time() (system clock) throughout instead of time.monotonic() — NTP adjustments corrupt TTL eviction.
No __slots__ on Node/DoublyLinkedList/LFUCache/Transaction — rubric required it for memory efficiency.
_delete_internal deliberately leaves empty frequency buckets in freq_map (documented but a minor memory leak: empty DoublyLinkedList objects accumulate).
Background evictor does list(self.cache.keys()) = O(N) snapshot every interval — a linear scan, forbidden by strict O(1).
No MVCC/version check on commit (lost-update possible); commit is not exception-safe across the deletes-vs-puts loops.
Tests pass but don't probe mid-commit read isolation or eviction-under-real-contention (capacity sized so all keys fit), so the isolation leak above goes undetected.
▮ RECOMMENDED USE
Clean, correct, runnable code with solid O(1) structure and good concurrency granularity. A reliable pick for everyday caching/async work after a monotonic-clock + __slots__ pass.
▮ REFACTORED PATCH
# FIX 1 (the isolation leak): tx reads must NOT mutate global freq.
# Add a read-only global lookup (no _update_frequency) and use it in tx.get:
async def _read_raw(self, key): # no freq bump
node = self.cache.get(key)
if node is None: return None
if time.monotonic() > node.expiry:
await self._delete_internal(key)
return None
return node.value
# then in Transaction.get fallback:
return await self._cache._read_raw(key) # NOT cache.get
# FIX 2: time.time() -> time.monotonic() everywhere (get/put/_put_internal/bg loop).
# FIX 3: add __slots__ to Node, DoublyLinkedList, LFUCache, Transaction.
# FIX 4: prune empty freq buckets on delete, or have _evict_lfu drop them.
# FIX 5: iterate a dedicated _ttl_keys set (batched) in the bg evictor
# instead of list(self.cache.keys()) to stay O(batch), not O(N).