[Libguestfs] [PATCH nbdkit 2/4] common/urils/vector.c: Optimize vector append
Eric Blake
eblake at redhat.com
Mon Nov 8 19:31:28 UTC 2021
On Sat, Nov 06, 2021 at 01:22:50AM +0200, Nir Soffer wrote:
> Minimize reallocs by growing the backing array by factor of 1.5.
s/urils/utils/ in the subject.
>
> Testing show that now append() is fast without calling reserve()
> upfront, simplifying code using vector.
>
> NBDKIT_BENCH=1 ./test-vector
> bench_reserve: 1000000 appends in 0.004496 s
> bench_append: 1000000 appends in 0.004180 s
>
> This can make a difference in code appending millions of items.
Yes, this is a well-known technique needed to turn what is otherwise a
quadratic O(n^2) growth loop into a much nicer amortized O(n) growth
pattern.
>
> Ported from libnbd:
> https://listman.redhat.com/archives/libguestfs/2021-October/msg00306.html
> ---
> common/utils/vector.c | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/common/utils/vector.c b/common/utils/vector.c
> index 00cd2546..7df17e1b 100644
> --- a/common/utils/vector.c
> +++ b/common/utils/vector.c
> @@ -41,11 +41,21 @@ int
> generic_vector_reserve (struct generic_vector *v, size_t n, size_t itemsize)
> {
> void *newptr;
> + size_t reqalloc, newalloc;
>
> - newptr = realloc (v->ptr, (n + v->alloc) * itemsize);
> + reqalloc = v->alloc + n;
> + if (reqalloc < v->alloc)
> + return -1; /* overflow */
> +
> + newalloc = (v->alloc * 3 + 1) / 2;
> +
> + if (newalloc < reqalloc)
> + newalloc = reqalloc;
> +
> + newptr = realloc (v->ptr, newalloc * itemsize);
Same potential for overflow as in the libnbd patches. Whatever we fix
there, we'll have to port here as well.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
More information about the Libguestfs
mailing list