]> granicus.if.org Git - libevent/commitdiff
Maximum evbuffer read configuration
authorAzat Khuzhin <azat@libevent.org>
Sat, 16 Mar 2019 14:09:51 +0000 (17:09 +0300)
committerAzat Khuzhin <azat@libevent.org>
Sat, 16 Mar 2019 14:30:15 +0000 (17:30 +0300)
Before this patch evbuffer always reads 4K at a time, while this is fine
most of time you can find an example when this will decrease throughput.

So add an API to change default limit:
- evbuffer_set_max_read()
- evbuffer_get_max_read()

And a notice that most of time default is sane.

buffer.c
evbuffer-internal.h
include/event2/buffer.h

index 690154bffee69d6ba937161e203bb1bd4b846f60..11b1bdae5ef0a2c6efece64bc778d66544719977 100644 (file)
--- a/buffer.c
+++ b/buffer.c
        (ptr)->internal_.pos_in_chain = 0;      \
 } while (0)
 
+#define EVBUFFER_MAX_READ_DEFAULT      4096
+
 static void evbuffer_chain_align(struct evbuffer_chain *chain);
 static int evbuffer_chain_should_realign(struct evbuffer_chain *chain,
     size_t datalen);
@@ -370,6 +372,7 @@ evbuffer_new(void)
        LIST_INIT(&buffer->callbacks);
        buffer->refcnt = 1;
        buffer->last_with_datap = &buffer->first;
+       buffer->max_read = EVBUFFER_MAX_READ_DEFAULT;
 
        return (buffer);
 }
@@ -591,6 +594,26 @@ evbuffer_free(struct evbuffer *buffer)
        evbuffer_decref_and_unlock_(buffer);
 }
 
+int evbuffer_set_max_read(struct evbuffer *buf, size_t max)
+{
+       if (max > INT_MAX) {
+               return -1;
+       }
+
+       EVBUFFER_LOCK(buf);
+       buf->max_read = max;
+       EVBUFFER_UNLOCK(buf);
+       return 0;
+}
+size_t evbuffer_get_max_read(struct evbuffer *buf)
+{
+       size_t result;
+       EVBUFFER_LOCK(buf);
+       result = buf->max_read;
+       EVBUFFER_UNLOCK(buf);
+       return result;
+}
+
 void
 evbuffer_lock(struct evbuffer *buf)
 {
@@ -607,13 +630,9 @@ size_t
 evbuffer_get_length(const struct evbuffer *buffer)
 {
        size_t result;
-
        EVBUFFER_LOCK(buffer);
-
-       result = (buffer->total_len);
-
+       result = buffer->total_len;
        EVBUFFER_UNLOCK(buffer);
-
        return result;
 }
 
@@ -2204,8 +2223,6 @@ evbuffer_expand(struct evbuffer *buf, size_t datlen)
 #endif
 #define NUM_READ_IOVEC 4
 
-#define EVBUFFER_MAX_READ      4096
-
 /** Helper function to figure out which space to use for reading data into
     an evbuffer.  Internal use only.
 
@@ -2261,18 +2278,18 @@ static int
 get_n_bytes_readable_on_socket(evutil_socket_t fd)
 {
 #if defined(FIONREAD) && defined(_WIN32)
-       unsigned long lng = EVBUFFER_MAX_READ;
+       unsigned long lng = EVBUFFER_MAX_READ_DEFAULT;
        if (ioctlsocket(fd, FIONREAD, &lng) < 0)
                return -1;
        /* Can overflow, but mostly harmlessly. XXXX */
        return (int)lng;
 #elif defined(FIONREAD)
-       int n = EVBUFFER_MAX_READ;
+       int n = EVBUFFER_MAX_READ_DEFAULT;
        if (ioctl(fd, FIONREAD, &n) < 0)
                return -1;
        return n;
 #else
-       return EVBUFFER_MAX_READ;
+       return EVBUFFER_MAX_READ_DEFAULT;
 #endif
 }
 
@@ -2300,8 +2317,8 @@ evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch)
        }
 
        n = get_n_bytes_readable_on_socket(fd);
-       if (n <= 0 || n > EVBUFFER_MAX_READ)
-               n = EVBUFFER_MAX_READ;
+       if (n <= 0 || n > (int)buf->max_read)
+               n = (int)buf->max_read;
        if (howmuch < 0 || howmuch > n)
                howmuch = n;
 
index d09b4f1ddd58af85c946ac4a1bfa178996930a77..b93601b293717a16c9ec91f4644fa521433c33f0 100644 (file)
@@ -100,6 +100,8 @@ struct evbuffer {
 
        /** Total amount of bytes stored in all chains.*/
        size_t total_len;
+       /** Maximum bytes per one read */
+       size_t max_read;
 
        /** Number of bytes we have added to the buffer since we last tried to
         * invoke callbacks. */
index 468588b9f141c200c2ab310afd1e448dd643e70f..56f620aff538447e5be1b12c17de158889b8711b 100644 (file)
@@ -158,6 +158,30 @@ struct evbuffer *evbuffer_new(void);
 EVENT2_EXPORT_SYMBOL
 void evbuffer_free(struct evbuffer *buf);
 
+
+/**
+  Set maximum read buffer size
+
+  Default is 4096 and it works fine most of time, so before increasing the
+  default check carefully, since this has some negative effects (like memory
+  fragmentation and unfair resource distribution, i.e. some events will make
+  less progress than others).
+
+  @param buf pointer to the evbuffer
+  @param max buffer size
+  @return 0 on success, -1 on failure (if @max > INT_MAX).
+ */
+EVENT2_EXPORT_SYMBOL
+int evbuffer_set_max_read(struct evbuffer *buf, size_t max);
+/**
+  Get maximum read buffer size
+
+  @param buf pointer to the evbuffer
+  @return current maximum buffer read
+ */
+EVENT2_EXPORT_SYMBOL
+size_t evbuffer_get_max_read(struct evbuffer *buf);
+
 /**
    Enable locking on an evbuffer so that it can safely be used by multiple
    threads at the same time.