phm: grow the bucket array past load factor 2 (map-read 4.5x recovery)
The phm had a FIXED 8 buckets, so a 100-entry map was a ~12-entry linear scan per lookup — and phm-get walked the bucket twice (contains? then find). This went mostly unnoticed until the canonical zipmap (batch 2) started returning phms where kvs->map had built structs for scalar keys, regressing the map-read bench ~7x (jolt-s3y). phm-assoc now rehashes into a doubled bucket array when the count passes 2 entries/bucket (done on the fresh copy, so persistence is untouched); phm-get is single-pass with a presence flag (nil values still distinguish from missing); key= tries identity/scalar equality before paying for canonicalization; the bucket count is derived from (length (m :buckets)), not a constant, so any already-marshaled map keeps working. core-contains?'s phm branch goes through phm-contains? instead of poking buckets directly. map-read 48.5 -> 10.9 ms (the residual vs the pre-batch-2 6.7 is the canonicalizing-representation constant); map-build steady; bench TOTAL 4457 vs 4565 on main back-to-back. New unit case crosses the resize boundary at 500 entries: every key found, nil values present, collection keys canonical, dissoc + persistence intact. Gate: jpm exit 0, conformance 326x3.
This commit is contained in:
parent
1d373299a4
commit
24a8522b51
3 changed files with 76 additions and 24 deletions
|
|
@ -72,4 +72,21 @@
|
|||
(assert (= 42 (ct-eval ctx "(get big-map :k42)")) "get k42"))
|
||||
(print " passed")
|
||||
|
||||
(print "6: bucket resize (jolt-s3y)...")
|
||||
(let [ctx (init-cached)]
|
||||
# Crossing the load-factor boundary several times: every key still found,
|
||||
# nil values preserved, collection keys still canonical, dissoc intact.
|
||||
(eval-string ctx "
|
||||
(def m (reduce (fn [m i] (assoc m i (* 10 i))) (hash-map) (range 500)))")
|
||||
(assert (= 500 (ct-eval ctx "(count m)")) "count survives rehash")
|
||||
(assert (= true (ct-eval ctx "(every? (fn [i] (= (* 10 i) (get m i))) (range 500))"))
|
||||
"every key found after rehash")
|
||||
(assert (= true (ct-eval ctx "(let [m2 (assoc m :nilv nil)] (and (contains? m2 :nilv) (nil? (get m2 :nilv :miss))))"))
|
||||
"nil value present after rehash")
|
||||
(assert (= :hit (ct-eval ctx "(get (assoc m [1 2] :hit) [1 2])"))
|
||||
"collection key canonical after rehash")
|
||||
(assert (= 499 (ct-eval ctx "(count (dissoc m 0))")) "dissoc after rehash")
|
||||
(assert (= 500 (ct-eval ctx "(count m)")) "persistence: source unchanged"))
|
||||
(print " passed")
|
||||
|
||||
(print "\nAll PersistentHashMap tests passed!")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue