Skip to content

Commit 8c2001e

Browse files
committed
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.
1 parent 6995b9a commit 8c2001e

File tree

3 files changed

+55
-12
lines changed

3 files changed

+55
-12
lines changed

buffer.c

+29-12
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@
140140
(ptr)->internal_.pos_in_chain = 0; \
141141
} while (0)
142142

143+
#define EVBUFFER_MAX_READ_DEFAULT 4096
144+
143145
static void evbuffer_chain_align(struct evbuffer_chain *chain);
144146
static int evbuffer_chain_should_realign(struct evbuffer_chain *chain,
145147
size_t datalen);
@@ -370,6 +372,7 @@ evbuffer_new(void)
370372
LIST_INIT(&buffer->callbacks);
371373
buffer->refcnt = 1;
372374
buffer->last_with_datap = &buffer->first;
375+
buffer->max_read = EVBUFFER_MAX_READ_DEFAULT;
373376

374377
return (buffer);
375378
}
@@ -591,6 +594,26 @@ evbuffer_free(struct evbuffer *buffer)
591594
evbuffer_decref_and_unlock_(buffer);
592595
}
593596

597+
int evbuffer_set_max_read(struct evbuffer *buf, size_t max)
598+
{
599+
if (max > INT_MAX) {
600+
return -1;
601+
}
602+
603+
EVBUFFER_LOCK(buf);
604+
buf->max_read = max;
605+
EVBUFFER_UNLOCK(buf);
606+
return 0;
607+
}
608+
size_t evbuffer_get_max_read(struct evbuffer *buf)
609+
{
610+
size_t result;
611+
EVBUFFER_LOCK(buf);
612+
result = buf->max_read;
613+
EVBUFFER_UNLOCK(buf);
614+
return result;
615+
}
616+
594617
void
595618
evbuffer_lock(struct evbuffer *buf)
596619
{
@@ -607,13 +630,9 @@ size_t
607630
evbuffer_get_length(const struct evbuffer *buffer)
608631
{
609632
size_t result;
610-
611633
EVBUFFER_LOCK(buffer);
612-
613-
result = (buffer->total_len);
614-
634+
result = buffer->total_len;
615635
EVBUFFER_UNLOCK(buffer);
616-
617636
return result;
618637
}
619638

@@ -2204,8 +2223,6 @@ evbuffer_expand(struct evbuffer *buf, size_t datlen)
22042223
#endif
22052224
#define NUM_READ_IOVEC 4
22062225

2207-
#define EVBUFFER_MAX_READ 4096
2208-
22092226
/** Helper function to figure out which space to use for reading data into
22102227
an evbuffer. Internal use only.
22112228
@@ -2261,18 +2278,18 @@ static int
22612278
get_n_bytes_readable_on_socket(evutil_socket_t fd)
22622279
{
22632280
#if defined(FIONREAD) && defined(_WIN32)
2264-
unsigned long lng = EVBUFFER_MAX_READ;
2281+
unsigned long lng = EVBUFFER_MAX_READ_DEFAULT;
22652282
if (ioctlsocket(fd, FIONREAD, &lng) < 0)
22662283
return -1;
22672284
/* Can overflow, but mostly harmlessly. XXXX */
22682285
return (int)lng;
22692286
#elif defined(FIONREAD)
2270-
int n = EVBUFFER_MAX_READ;
2287+
int n = EVBUFFER_MAX_READ_DEFAULT;
22712288
if (ioctl(fd, FIONREAD, &n) < 0)
22722289
return -1;
22732290
return n;
22742291
#else
2275-
return EVBUFFER_MAX_READ;
2292+
return EVBUFFER_MAX_READ_DEFAULT;
22762293
#endif
22772294
}
22782295

@@ -2300,8 +2317,8 @@ evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch)
23002317
}
23012318

23022319
n = get_n_bytes_readable_on_socket(fd);
2303-
if (n <= 0 || n > EVBUFFER_MAX_READ)
2304-
n = EVBUFFER_MAX_READ;
2320+
if (n <= 0 || n > (int)buf->max_read)
2321+
n = (int)buf->max_read;
23052322
if (howmuch < 0 || howmuch > n)
23062323
howmuch = n;
23072324

evbuffer-internal.h

+2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ struct evbuffer {
100100

101101
/** Total amount of bytes stored in all chains.*/
102102
size_t total_len;
103+
/** Maximum bytes per one read */
104+
size_t max_read;
103105

104106
/** Number of bytes we have added to the buffer since we last tried to
105107
* invoke callbacks. */

include/event2/buffer.h

+24
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,30 @@ struct evbuffer *evbuffer_new(void);
158158
EVENT2_EXPORT_SYMBOL
159159
void evbuffer_free(struct evbuffer *buf);
160160

161+
162+
/**
163+
Set maximum read buffer size
164+
165+
Default is 4096 and it works fine most of time, so before increasing the
166+
default check carefully, since this has some negative effects (like memory
167+
fragmentation and unfair resource distribution, i.e. some events will make
168+
less progress than others).
169+
170+
@param buf pointer to the evbuffer
171+
@param max buffer size
172+
@return 0 on success, -1 on failure (if @max > INT_MAX).
173+
*/
174+
EVENT2_EXPORT_SYMBOL
175+
int evbuffer_set_max_read(struct evbuffer *buf, size_t max);
176+
/**
177+
Get maximum read buffer size
178+
179+
@param buf pointer to the evbuffer
180+
@return current maximum buffer read
181+
*/
182+
EVENT2_EXPORT_SYMBOL
183+
size_t evbuffer_get_max_read(struct evbuffer *buf);
184+
161185
/**
162186
Enable locking on an evbuffer so that it can safely be used by multiple
163187
threads at the same time.

0 commit comments

Comments
 (0)