;;; bench-gc-arena.lsp — arena (meta-GC fast path) vs naive sweep on
;;; the same transient-allocation workload. Runs inside the GC build
;;; only, since with-arena and arena-stats are GC-build primitives.
;;;
;;; Phase A runs the workload WITHOUT wrapping it — every iteration
;;; triggers a naive mark-sweep when the heap fills.
;;;
;;; Phase B runs the same body inside (with-arena thunk) — each
;;; arena exit attempts an O(1) bulk reset; if the verifier sees no
;;; escape, the body's allocations never hit the mark phase.

(define K 200)
(define N 2000)

(define (build-list k acc)
  (if (= k 0) acc (build-list (- k 1) (cons k acc))))

(define (sum-list lst acc)
  (if (null? lst) acc (sum-list (cdr lst) (+ acc (car lst)))))

;;; ── Phase A: naive sweep only ──
(define total-a 0)
(define i 0)
(define (step-a)
  (if (>= i N) total-a
      (begin
        (set! total-a (+ total-a (sum-list (build-list K '()) 0)))
        (set! i (+ i 1))
        (step-a))))

(display "=== Phase A: naive sweep (no arena) ===") (newline)
(define t0 (current-time-ms))
(display "result=") (display (step-a)) (newline)
(display "time_ms=") (display (- (current-time-ms) t0)) (newline)
(display "gc-stats=") (display (gc-stats)) (newline)
(display "arena-stats=") (display (arena-stats)) (newline)

;;; ── Phase B: each iteration wrapped in an arena ──
(define total-b 0)
(define j 0)
(define (iter-body) (sum-list (build-list K '()) 0))
(define (step-b)
  (if (>= j N) total-b
      (begin
        (set! total-b (+ total-b (with-arena iter-body)))
        (set! j (+ j 1))
        (step-b))))

(display "") (newline)
(display "=== Phase B: arena-wrapped (meta-GC fast path) ===") (newline)
(set! t0 (current-time-ms))
(display "result=") (display (step-b)) (newline)
(display "time_ms=") (display (- (current-time-ms) t0)) (newline)
(display "gc-stats=") (display (gc-stats)) (newline)
(display "arena-stats=") (display (arena-stats)) (newline)
