Skip to content

Commit

Permalink
Maximum evbuffer read configuration
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
azat committed Mar 16, 2019
1 parent 6995b9a commit 8c2001e
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 12 deletions.
41 changes: 29 additions & 12 deletions buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@
(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);
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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)
{
Expand All @@ -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;
}

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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;

Expand Down
2 changes: 2 additions & 0 deletions evbuffer-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
24 changes: 24 additions & 0 deletions include/event2/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 8c2001e

Please sign in to comment.