From bbdcd93417d6a64801cd49da9ba7e651fd08dabf Mon Sep 17 00:00:00 2001 From: Fardale Date: Sat, 14 Dec 2019 17:36:25 +0100 Subject: [PATCH] wip: improved gc behavior for ccvector --- src/core/CCVector.ml | 51 +++++++++++++++++++++---------------------- src/core/CCVector.mli | 12 +++++----- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/src/core/CCVector.ml b/src/core/CCVector.ml index d4932bf5..4289cf73 100644 --- a/src/core/CCVector.ml +++ b/src/core/CCVector.ml @@ -22,6 +22,16 @@ type 'a vector = ('a, rw) t type 'a ro_vector = ('a, ro) t +external as_float_arr : 'a array -> float array = "%identity" +external as_obj_arr : 'a array -> Obj.t array = "%identity" + +let fill_with_junk_ (a:_ array) i len : unit = + if Obj.(tag (repr a) = double_array_tag) then ( + Array.fill (as_float_arr a) i len 0.; + ) else ( + Array.fill (as_obj_arr a) i len (Obj.repr ()); + ) + let freeze v = { size=v.size; vec=v.vec; @@ -37,9 +47,12 @@ let create () = { vec = [| |]; } -let create_with ?(capacity=128) x = { +let create_with ?(capacity=128) x = + let vec = Array.make capacity x in + fill_with_junk_ vec 0 capacity; + { size = 0; - vec = Array.make capacity x; + vec } (*$T @@ -70,16 +83,6 @@ let init n f = { let array_is_empty_ v = Array.length v.vec = 0 -external as_float_arr : 'a array -> float array = "%identity" -external as_obj_arr : 'a array -> Obj.t array = "%identity" - -let fill_with_junk_ (a:_ array) i len : unit = - if Obj.(tag (repr a) = double_array_tag) then ( - Array.fill (as_float_arr a) i len 0.; - ) else ( - Array.fill (as_obj_arr a) i len (Obj.repr ()); - ) - (* assuming the underlying array isn't empty, resize it *) let resize_ v newcapacity = assert (newcapacity >= v.size); @@ -146,7 +149,8 @@ let ensure_assuming_not_empty_ v ~size = let ensure_with ~init v size = if array_is_empty_ v then ( - v.vec <- Array.make size init + v.vec <- Array.make size init; + fill_with_junk_ v.vec 0 size ) else ( ensure_assuming_not_empty_ v ~size ) @@ -249,7 +253,8 @@ let remove v i = if i < v.size - 1 then v.vec.(i) <- v.vec.(v.size - 1); (* remove one element *) - v.size <- v.size - 1 + v.size <- v.size - 1; + fill_with_junk_ v.vec v.size 1 let append_seq a seq = seq (fun x -> push a x) @@ -378,7 +383,8 @@ let pop_exn v = let new_size = v.size - 1 in v.size <- new_size; let x = v.vec.(new_size) in - if new_size > 0 then v.vec.(new_size) <- v.vec.(0); (* free last element *) + (* free last element *) + fill_with_junk_ v.vec new_size 1; x let pop v = @@ -430,10 +436,8 @@ let shrink v n = let old_size = v.size in if n < old_size then ( v.size <- n; - if n > 0 then ( - (* free elements by erasing them *) - Array.fill v.vec n (old_size-n) v.vec.(0); - ) + (* free elements by erasing them *) + fill_with_junk_ v.vec n (old_size-n); ) (*$R @@ -611,9 +615,7 @@ let filter' p v = ) else incr i done; (* free elements *) - if !j > 0 && !j < v.size then ( - Array.fill v.vec !j (v.size - !j) v.vec.(0); - ); + fill_with_junk_ v.vec !j (v.size - !j); v.size <- !j (*$T @@ -756,7 +758,6 @@ let filter_map f v = to_list (filter_map f v) = CCList.filter_map f l) *) -(* TODO: free elements *) let filter_map_in_place f v = let i = ref 0 in (* cur element *) let j = ref 0 in (* cur insertion point *) @@ -772,9 +773,7 @@ let filter_map_in_place f v = incr j done; (* free elements *) - if !j > 0 && !j < v.size then ( - Array.fill v.vec !j (v.size - !j) v.vec.(0); - ); + fill_with_junk_ v.vec !j (v.size - !j); v.size <- !j (*$QR diff --git a/src/core/CCVector.mli b/src/core/CCVector.mli index 7271e2f9..dc0b07b4 100644 --- a/src/core/CCVector.mli +++ b/src/core/CCVector.mli @@ -35,17 +35,15 @@ val create : unit -> ('a, rw) t (** Create a new, empty vector. *) val create_with : ?capacity:int -> 'a -> ('a, rw) t -(** Create a new vector, using the given value as a filler. - @param capacity the size of the underlying array. - {b caution}: the value will likely not be GC'd before the vector is. *) +(** Create a new vector, the value is used to enforce the type the new vector. + @param capacity the size of the underlying array. *) val return : 'a -> ('a, 'mut) t (** Singleton vector. @since 0.14 *) val make : int -> 'a -> ('a, 'mut) t -(** [make n x] makes a vector of size [n], filled with [x]. - The element [x] will possibly live as long as the vector. *) +(** [make n x] makes a vector of size [n], filled with [x]. *) val init : int -> (int -> 'a) -> ('a, 'mut) t (** Init the vector with the given function and size. *) @@ -60,8 +58,8 @@ val clear_and_reset : ('a, rw) t -> unit val ensure_with : init:'a -> ('a, rw) t -> int -> unit (** Hint to the vector that it should have at least the given capacity. - @param init if [capacity v = 0], used as a filler - element for the underlying array (see {!create_with}). + @param init if [capacity v = 0], used to enforce the type of the vector + (see {!create_with}). @since 0.14 *) val ensure : ('a, rw) t -> int -> unit