Closes the three tractable pending buckets (all non-no_dir work):
+ lean4-0004..0007: 4 correctness/race benches (ir_interp DCL, jobreg
IO.Ref race, g_opts thread-local leakage, process envvar hash).
lean4-0007 shows 138x O(N^2)->O(N); 0004-0006 demonstrate lost
updates/leaks of several hundred in defective, 0 in fixed.
+ 0ad-0001..0004: 3 CWE-407 list.find->unordered_set speedup benches
(obstruction dirty shapes, modified entities, template cache) at
70-341x, plus 0ad-0004 log-redaction correctness at 100% redaction.
+ activemq-0001..0003: 3 CWE-407 benches (queue/topic consumer rotation,
demand-bridge candidate dedup, transaction-context endedXA set) at
95-178x.
+ linux-0001..0008: 8 Python complexity-class models for the kernel
patches. Coexist with the existing build-and-bench.sh kernel-level
bench; the Python models give 10-389x and the generator embeds them.
+ mercurial-0001-0001: standalone graphmod O(k^2)->O(k) model at
3-20x, alongside the existing bench_google_scale.py (which imports
the real mercurial graphmod).
Progress: 13 -> 33 full coverage. Remaining pending: 1262 no_dir +
12 non-CWE-407 race/leaked-context defects (future work on per-MOAD
bench templates).
113 lines
3.4 KiB
Python
113 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
# bench-lean4-0006.py
|
|
# LEAN_THREAD_PTR(g_opts) not reset at task boundaries: pooled thread inherits
|
|
# previous task's trace options. Fixed path: reset g_opts to nullptr on task
|
|
# finalize. Correctness metric: observed leakage count (task B sees task A's
|
|
# options).
|
|
|
|
import sys
|
|
import threading
|
|
import queue
|
|
import time
|
|
|
|
|
|
def make_pool(n_threads, task_queue, context_fn):
|
|
"""Minimal thread-pool. context_fn receives (tid, task) and runs under
|
|
whatever thread-local setup context_fn itself establishes."""
|
|
def loop(tid):
|
|
while True:
|
|
task = task_queue.get()
|
|
if task is None:
|
|
task_queue.task_done()
|
|
break
|
|
context_fn(tid, task)
|
|
task_queue.task_done()
|
|
|
|
threads = [threading.Thread(target=loop, args=(i,)) for i in range(n_threads)]
|
|
for t in threads:
|
|
t.start()
|
|
return threads
|
|
|
|
|
|
def bench_defective(n_threads, n_tasks):
|
|
"""g_opts modelled as a thread-local dict; defective path does NOT clear
|
|
g_opts between tasks, so a reused thread keeps the prior task's options.
|
|
Count leakages: task T_new observes g_opts_from T_prev."""
|
|
g_opts = threading.local()
|
|
leakages = [0]
|
|
leak_lock = threading.Lock()
|
|
tq = queue.Queue()
|
|
|
|
def run_task(tid, task):
|
|
prior = getattr(g_opts, 'payload', None)
|
|
if prior is not None and prior != task['tid']:
|
|
with leak_lock:
|
|
leakages[0] += 1
|
|
g_opts.payload = task['tid']
|
|
# simulate work
|
|
_ = sum(range(50))
|
|
# defective: no reset
|
|
|
|
threads = make_pool(n_threads, tq, run_task)
|
|
t0 = time.perf_counter()
|
|
for i in range(n_tasks):
|
|
tq.put({'tid': f't{i}'})
|
|
for _ in threads:
|
|
tq.put(None)
|
|
for t in threads:
|
|
t.join()
|
|
elapsed = time.perf_counter() - t0
|
|
return elapsed, leakages[0]
|
|
|
|
|
|
def bench_fixed(n_threads, n_tasks):
|
|
"""Fixed: task finalizer resets g_opts to None before returning."""
|
|
g_opts = threading.local()
|
|
leakages = [0]
|
|
leak_lock = threading.Lock()
|
|
tq = queue.Queue()
|
|
|
|
def run_task(tid, task):
|
|
prior = getattr(g_opts, 'payload', None)
|
|
if prior is not None and prior != task['tid']:
|
|
with leak_lock:
|
|
leakages[0] += 1
|
|
g_opts.payload = task['tid']
|
|
_ = sum(range(50))
|
|
g_opts.payload = None # task finalizer: reset
|
|
|
|
threads = make_pool(n_threads, tq, run_task)
|
|
t0 = time.perf_counter()
|
|
for i in range(n_tasks):
|
|
tq.put({'tid': f't{i}'})
|
|
for _ in threads:
|
|
tq.put(None)
|
|
for t in threads:
|
|
t.join()
|
|
elapsed = time.perf_counter() - t0
|
|
return elapsed, leakages[0]
|
|
|
|
|
|
TRIALS = 3
|
|
|
|
|
|
def run():
|
|
lines = []
|
|
header = "=== lean4-0006: kernel/trace g_opts thread-local leakage (correctness) ==="
|
|
print(header); lines.append(header)
|
|
for n_threads, n_tasks in [(2, 200), (4, 400), (8, 800)]:
|
|
def_leaks = []
|
|
fix_leaks = []
|
|
for _ in range(TRIALS):
|
|
_, dl = bench_defective(n_threads, n_tasks)
|
|
_, fl = bench_fixed(n_threads, n_tasks)
|
|
def_leaks.append(dl); fix_leaks.append(fl)
|
|
line = (f"threads={n_threads:<2} tasks={n_tasks:<4}: "
|
|
f"defective_leakages(max)={max(def_leaks):>5} "
|
|
f"fixed_leakages(max)={max(fix_leaks):>5}")
|
|
print(line); lines.append(line); sys.stdout.flush()
|
|
return lines
|
|
|
|
|
|
if __name__ == "__main__":
|
|
run()
|