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 =
bv.size <- size;
if desired <> current then (
let b = Bytes.make desired zero in let b = Bytes.make desired zero in
Bytes.blit bv.b 0 b 0 current; Bytes.blit bv.b 0 b 0 current;
bv.b <- b; bv.b <- b;
bv.size <- size )
let grow_ bv size = let[@inline never] grow_real_ bv size =
if size <= capacity bv (* within capacity *)
then bv.size <- size
else (
(* beyond capacity *) (* beyond capacity *)
let desired = bytes_length_of_size size in let desired = bytes_length_of_size size in
let current = Bytes.length bv.b in let current = Bytes.length bv.b in
assert (desired > current); assert (desired > current);
really_resize_ bv ~desired ~current size really_resize_ bv ~desired ~current size
let grow_ bv 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 = 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? *)