Files
modelTesting/outputs/qwen3.6-35b-a3b-4bit-mlx.py
T
adminandClaude f0281f2878 Initial benchmark suite: 8 graded models + cyberpunk dashboard generator
- prompts/: LFU cache exam + 5-pillar grading rubric
- outputs/: 8 model .py outputs (local + cloud baseline)
- data/benchmark_history.json: graded results (scores, metrics, bugs, patches)
- generate_dashboard.py: builds dashboard.html + pages/*.html from JSON
- Dockerfile + DEPLOY.md: Gitea→Coolify deploy (build-step, nginx static)
- .gitignore: generated HTML excluded (built on deploy)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-28 14:00:40 -07:00

366 lines
13 KiB
Python

"""
In-Memory Concurrent LFU Cache with Async TTL Eviction and Atomic Transactions.
Pure Python 3.11+ implementation using only standard library modules.
"""
import asyncio
import time
from typing import Any, Dict, List, Optional, Tuple
from asyncio import Lock
# ---------------------------------------------------------------------------
# Internal Data Structures (O(1) LFU Core)
# ---------------------------------------------------------------------------
class _Node:
"""Doubly linked list node tracking key, value, frequency, and TTL."""
__slots__ = ('key', 'value', 'freq', 'expires_at', 'prev', 'next')
def __init__(self, key: Any, value: Any, freq: int = 1, expires_at: float = 0.0):
self.key = key
self.value = value
self.freq = freq
self.expires_at = expires_at
self.prev = None
self.next = None
class _FreqList:
"""Doubly linked list maintaining nodes of a specific frequency tier."""
__slots__ = ('head', 'tail', 'size')
def __init__(self):
self.head = _Node(None, None) # Dummy head
self.tail = _Node(None, None) # Dummy tail
self.head.next = self.tail
self.tail.prev = self.head
self.size = 0
def add(self, node: _Node):
"""Add node to tail (most recently used in this frequency)."""
last = self.tail.prev
last.next = node
node.prev = last
node.next = self.tail
self.tail.prev = node
self.size += 1
def remove(self, node: _Node):
"""Remove node from the list in O(1)."""
node.prev.next = node.next
node.next.prev = node.prev
node.prev = None
node.next = None
self.size -= 1
def pop(self) -> _Node:
"""Remove and return node from head (least recently used)."""
node = self.head.next
self.remove(node)
return node
# ---------------------------------------------------------------------------
# Main Cache Implementation
# ---------------------------------------------------------------------------
class LFUCache:
"""
O(1) In-Memory Concurrent LFU Cache with Async TTL Eviction.
Uses a hash map for key lookup and a hash map of frequency-buckets
with doubly linked lists for O(1) frequency updates and eviction.
"""
def __init__(self, capacity: int, evict_interval: float = 1.0):
self.capacity = capacity
self.evict_interval = evict_interval
self.key_to_node: Dict[Any, _Node] = {}
self.freq_to_list: Dict[int, _FreqList] = {}
self.min_freq: int = 1
self.lock: Lock = asyncio.Lock()
self._evict_task: Optional[asyncio.Task] = None
self._running = False
async def start_evictor(self):
"""Start the non-blocking background TTL eviction loop."""
self._running = True
self._evict_task = asyncio.create_task(self._eviction_loop())
async def stop_evictor(self):
"""Gracefully stop the background eviction task."""
self._running = False
if self._evict_task:
self._evict_task.cancel()
try: await self._evict_task
except asyncio.CancelledError: pass
async def get(self, key: Any) -> Optional[Any]:
"""Retrieve value in O(1). Performs lazy TTL eviction and frequency update."""
async with self.lock:
node = self.key_to_node.get(key)
if not node:
return None
# Lazy TTL Eviction
if node.expires_at > 0 and node.expires_at <= time.time():
self._remove_node(node)
return None
# O(1) Frequency Update
self._update_freq(node)
return node.value
async def put(self, key: Any, value: Any, ttl_seconds: float = 0.0):
"""Insert/update value in O(1). Handles capacity eviction and TTL."""
async with self.lock:
node = self.key_to_node.get(key)
if node:
# Update existing node
node.value = value
if ttl_seconds > 0:
node.expires_at = time.time() + ttl_seconds
self._update_freq(node)
else:
# Evict if capacity reached
if len(self.key_to_node) >= self.capacity:
self._evict()
# Insert new node with freq=1
node = _Node(
key, value, freq=1,
expires_at=float('inf') if ttl_seconds <= 0 else time.time() + ttl_seconds
)
self.key_to_node[key] = node
self._add_to_freq(node)
self.min_freq = 1 # New keys always start at freq 1
async def begin_transaction(self) -> 'Transaction':
"""Create an isolated transaction session."""
return Transaction(self)
# --- Internal Cache Helpers (O(1)) ---
def _remove_node(self, node: _Node):
"""Remove node from global structures."""
del self.key_to_node[node.key]
self.freq_to_list[node.freq].remove(node)
if self.freq_to_list[node.freq].size == 0:
del self.freq_to_list[node.freq]
if self.min_freq == node.freq:
self.min_freq += 1
def _update_freq(self, node: _Node):
"""Move node to next frequency bucket in O(1)."""
old_freq = node.freq
self.freq_to_list[old_freq].remove(node)
if self.freq_to_list[old_freq].size == 0:
del self.freq_to_list[old_freq]
if self.min_freq == old_freq:
self.min_freq += 1
node.freq += 1
self._add_to_freq(node)
def _add_to_freq(self, node: _Node):
"""Add node to its frequency bucket."""
if node.freq not in self.freq_to_list:
self.freq_to_list[node.freq] = _FreqList()
self.freq_to_list[node.freq].add(node)
def _evict(self):
"""Evict least frequently used (then LRU) node in O(1)."""
if not self.freq_to_list:
return
evict_list = self.freq_to_list[self.min_freq]
node = evict_list.pop()
self._remove_node(node)
async def _eviction_loop(self):
"""Background async task that purges expired keys in small batches."""
while self._running:
await asyncio.sleep(self.evict_interval)
async with self.lock:
# Batch scan limited to avoid blocking reads
keys_to_check = list(self.key_to_node.keys())[:50]
for k in keys_to_check:
node = self.key_to_node.get(k)
if node and node.expires_at > 0 and node.expires_at <= time.time():
self._remove_node(node)
# ---------------------------------------------------------------------------
# Transaction Isolation Layer
# ---------------------------------------------------------------------------
class Transaction:
"""
Atomic transaction session providing Read-Your-Own-Writes isolation.
Global readers remain blind to uncommitted changes until commit().
"""
def __init__(self, cache: LFUCache):
self.cache = cache
self.buffer: List[Dict] = []
self.committed = False
async def get(self, key: Any) -> Optional[Any]:
"""Read with local isolation. Does not update global frequencies."""
# Read-Your-Own-Writes: check buffer first
for op in reversed(self.buffer):
if op['key'] == key:
return None if op['op'] == 'delete' else op['value']
# Global read (no freq update to preserve isolation)
async with self.cache.lock:
node = self.cache.key_to_node.get(key)
if not node:
return None
# Lazy TTL check without mutation
if node.expires_at > 0 and node.expires_at <= time.time():
return None
return node.value
async def put(self, key: Any, value: Any, ttl_seconds: float = 0.0):
"""Buffer a put operation without mutating global state."""
original = self.cache.key_to_node.get(key)
self.buffer.append({'op': 'put', 'key': key, 'value': value, 'ttl': ttl_seconds, 'original': original})
async def delete(self, key: Any):
"""Buffer a delete operation without mutating global state."""
original = self.cache.key_to_node.get(key)
self.buffer.append({'op': 'delete', 'key': key, 'original': original})
async def commit(self):
"""Apply buffered changes to global cache atomically."""
async with self.cache.lock:
# Merge buffer: keep only the latest operation per key
merged = {}
for op in self.buffer:
merged[op['key']] = op
for op in merged.values():
if op['op'] == 'put':
await self._apply_put(op['key'], op['value'], op['ttl'], self.cache.key_to_node.get(op['key']))
elif op['op'] == 'delete':
await self._apply_delete(op['key'], self.cache.key_to_node.get(op['key']))
self.buffer.clear()
self.committed = True
async def rollback(self):
"""Discard all pending changes without affecting global frequencies or TTL."""
self.buffer.clear()
self.committed = False
async def _apply_put(self, key: Any, value: Any, ttl: float, original_node: Optional[_Node]):
"""Apply buffered put to global cache."""
if original_node:
original_node.value = value
if ttl > 0:
original_node.expires_at = time.time() + ttl
self.cache._update_freq(original_node)
else:
if len(self.cache.key_to_node) >= self.cache.capacity:
self.cache._evict()
node = _Node(
key, value, freq=1,
expires_at=float('inf') if ttl <= 0 else time.time() + ttl
)
self.cache.key_to_node[key] = node
self.cache._add_to_freq(node)
self.cache.min_freq = 1
async def _apply_delete(self, key: Any, original_node: Optional[_Node]):
"""Apply buffered delete to global cache."""
if original_node:
self.cache._remove_node(original_node)
# ---------------------------------------------------------------------------
# Executable Unit Tests
# ---------------------------------------------------------------------------
async def main():
print("🧪 Running LFU Cache Test Suite...\n")
await test_lfu_eviction()
await test_ttl_eviction()
await test_transactions()
await test_stress()
print("✅ All tests passed successfully!")
async def test_lfu_eviction():
"""Verifies strict O(1) LFU eviction order when capacity is reached."""
cache = LFUCache(3)
await cache.put(1, 1)
await cache.put(2, 2)
await cache.put(3, 3)
# Access 1 -> freq becomes 2
assert await cache.get(1) == 1
# Insert 4 -> evicts key 2 (freq=1, LRU among freq=1)
await cache.put(4, 4)
assert await cache.get(2) is None, "Key 2 should be evicted"
assert await cache.get(1) == 1
assert await cache.get(3) == 3
assert await cache.get(4) == 4
print(" ✓ O(1) LFU eviction order verified")
async def test_ttl_eviction():
"""Verifies Lazy vs Background Async Sweep eviction."""
cache = LFUCache(10, evict_interval=0.1)
await cache.start_evictor()
# Lazy eviction on access
await cache.put('a', 1, ttl_seconds=0.2)
assert await cache.get('a') == 1
await asyncio.sleep(0.3)
assert await cache.get('a') is None, "Lazy eviction failed"
# Background async sweep
await cache.put('b', 2, ttl_seconds=0.1)
await asyncio.sleep(0.2) # Wait for background loop
assert await cache.get('b') is None, "Background sweep failed"
await cache.stop_evictor()
print(" ✓ Dual-layer TTL eviction (Lazy + Background) verified")
async def test_transactions():
"""Verifies Transaction commit visibility vs rollback state restoration."""
cache = LFUCache(5)
await cache.put('x', 10)
# Test 1: Isolation & Read-Your-Own-Writes
tx = await cache.begin_transaction()
await tx.put('x', 20)
assert await tx.get('x') == 20, "Transaction failed Read-Your-Own-Writes"
assert await cache.get('x') == 10, "Global cache leaked uncommitted write"
await tx.commit()
assert await cache.get('x') == 20, "Commit failed to apply changes"
# Test 2: Rollback restores state
tx2 = await cache.begin_transaction()
await tx2.put('y', 30)
await tx2.rollback()
assert await cache.get('y') is None, "Rollback failed to discard changes"
print(" ✓ Transaction commit/rollback isolation verified")
async def test_stress():
"""Stress test with 50 concurrent async tasks reading/writing simultaneously."""
cache = LFUCache(100)
await cache.start_evictor()
tasks = []
for i in range(50):
async def worker(idx):
tx = await cache.begin_transaction()
await tx.put(f'key_{idx}', idx)
await asyncio.sleep(0.01)
val = await tx.get(f'key_{idx}')
assert val == idx, f"Transaction read mismatch for key_{idx}"
await tx.commit()
# Verify global visibility post-commit
assert await cache.get(f'key_{idx}') == idx, f"Global read mismatch for key_{idx}"
tasks.append(asyncio.create_task(worker(i)))
await asyncio.gather(*tasks)
await cache.stop_evictor()
print(" ✓ Stress test (50 concurrent tasks) passed without race conditions")
if __name__ == '__main__':
asyncio.run(main())