feat(CCBV): prevent resize from shrinking underlying array

also add `BV.resize_minimize_memory` to force shrinking. This shouldn't
be the default because it can allocate a lot in case of repeated
shrinkings.
This commit is contained in:
Simon Cruanes 2022-01-02 21:57:53 -05:00
parent 92463d33c5
commit 3d57a5c86e
No known key found for this signature in database
GPG key ID: 4AC01D0849AA62B6
2 changed files with 42 additions and 20 deletions

View file

@ -165,20 +165,28 @@ let cardinal bv =
*) *)
let really_resize_ bv ~desired ~current size = let really_resize_ bv ~desired ~current size =
let b = Bytes.make desired zero in bv.size <- size;
Bytes.blit bv.b 0 b 0 current; if desired <> current then (
bv.b <- b; let b = Bytes.make desired zero in
bv.size <- size Bytes.blit bv.b 0 b 0 current;
bv.b <- b;
)
let[@inline never] grow_real_ bv size =
(* beyond capacity *)
let desired = bytes_length_of_size size in
let current = Bytes.length bv.b in
assert (desired > current);
really_resize_ bv ~desired ~current size
let grow_ bv size = let grow_ bv size =
if size <= capacity bv (* within capacity *) if size <= capacity bv then (
then bv.size <- size (* within capacity *)
else ( bv.size <- size
(* beyond capacity *) ) else (
let desired = bytes_length_of_size size in (* resize. This is a separate function so it's easier to
let current = Bytes.length bv.b in inline the happy path. *)
assert (desired > current); grow_real_ bv size
really_resize_ bv ~desired ~current size
) )
let shrink_ bv size = let shrink_ bv size =
@ -188,11 +196,19 @@ let shrink_ bv size =
let resize bv size = let resize bv size =
if size < 0 then invalid_arg "resize: negative size"; if size < 0 then invalid_arg "resize: negative size";
if size < bv.size (* shrink *) if size < bv.size then (
then shrink_ bv size bv.size <- size;
else if size = bv.size ) else if size > bv.size then (
then () grow_ bv size
else grow_ bv size )
let resize_minimize_memory bv size =
if size < 0 then invalid_arg "resize: negative size";
if size < bv.size then (
shrink_ bv size
) else if size > bv.size then (
grow_ bv size
)
(*$R (*$R
let bv1 = CCBV.create ~size:87 true in let bv1 = CCBV.create ~size:87 true in

View file

@ -39,10 +39,16 @@ val capacity : t -> int
@since 1.2 *) @since 1.2 *)
val resize : t -> int -> unit val resize : t -> int -> unit
(** Resize the BV so that it has the specified length. This can grow or shrink (** Resize the BV so that it has the specified length. This can grow
the underlying bitvector. the underlying array, but it will not shrink it, to minimize
memory traffic.
@raise Invalid_argument on negative sizes. *)
@raise Invalid_arg on negative sizes. *) val resize_minimize_memory : t -> int -> unit
(** Same as {!resize}, but this can also shrink the underlying
array if this reduces the size.
@raise Invalid_argument on negative sizes.
@since NEXT_RELEASE *)
val is_empty : t -> bool val is_empty : t -> bool
(** Are there any true bits? *) (** Are there any true bits? *)