;; A Map holding closures and a Map holding dyn values, both kept alive by the ;; collector across enough allocation that it runs many times. A Map's block is ;; walked like a Vec's: the full slots' values are marked through the value ;; type's descriptor. A lost value is a use of freed memory here, not a wrong ;; number. (defn adder [n i32] (Fn [i32] i32) (fn [x] (+ x n))) ;; Garbage, and plenty of it: every pass boxes and drops a vector of four. (defn churn [n i32] () (dotimes [i n] (let [junk (vec-new dyn)] (push junk i) (push junk "row") (push junk 2.5) (push junk true)))) (defn main [] i32 (let [ops (map-new str (Fn [i32] i32)) many (map-new i32 (Fn [i32] i32)) rows (map-new i32 dyn)] (put ops "one" (adder 1)) (put ops "ten" (adder 10)) (put ops "hundred" (adder 100)) ;; Each value a dyn vector the collector allocated, reachable from ;; nothing but the map. (dotimes [i 64] (let [row (vec-new dyn)] (push row i) (push row "row") (put rows i row))) (churn 40000) ;; Grown after the churn, so a rebuilt block is walked too. (dotimes [i 64] (put many i (adder i))) (churn 40000) (let [total 0] (dotimes [i 64] (set total (+ total (match (get many i) (Some f) (f 0) None 0)))) (println total)) (dotimes [i 3] (let [name (at ["one" "ten" "hundred"] i)] (println (match (get ops name) (Some f) (f 1) None -1)))) (let [cur (i64 0) k 0 v (the dyn nil) sum 0 n 0] (while (map-next rows (addr cur) (addr k) (addr v)) (set sum (+ sum (i32 (at v 0)))) (set n (+ n 1))) (println n) (println sum)) (free ops) (free many) (free rows)) 0)