Transients: mutable backing instead of copy-on-write
The Chez port had landed transients as copy-on-write — each conj!/assoc!/etc.
rebuilt the whole persistent collection. Semantics were right but a transient
vector was O(n^2) to build (the persistent vector is a flat array, so every
conj! copied it); maps/sets were ~O(n log n) since the HAMT only path-copies.
This restores the Janet host's approach: true mutable backing, snapshot once on
persistent!.
vec : a growable Scheme vector (capacity + fill count); conj!/pop! amortized
O(1), persistent! hands off the buffer (exact fit) or trims once.
map : a Chez hashtable keyed by key-hash/jolt= (value equality, nil-safe);
persistent! folds it into a pmap.
set : a Chez hashtable; persistent! folds into a pset.
cow : fallback for anything else (e.g. a sorted coll) keeps the old
copy-on-write path, preserving jolt's superset.
get/count/contains?/nth see through each representation. Building a 400k vector
went from minutes (quadratic) to ~50ms (linear). assoc! keeps the variadic
dangling-key nil-pad on both vectors and maps. test/chez/transient-test.ss pins
the invariants and the linear-time property; wired in as `make transient`.
This commit is contained in:
parent
6f433a1b3c
commit
fe3fdf6b9c
4 changed files with 210 additions and 44 deletions
|
|
@ -37,7 +37,8 @@
|
|||
;; multimethod; the readable fallback renders it directly).
|
||||
;; forward refs to transients.ss (loaded later) — resolved at call time.
|
||||
((jolt-transient? x)
|
||||
(if (pvec? (jolt-transient-coll x)) "#<transient vector>" "#<transient map>"))
|
||||
(case (jolt-transient-kind x)
|
||||
((vec) "#<transient vector>") ((set) "#<transient set>") (else "#<transient map>")))
|
||||
((pvec? x)
|
||||
(let ((acc '()))
|
||||
(let loop ((i (fx- (pvec-count x) 1)))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue