mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
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:
parent
92463d33c5
commit
3d57a5c86e
2 changed files with 42 additions and 20 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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? *)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue