| From 58f10b380d63b061b71ad0b3e8462e9ef7f1d49a Mon Sep 17 00:00:00 2001 |
| From: Nir Soffer <nsoffer@redhat.com> |
| Date: Fri, 5 Nov 2021 22:16:26 +0200 |
| Subject: [PATCH] common/urils/vector.c: Optimize vector append |
| |
| 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. |
| |
| 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. |
| |
| Ported from libnbd commit 985dfa72ae2e41901f0af21e7205ef85428cd4bd. |
| |
| (cherry picked from commit 12356fa97a840de19bb61e0abedd6e7c7e578e5a) |
| |
| 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 |
| |
| |
| @@ -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); |
| if (newptr == NULL) |
| return -1; |
| v->ptr = newptr; |
| - v->alloc += n; |
| + v->alloc = newalloc; |
| return 0; |
| } |
| -- |
| 2.31.1 |
| |