4444
4545# ---- Constants --------------------------------------------------------------
4646
47- WARMUP_RUNS = 3
48- BENCH_RUNS = 20
47+ # Fixed run count for every timed measurement (hit sweep, decomposition,
48+ # and miss). One warmup call precedes these in `samples_ms`.
49+ BENCH_RUNS = 10
4950
5051# Lift diskcache's 1 GB default so only `memoize`'s SQLite blob
5152# ceiling causes a method to fall out of the comparison.
@@ -122,16 +123,6 @@ def median_ms(fn: Callable[[], Any], runs: int,
122123 return float (np .median (samples_ms (fn , runs , settle_s )))
123124
124125
125- def runs_for (size_mb : float ) -> int :
126- """Adaptive run count — fewer iterations at multi-GB sizes."""
127- if size_mb <= 1 : return 30
128- if size_mb <= 10 : return 15
129- if size_mb <= 50 : return 8
130- if size_mb <= 250 : return 4
131- if size_mb <= 1000 : return 3
132- return 2
133-
134-
135126def random_payload (size_mb : float ) -> np .ndarray :
136127 """Random float64 numpy array sized to approximately `size_mb` MB."""
137128 n = max (1 , int (size_mb * 1024 ** 2 / 8 ))
@@ -211,7 +202,7 @@ def _measure_marimo_lazy_load(payload, fallback_ms: float, runs: int) -> float:
211202 return fallback_ms
212203 tmp = tempfile .mkdtemp ()
213204 try :
214- loader = LazyLoader ("bench-lazy" , store = LazyStore (save_path = tmp ))
205+ loader = LazyLoader ("bench-lazy" , store = LazyStore (FileStore ( save_path = tmp ) ))
215206 if not loader .save_cache (_bench_cache (payload )):
216207 return float ("nan" )
217208 loader .flush () # let background writer threads finish before reads
@@ -342,7 +333,7 @@ def _median_save_ms(
342333 return float (np .median (times ))
343334
344335
345- def measure_miss (payload : Any , runs : int = 5 ) -> list [dict ]:
336+ def measure_miss (payload : Any , runs : int = BENCH_RUNS ) -> list [dict ]:
346337 """Decompose cache-miss overhead per method into key + save (ms).
347338
348339 Returns `{method, stage, ms}` rows shaped exactly like
@@ -359,7 +350,7 @@ def save_pickle(d: str) -> None:
359350 assert loader .save_cache (_bench_cache (payload ))
360351
361352 def save_lazy (d : str ) -> None :
362- loader = LazyLoader ("bench" , store = LazyStore (save_path = d ))
353+ loader = LazyLoader ("bench" , store = LazyStore (FileStore ( save_path = d ) ))
363354 assert loader .save_cache (_bench_cache (payload ))
364355 loader .flush () # charge the background writers to the save
365356
@@ -395,7 +386,7 @@ def save_diskcache(d: str) -> None:
395386
396387
397388def sweep_write_overhead (
398- sizes_mb : tuple [float , ...], runs : int = 3 ,
389+ sizes_mb : tuple [float , ...],
399390) -> list [dict ]:
400391 """Total miss overhead (key + save, ms) per (size, method).
401392
@@ -405,7 +396,7 @@ def sweep_write_overhead(
405396 rows : list [dict ] = []
406397 for s in sizes_mb :
407398 payload = random_payload (s )
408- for r in measure_miss (payload , runs = max ( runs , runs_for ( s ) // 4 ) ):
399+ for r in measure_miss (payload ):
409400 rows .append ({"size_mb" : s , "method" : r ["method" ],
410401 "stage" : r ["stage" ], "ms" : r ["ms" ]})
411402 del payload
@@ -510,7 +501,6 @@ def sweep_methods_samples(
510501 setup_methods : Callable [[], Any ],
511502 * ,
512503 settle_s : float = LAZY_SETTLE_S ,
513- min_runs : int = 5 ,
514504) -> list [dict ]:
515505 """End-to-end sweep returning raw samples per (size, method).
516506
@@ -541,7 +531,7 @@ def sweep_methods_samples(
541531 try :
542532 for s in sizes_mb :
543533 payload = random_payload (s )
544- runs = max ( min_runs , runs_for ( s ) // 2 )
534+ runs = BENCH_RUNS
545535 for name , bind in methods .items ():
546536 try :
547537 hit = bind (payload )
@@ -721,11 +711,13 @@ def plot_e2e(
721711 markersize = 4 , lw = 1.2 ,
722712 )
723713 ax .axhline (threshold_ms , ls = "--" , color = "gray" , lw = 0.8 , alpha = 0.6 )
724- # Right-aligned so the legend (upper left) cannot occlude it.
714+ # Sit the label in the clear gap just above the line — centered on the
715+ # geometric-mid payload, right of the upper-left legend and left of where
716+ # the curves cross the threshold on the right, so it never overlaps either.
725717 ax .text (
726- sizes_mb .max (), threshold_ms * 1.15 ,
718+ float ( np . sqrt ( sizes_mb .min () * sizes_mb . max ())) , threshold_ms * 1.25 ,
727719 f"{ threshold_ms :.0f} ms interactive threshold" ,
728- fontsize = 7 , color = "gray" , style = "italic" , ha = "right " ,
720+ fontsize = 7 , color = "gray" , style = "italic" , ha = "center" , va = "bottom " ,
729721 )
730722 ax .set_xlabel ("Payload size (MB)" )
731723 ax .set_ylabel ("Cache-hit latency (ms)" )
0 commit comments