[Libguestfs] [PATCH libnbd v2 3/8] common/utils/vector.c: Optimize vector append

Eric Blake
Mon, 08 Nov 2021 19:14:21 -0000

On Sun, Oct 31, 2021 at 05:38:52PM +0200, Nir Soffer
wrote:
> Minimize reallocs by growing the backing array by factor of 1.5.
>
> Testing show that now append() is fast without calling reserve()
> upfront, simplifying code using vector.
>
> $ ./test-vector | grep bench
> bench_reserve: 1000000 appends in 0.003997 s
> bench_append: 1000000 appends in 0.003869 s
>
> In practice, this can make "nbdinfo --map" 10 milliseconds faster
when
> running with image that have 500,000 extents.
>
> Signed-off-by: Nir Soffer <nsoffer at redhat.com>
> ---
>  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 00cd254..7df17e1 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 */

The value of errno is indeterminate here,...

> +
> +  newalloc = (v->alloc * 3 + 1) / 2;

On a 32-bit machine, are we at risk of v->alloc*3 overflowing size_t?
If so, should that be another place where we do an early return -1?

> +
> +  if (newalloc < reqalloc)
> +    newalloc = reqalloc;
> +
> +  newptr = realloc (v->ptr, newalloc * itemsize);
>    if (newptr == NULL)
>      return -1;

but ENOMEM here.  We probably want to guarantee it is ENOMEM on all
error paths, rather than having to audit whether callers care.

>    v->ptr = newptr;
> -  v->alloc += n;
> +  v->alloc = newalloc;
>    return 0;
>  }
> --
> 2.31.1
>

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org