59 lines
1.8 KiB
Plaintext
59 lines
1.8 KiB
Plaintext
;; 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)
|