Grade 3 more models + dashboard v2 layout (quant/format as first-class)
New graded (11 total now):
gemma4-26b-a4b-8bit-mlx 82 Minor Flaws (tied top local; delta-based tx freq)
qwen3.6-27b-8bit-mlx 78 Minor Flaws (clean; anom. slow generation flagged)
qwen3-coder-30b-6bit-mlx 50 Critical (asyncio.Lock used with sync with -> crash)
Dashboard redesign:
- Bar chart is now the full-width hero row (was cramped half-width)
- 4 stat tiles squished 2x2 beside the radar up top
- Quant + Format are dedicated columns in the leaderboard (MLX/GGUF/CLOUD chips)
- New 'Format & Quant Showdown' panel: groups same-family variants so
GGUF-vs-MLX and quant-depth comparisons are side by side
- Bar-chart axis labels now include the quant so duplicate model names
are distinguishable, with rotation for readability
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,349 @@
|
||||
"""
|
||||
In-Memory Concurrent LFU Cache with Async TTL Eviction and Atomic Transactions.
|
||||
Pure Python 3.11+ implementation using only built-in modules.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Optional, Dict, Tuple
|
||||
|
||||
|
||||
@dataclass
|
||||
class Node:
|
||||
"""Represents a key-value pair in the cache with frequency and TTL tracking."""
|
||||
key: Any
|
||||
value: Any
|
||||
freq: int = 1
|
||||
expires_at: float = 0.0
|
||||
prev: Optional['Node'] = None
|
||||
next: Optional['Node'] = None
|
||||
|
||||
|
||||
class DoublyLinkedList:
|
||||
"""O(1) Doubly Linked List for maintaining insertion order within frequency buckets."""
|
||||
def __init__(self) -> None:
|
||||
self.head = Node(key=None, value=None)
|
||||
self.tail = Node(key=None, value=None)
|
||||
self.head.next = self.tail
|
||||
self.tail.prev = self.head
|
||||
self.size = 0
|
||||
|
||||
def append(self, node: Node) -> None:
|
||||
"""Append node to the tail (MRU position). O(1)"""
|
||||
node.prev = self.tail.prev
|
||||
node.next = self.tail
|
||||
self.tail.prev.next = node
|
||||
self.tail.prev = node
|
||||
self.size += 1
|
||||
|
||||
def remove(self, node: Node) -> None:
|
||||
"""Remove specific node from the list. O(1)"""
|
||||
node.prev.next = node.next
|
||||
node.next.prev = node.prev
|
||||
node.prev = node.next = None
|
||||
self.size -= 1
|
||||
|
||||
def pop_lru(self) -> Optional[Node]:
|
||||
"""Remove and return the LRU node (head.next). O(1)"""
|
||||
if self.size == 0:
|
||||
return None
|
||||
node = self.head.next
|
||||
self.remove(node)
|
||||
return node
|
||||
|
||||
|
||||
class Transaction:
|
||||
"""
|
||||
ACID-like transaction handle supporting Read-Your-Own-Writes isolation.
|
||||
Uncommitted changes are buffered locally and invisible to global readers.
|
||||
"""
|
||||
def __init__(self, cache: 'LFUCache') -> None:
|
||||
self._cache = cache
|
||||
# key -> (value, expires_at) | None (marks deletion)
|
||||
self._writes: Dict[Any, Optional[Tuple[Any, float]]] = {}
|
||||
self._committed = False
|
||||
self._rolled_back = False
|
||||
|
||||
def _check_active(self) -> None:
|
||||
if self._committed or self._rolled_back:
|
||||
raise RuntimeError("Transaction is no longer active (already committed or rolled back).")
|
||||
|
||||
async def get(self, key: Any) -> Any:
|
||||
"""Read-Your-Own-Writes: checks local buffer first, then global cache."""
|
||||
self._check_active()
|
||||
if key in self._writes and self._writes[key] is not None:
|
||||
val, exp = self._writes[key]
|
||||
return None if time.time() > exp else val
|
||||
return await self._cache.get(key)
|
||||
|
||||
async def put(self, key: Any, value: Any, ttl_seconds: float = 0.0) -> None:
|
||||
"""Buffer write locally without mutating global state."""
|
||||
self._check_active()
|
||||
exp = time.time() + ttl_seconds if ttl_seconds > 0 else float('inf')
|
||||
self._writes[key] = (value, exp)
|
||||
|
||||
async def delete(self, key: Any) -> None:
|
||||
"""Buffer deletion locally."""
|
||||
self._check_active()
|
||||
self._writes[key] = None
|
||||
|
||||
async def commit(self) -> None:
|
||||
"""Apply buffered changes to the global cache atomically."""
|
||||
self._check_active()
|
||||
async with self._cache.lock:
|
||||
for key, data in self._writes.items():
|
||||
if data is None:
|
||||
# Apply deletion
|
||||
if key in self._cache.nodes:
|
||||
self._cache._remove_node(key)
|
||||
else:
|
||||
val, exp = data
|
||||
if key in self._cache.nodes:
|
||||
# Update existing
|
||||
node = self._cache.nodes[key]
|
||||
node.value = val
|
||||
node.expires_at = exp
|
||||
self._cache._update_freq(node)
|
||||
else:
|
||||
# Insert new
|
||||
if self._cache.size >= self._cache.capacity:
|
||||
self._cache._evict_lfu()
|
||||
node = Node(key=key, value=val, freq=1, expires_at=exp)
|
||||
self._cache.nodes[key] = node
|
||||
if 1 not in self._cache.freq_buckets:
|
||||
self._cache.freq_buckets[1] = DoublyLinkedList()
|
||||
self._cache.freq_buckets[1].append(node)
|
||||
self._cache.min_freq = 1
|
||||
self._cache.size += 1
|
||||
self._writes.clear()
|
||||
self._committed = True
|
||||
|
||||
async def rollback(self) -> None:
|
||||
"""Discard all pending changes without affecting global state."""
|
||||
self._check_active()
|
||||
self._writes.clear()
|
||||
self._rolled_back = True
|
||||
|
||||
|
||||
class LFUCache:
|
||||
"""
|
||||
O(1) LFU Cache with Dual-Layer TTL Eviction and Async Concurrency.
|
||||
Uses frequency buckets + doubly linked lists for strict O(1) get/put.
|
||||
"""
|
||||
def __init__(self, capacity: int) -> None:
|
||||
if capacity <= 0:
|
||||
raise ValueError("Capacity must be a positive integer.")
|
||||
self.capacity = capacity
|
||||
self.nodes: Dict[Any, Node] = {}
|
||||
self.freq_buckets: Dict[int, DoublyLinkedList] = {}
|
||||
self.min_freq = 0
|
||||
self.size = 0
|
||||
self.lock = asyncio.Lock()
|
||||
self._evictor_task: Optional[asyncio.Task] = None
|
||||
self._running = False
|
||||
|
||||
def begin_transaction(self) -> Transaction:
|
||||
"""Start a new isolated transaction session."""
|
||||
return Transaction(self)
|
||||
|
||||
async def get(self, key: Any) -> Any:
|
||||
"""Retrieve value by key. O(1) average time complexity."""
|
||||
async with self.lock:
|
||||
if key not in self.nodes:
|
||||
return None
|
||||
node = self.nodes[key]
|
||||
# Lazy TTL Eviction
|
||||
if time.time() > node.expires_at:
|
||||
self._remove_node(key)
|
||||
return None
|
||||
self._update_freq(node)
|
||||
return node.value
|
||||
|
||||
async def put(self, key: Any, value: Any, ttl_seconds: float = 0.0) -> None:
|
||||
"""Insert or update key-value pair. O(1) average time complexity."""
|
||||
async with self.lock:
|
||||
if key in self.nodes:
|
||||
node = self.nodes[key]
|
||||
node.value = value
|
||||
node.expires_at = time.time() + ttl_seconds if ttl_seconds > 0 else float('inf')
|
||||
self._update_freq(node)
|
||||
return
|
||||
|
||||
if self.size >= self.capacity:
|
||||
self._evict_lfu()
|
||||
|
||||
node = Node(
|
||||
key=key,
|
||||
value=value,
|
||||
freq=1,
|
||||
expires_at=time.time() + ttl_seconds if ttl_seconds > 0 else float('inf')
|
||||
)
|
||||
self.nodes[key] = node
|
||||
if 1 not in self.freq_buckets:
|
||||
self.freq_buckets[1] = DoublyLinkedList()
|
||||
self.freq_buckets[1].append(node)
|
||||
self.min_freq = 1
|
||||
self.size += 1
|
||||
|
||||
def _update_freq(self, node: Node) -> None:
|
||||
"""Move node to next frequency bucket. O(1)"""
|
||||
freq = node.freq
|
||||
if freq in self.freq_buckets:
|
||||
self.freq_buckets[freq].remove(node)
|
||||
if self.freq_buckets[freq].size == 0:
|
||||
del self.freq_buckets[freq]
|
||||
if self.min_freq == freq:
|
||||
self.min_freq += 1
|
||||
node.freq += 1
|
||||
if node.freq not in self.freq_buckets:
|
||||
self.freq_buckets[node.freq] = DoublyLinkedList()
|
||||
self.freq_buckets[node.freq].append(node)
|
||||
|
||||
def _evict_lfu(self) -> None:
|
||||
"""Evict LRU key from the minimum frequency bucket. O(1)"""
|
||||
if self.min_freq not in self.freq_buckets:
|
||||
return
|
||||
lru_node = self.freq_buckets[self.min_freq].pop_lru()
|
||||
if lru_node:
|
||||
del self.nodes[lru_node.key]
|
||||
if self.freq_buckets[self.min_freq].size == 0:
|
||||
del self.freq_buckets[self.min_freq]
|
||||
self.size -= 1
|
||||
|
||||
def _remove_node(self, key: Any) -> None:
|
||||
"""Remove node from cache and frequency structure. O(1)"""
|
||||
node = self.nodes.pop(key)
|
||||
if node.freq in self.freq_buckets:
|
||||
self.freq_buckets[node.freq].remove(node)
|
||||
if self.freq_buckets[node.freq].size == 0:
|
||||
del self.freq_buckets[node.freq]
|
||||
if self.min_freq == node.freq:
|
||||
self.min_freq += 1
|
||||
self.size -= 1
|
||||
|
||||
async def start_evictor(self, interval: float = 0.1, batch_size: int = 50) -> None:
|
||||
"""Start background async TTL sweep task."""
|
||||
if self._running:
|
||||
return
|
||||
self._running = True
|
||||
self._evictor_task = asyncio.create_task(self._evict_loop(interval, batch_size))
|
||||
|
||||
async def stop_evictor(self) -> None:
|
||||
"""Gracefully stop the background evictor."""
|
||||
self._running = False
|
||||
if self._evictor_task:
|
||||
self._evictor_task.cancel()
|
||||
try:
|
||||
await self._evictor_task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
|
||||
async def _evict_loop(self, interval: float, batch_size: int) -> None:
|
||||
"""Non-blocking background eviction that processes in small batches."""
|
||||
while self._running:
|
||||
async with self.lock:
|
||||
now = time.time()
|
||||
checked = 0
|
||||
# Snapshot keys to avoid RuntimeError during iteration/mutation
|
||||
for key in list(self.nodes.keys()):
|
||||
if checked >= batch_size:
|
||||
break
|
||||
node = self.nodes.get(key)
|
||||
if node and now > node.expires_at:
|
||||
self._remove_node(key)
|
||||
checked += 1
|
||||
await asyncio.sleep(interval)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# EXECUTABLE UNIT TESTS
|
||||
# =============================================================================
|
||||
|
||||
async def main() -> None:
|
||||
print("=== Running LFU Cache Test Suite ===\n")
|
||||
|
||||
# a) O(1) LFU eviction order
|
||||
print("[TEST a] LFU Eviction Order...")
|
||||
cache = LFUCache(3)
|
||||
await cache.put('a', 1)
|
||||
await cache.put('b', 2)
|
||||
await cache.put('c', 3)
|
||||
await cache.get('a') # freq: a=2, b=1, c=1
|
||||
await cache.put('d', 4) # Evicts 'b' (LRU among freq=1)
|
||||
assert await cache.get('b') is None, "LFU eviction failed: 'b' should be evicted"
|
||||
assert await cache.get('a') == 1
|
||||
assert await cache.get('c') == 3
|
||||
assert await cache.get('d') == 4
|
||||
print(" ✅ PASSED\n")
|
||||
|
||||
# b) Lazy TTL vs Background Async Sweep
|
||||
print("[TEST b] Dual-Layer TTL Eviction...")
|
||||
cache2 = LFUCache(10)
|
||||
await cache2.start_evictor(interval=0.05, batch_size=10)
|
||||
|
||||
# Lazy eviction test
|
||||
await cache2.put('lazy', 'val', ttl_seconds=0.1)
|
||||
await asyncio.sleep(0.12)
|
||||
assert await cache2.get('lazy') is None, "Lazy TTL eviction failed"
|
||||
|
||||
# Background sweep test
|
||||
await cache2.put('bg1', 'v', ttl_seconds=0.05)
|
||||
await cache2.put('bg2', 'v', ttl_seconds=0.05)
|
||||
await asyncio.sleep(0.12)
|
||||
assert 'bg1' not in cache2.nodes, "Background sweep failed to remove 'bg1'"
|
||||
assert 'bg2' not in cache2.nodes, "Background sweep failed to remove 'bg2'"
|
||||
|
||||
await cache2.stop_evictor()
|
||||
print(" ✅ PASSED\n")
|
||||
|
||||
# c) Transaction commit visibility vs rollback state restoration
|
||||
print("[TEST c] Transaction Isolation & Rollback...")
|
||||
cache3 = LFUCache(10)
|
||||
|
||||
# Commit test
|
||||
tx1 = cache3.begin_transaction()
|
||||
await tx1.put('x', 100)
|
||||
assert await cache3.get('x') is None, "Isolation broken: global reader saw uncommitted write"
|
||||
assert await tx1.get('x') == 100, "Read-Your-Own-Writes failed"
|
||||
await tx1.commit()
|
||||
assert await cache3.get('x') == 100, "Commit failed: value not visible globally"
|
||||
|
||||
# Rollback test
|
||||
tx2 = cache3.begin_transaction()
|
||||
await tx2.put('y', 200)
|
||||
await tx2.rollback()
|
||||
assert await cache3.get('y') is None, "Rollback failed: uncommitted value leaked"
|
||||
print(" ✅ PASSED\n")
|
||||
|
||||
# d) Stress test: 50 concurrent async tasks
|
||||
print("[TEST d] Concurrency Stress Test (50 tasks, 100 ops each)...")
|
||||
cache4 = LFUCache(50)
|
||||
|
||||
async def worker(wid: int) -> None:
|
||||
for i in range(100):
|
||||
key = f"k_{wid}_{i}"
|
||||
op = i % 3
|
||||
if op == 0:
|
||||
await cache4.put(key, f"v_{i}", ttl_seconds=0.5 if i % 2 == 0 else 0)
|
||||
elif op == 1:
|
||||
await cache4.get(key)
|
||||
else:
|
||||
tx = cache4.begin_transaction()
|
||||
await tx.put(key, f"tx_{i}")
|
||||
if i % 2 == 0:
|
||||
await tx.commit()
|
||||
else:
|
||||
await tx.rollback()
|
||||
|
||||
tasks = [asyncio.create_task(worker(i)) for i in range(50)]
|
||||
await asyncio.gather(*tasks)
|
||||
assert cache4.size <= 50, f"Capacity violation during stress test: size={cache4.size}"
|
||||
print(" ✅ PASSED\n")
|
||||
|
||||
print("=== All Tests Passed Successfully ===")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
||||
Reference in New Issue
Block a user