]> granicus.if.org Git - libevent/commitdiff
buffer: do not round up allocation for reference-type chain objects
authorPierce Lopez <pierce.lopez@gmail.com>
Fri, 17 Sep 2021 03:21:26 +0000 (23:21 -0400)
committerPierce Lopez <pierce.lopez@gmail.com>
Fri, 17 Sep 2021 03:21:26 +0000 (23:21 -0400)
Skip rounding up memory allocations for:
  * evbuffer_add_reference()
  * evbuffer_add_buffer_reference()
  * evbuffer_add_file_segment()

These chain objects only store small structs with references to
other things, and these small structs do not themselves grow, so
bumping up the allocation to MIN_BUFFER_SIZE (512 bytes) is wasteful.

buffer.c

index 822d97a5a93cd65733a8761082a8aaa62fc75be2..6c96f05422ace058bf6873db485fe8f85f399484 100644 (file)
--- a/buffer.c
+++ b/buffer.c
@@ -158,17 +158,7 @@ evbuffer_chain_new(size_t size)
        if (size > EVBUFFER_CHAIN_MAX - EVBUFFER_CHAIN_SIZE)
                return (NULL);
 
-       size += EVBUFFER_CHAIN_SIZE;
-
-       /* get the next largest memory that can hold the buffer */
-       if (size < EVBUFFER_CHAIN_MAX / 2) {
-               to_alloc = MIN_BUFFER_SIZE;
-               while (to_alloc < size) {
-                       to_alloc <<= 1;
-               }
-       } else {
-               to_alloc = size;
-       }
+       to_alloc = size + EVBUFFER_CHAIN_SIZE;
 
        /* we get everything in one chunk */
        if ((chain = mm_malloc(to_alloc)) == NULL)
@@ -188,6 +178,29 @@ evbuffer_chain_new(size_t size)
        return (chain);
 }
 
+static struct evbuffer_chain *
+evbuffer_chain_new_membuf(size_t size)
+{
+       size_t to_alloc;
+
+       if (size > EVBUFFER_CHAIN_MAX - EVBUFFER_CHAIN_SIZE)
+               return (NULL);
+
+       size += EVBUFFER_CHAIN_SIZE;
+
+       /* get the next largest memory that can hold the buffer */
+       if (size < EVBUFFER_CHAIN_MAX / 2) {
+               to_alloc = MIN_BUFFER_SIZE;
+               while (to_alloc < size) {
+                       to_alloc <<= 1;
+               }
+       } else {
+               to_alloc = size;
+       }
+
+       return evbuffer_chain_new(to_alloc - EVBUFFER_CHAIN_SIZE);
+}
+
 static inline void
 evbuffer_chain_free(struct evbuffer_chain *chain)
 {
@@ -326,7 +339,7 @@ static inline struct evbuffer_chain *
 evbuffer_chain_insert_new(struct evbuffer *buf, size_t datlen)
 {
        struct evbuffer_chain *chain;
-       if ((chain = evbuffer_chain_new(datlen)) == NULL)
+       if ((chain = evbuffer_chain_new_membuf(datlen)) == NULL)
                return NULL;
        evbuffer_chain_insert(buf, chain);
        return chain;
@@ -849,7 +862,7 @@ PRESERVE_PINNED(struct evbuffer *src, struct evbuffer_chain **first,
                struct evbuffer_chain *tmp;
 
                EVUTIL_ASSERT(pinned == src->last_with_datap);
-               tmp = evbuffer_chain_new(chain->off);
+               tmp = evbuffer_chain_new_membuf(chain->off);
                if (!tmp)
                        return -1;
                memcpy(tmp->buffer, chain->buffer + chain->misalign,
@@ -1418,7 +1431,7 @@ evbuffer_pullup(struct evbuffer *buf, ev_ssize_t size)
                size -= old_off;
                chain = chain->next;
        } else {
-               if ((tmp = evbuffer_chain_new(size)) == NULL) {
+               if ((tmp = evbuffer_chain_new_membuf(size)) == NULL) {
                        event_warn("%s: out of memory", __func__);
                        goto done;
                }
@@ -1766,10 +1779,9 @@ evbuffer_add(struct evbuffer *buf, const void *data_in, size_t datlen)
        /* If there are no chains allocated for this buffer, allocate one
         * big enough to hold all the data. */
        if (chain == NULL) {
-               chain = evbuffer_chain_new(datlen);
+               chain = evbuffer_chain_insert_new(buf, datlen);
                if (!chain)
                        goto done;
-               evbuffer_chain_insert(buf, chain);
        }
 
        if ((chain->flags & EVBUFFER_IMMUTABLE) == 0) {
@@ -1808,7 +1820,7 @@ evbuffer_add(struct evbuffer *buf, const void *data_in, size_t datlen)
                to_alloc <<= 1;
        if (datlen > to_alloc)
                to_alloc = datlen;
-       tmp = evbuffer_chain_new(to_alloc);
+       tmp = evbuffer_chain_new_membuf(to_alloc);
        if (tmp == NULL)
                goto done;
 
@@ -1858,10 +1870,9 @@ evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen)
        chain = buf->first;
 
        if (chain == NULL) {
-               chain = evbuffer_chain_new(datlen);
+               chain = evbuffer_chain_insert_new(buf, datlen);
                if (!chain)
                        goto done;
-               evbuffer_chain_insert(buf, chain);
        }
 
        /* we cannot touch immutable buffers */
@@ -1898,7 +1909,7 @@ evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen)
        }
 
        /* we need to add another chain */
-       if ((tmp = evbuffer_chain_new(datlen)) == NULL)
+       if ((tmp = evbuffer_chain_new_membuf(datlen)) == NULL)
                goto done;
        buf->first = tmp;
        if (buf->last_with_datap == &buf->first && chain->off)
@@ -2027,7 +2038,7 @@ evbuffer_expand_singlechain(struct evbuffer *buf, size_t datlen)
                 * MAX_TO_COPY_IN_EXPAND bytes. */
                /* figure out how much space we need */
                size_t length = chain->off + datlen;
-               struct evbuffer_chain *tmp = evbuffer_chain_new(length);
+               struct evbuffer_chain *tmp = evbuffer_chain_new_membuf(length);
                if (tmp == NULL)
                        goto err;
 
@@ -2073,12 +2084,11 @@ evbuffer_expand_fast_(struct evbuffer *buf, size_t datlen, int n)
        if (chain == NULL || (chain->flags & EVBUFFER_IMMUTABLE)) {
                /* There is no last chunk, or we can't touch the last chunk.
                 * Just add a new chunk. */
-               chain = evbuffer_chain_new(datlen);
+               chain = evbuffer_chain_insert_new(buf, datlen);
                if (chain == NULL)
                        return (-1);
-
-               evbuffer_chain_insert(buf, chain);
-               return (0);
+               else
+                       return (0);
        }
 
        used = 0; /* number of chains we're using space in. */
@@ -2116,7 +2126,7 @@ evbuffer_expand_fast_(struct evbuffer *buf, size_t datlen, int n)
                 * chains; we can add another. */
                EVUTIL_ASSERT(chain == NULL);
 
-               tmp = evbuffer_chain_new(datlen - avail);
+               tmp = evbuffer_chain_new_membuf(datlen - avail);
                if (tmp == NULL)
                        return (-1);
 
@@ -2148,7 +2158,7 @@ evbuffer_expand_fast_(struct evbuffer *buf, size_t datlen, int n)
                        evbuffer_chain_free(chain);
                }
                EVUTIL_ASSERT(datlen >= avail);
-               tmp = evbuffer_chain_new(datlen - avail);
+               tmp = evbuffer_chain_new_membuf(datlen - avail);
                if (tmp == NULL) {
                        if (rmv_all) {
                                ZERO_CHAIN(buf);