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 b = Bytes.make desired zero in
Bytes.blit bv.b 0 b 0 current;
bv.b <- b;
bv.size <- size
bv.size <- size;
if desired <> current then (
let b = Bytes.make desired zero in
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 =
if size <= capacity bv (* within capacity *)
then bv.size <- size
else (
(* 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
if size <= capacity bv then (
(* within capacity *)
bv.size <- size
) else (
(* resize. This is a separate function so it's easier to
inline the happy path. *)
grow_real_ bv size
)
let shrink_ bv size =
@ -188,11 +196,19 @@ let shrink_ bv size =
let resize bv size =
if size < 0 then invalid_arg "resize: negative size";
if size < bv.size (* shrink *)
then shrink_ bv size
else if size = bv.size
then ()
else grow_ bv size
if size < bv.size then (
bv.size <- size;
) else if size > bv.size then (
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
let bv1 = CCBV.create ~size:87 true in

View file

@ -39,10 +39,16 @@ val capacity : t -> int
@since 1.2 *)
val resize : t -> int -> unit
(** Resize the BV so that it has the specified length. This can grow or shrink
the underlying bitvector.
(** Resize the BV so that it has the specified length. This can grow
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
(** Are there any true bits? *)