mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
Maximum evbuffer read configuration
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.
This commit is contained in:
parent
6995b9a864
commit
8c2001e92a
41
buffer.c
41
buffer.c
@ -140,6 +140,8 @@
|
|||||||
(ptr)->internal_.pos_in_chain = 0; \
|
(ptr)->internal_.pos_in_chain = 0; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define EVBUFFER_MAX_READ_DEFAULT 4096
|
||||||
|
|
||||||
static void evbuffer_chain_align(struct evbuffer_chain *chain);
|
static void evbuffer_chain_align(struct evbuffer_chain *chain);
|
||||||
static int evbuffer_chain_should_realign(struct evbuffer_chain *chain,
|
static int evbuffer_chain_should_realign(struct evbuffer_chain *chain,
|
||||||
size_t datalen);
|
size_t datalen);
|
||||||
@ -370,6 +372,7 @@ evbuffer_new(void)
|
|||||||
LIST_INIT(&buffer->callbacks);
|
LIST_INIT(&buffer->callbacks);
|
||||||
buffer->refcnt = 1;
|
buffer->refcnt = 1;
|
||||||
buffer->last_with_datap = &buffer->first;
|
buffer->last_with_datap = &buffer->first;
|
||||||
|
buffer->max_read = EVBUFFER_MAX_READ_DEFAULT;
|
||||||
|
|
||||||
return (buffer);
|
return (buffer);
|
||||||
}
|
}
|
||||||
@ -591,6 +594,26 @@ evbuffer_free(struct evbuffer *buffer)
|
|||||||
evbuffer_decref_and_unlock_(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
|
void
|
||||||
evbuffer_lock(struct evbuffer *buf)
|
evbuffer_lock(struct evbuffer *buf)
|
||||||
{
|
{
|
||||||
@ -607,13 +630,9 @@ size_t
|
|||||||
evbuffer_get_length(const struct evbuffer *buffer)
|
evbuffer_get_length(const struct evbuffer *buffer)
|
||||||
{
|
{
|
||||||
size_t result;
|
size_t result;
|
||||||
|
|
||||||
EVBUFFER_LOCK(buffer);
|
EVBUFFER_LOCK(buffer);
|
||||||
|
result = buffer->total_len;
|
||||||
result = (buffer->total_len);
|
|
||||||
|
|
||||||
EVBUFFER_UNLOCK(buffer);
|
EVBUFFER_UNLOCK(buffer);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2204,8 +2223,6 @@ evbuffer_expand(struct evbuffer *buf, size_t datlen)
|
|||||||
#endif
|
#endif
|
||||||
#define NUM_READ_IOVEC 4
|
#define NUM_READ_IOVEC 4
|
||||||
|
|
||||||
#define EVBUFFER_MAX_READ 4096
|
|
||||||
|
|
||||||
/** Helper function to figure out which space to use for reading data into
|
/** Helper function to figure out which space to use for reading data into
|
||||||
an evbuffer. Internal use only.
|
an evbuffer. Internal use only.
|
||||||
|
|
||||||
@ -2261,18 +2278,18 @@ static int
|
|||||||
get_n_bytes_readable_on_socket(evutil_socket_t fd)
|
get_n_bytes_readable_on_socket(evutil_socket_t fd)
|
||||||
{
|
{
|
||||||
#if defined(FIONREAD) && defined(_WIN32)
|
#if defined(FIONREAD) && defined(_WIN32)
|
||||||
unsigned long lng = EVBUFFER_MAX_READ;
|
unsigned long lng = EVBUFFER_MAX_READ_DEFAULT;
|
||||||
if (ioctlsocket(fd, FIONREAD, &lng) < 0)
|
if (ioctlsocket(fd, FIONREAD, &lng) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
/* Can overflow, but mostly harmlessly. XXXX */
|
/* Can overflow, but mostly harmlessly. XXXX */
|
||||||
return (int)lng;
|
return (int)lng;
|
||||||
#elif defined(FIONREAD)
|
#elif defined(FIONREAD)
|
||||||
int n = EVBUFFER_MAX_READ;
|
int n = EVBUFFER_MAX_READ_DEFAULT;
|
||||||
if (ioctl(fd, FIONREAD, &n) < 0)
|
if (ioctl(fd, FIONREAD, &n) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
return n;
|
return n;
|
||||||
#else
|
#else
|
||||||
return EVBUFFER_MAX_READ;
|
return EVBUFFER_MAX_READ_DEFAULT;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2300,8 +2317,8 @@ evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
n = get_n_bytes_readable_on_socket(fd);
|
n = get_n_bytes_readable_on_socket(fd);
|
||||||
if (n <= 0 || n > EVBUFFER_MAX_READ)
|
if (n <= 0 || n > (int)buf->max_read)
|
||||||
n = EVBUFFER_MAX_READ;
|
n = (int)buf->max_read;
|
||||||
if (howmuch < 0 || howmuch > n)
|
if (howmuch < 0 || howmuch > n)
|
||||||
howmuch = n;
|
howmuch = n;
|
||||||
|
|
||||||
|
@ -100,6 +100,8 @@ struct evbuffer {
|
|||||||
|
|
||||||
/** Total amount of bytes stored in all chains.*/
|
/** Total amount of bytes stored in all chains.*/
|
||||||
size_t total_len;
|
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
|
/** Number of bytes we have added to the buffer since we last tried to
|
||||||
* invoke callbacks. */
|
* invoke callbacks. */
|
||||||
|
@ -158,6 +158,30 @@ struct evbuffer *evbuffer_new(void);
|
|||||||
EVENT2_EXPORT_SYMBOL
|
EVENT2_EXPORT_SYMBOL
|
||||||
void evbuffer_free(struct evbuffer *buf);
|
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
|
Enable locking on an evbuffer so that it can safely be used by multiple
|
||||||
threads at the same time.
|
threads at the same time.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user