[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [Libevent-users] patch to prevent unnecessary ioctl(FIONREAD) calls
2010/1/30 Péter Szabó <ptspts@xxxxxxxxx>:
> Hi,
>
> I have a patch which prevents unnecessary ioctl(FIONREAD) system calls
> when reading to an evbuffer. Get the patch from
> http://code.google.com/p/syncless/source/browse/trunk/ptsevent/pts-libevent-prevent-fionread.patch
Hi, Péter!
This code only applies to 1.4.x, from what I can tell. We're trying
to only apply bugfixes to the 1.4.x series (since it's supposed to be
stable); I'm not 100% sure whether this should count as a bugfix or a
feature. Niels, what do you think?
Libevent 2.0.x has a new evbuffer implementation that uses a linked
list of memory chunks rather than a big, wasteful,
inefficient-to-resize circular buffer. Libevent 2.0.x also uses
readv/writev (or WSASend/WSARecv on Windows) to send from multiple
chunks at once, so it can be useful to read.
I think that the equivalent check in 2.0.x would look something like
what I've attached; does it look right to others?
--
Nick
diff --git a/buffer.c b/buffer.c
index e098df7..c8ac6d2 100644
--- a/buffer.c
+++ b/buffer.c
@@ -1619,6 +1619,7 @@ evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch)
struct evbuffer_chain *chain = buf->last;
int n = EVBUFFER_MAX_READ;
int result;
+ size_t free_space = 0;
#ifdef USE_IOVEC_IMPL
int nvecs;
@@ -1636,6 +1637,21 @@ evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch)
goto done;
}
+ /* Figure out how much space we could get at without doing any
+ * memory allocation or reallocation operations at all. If we
+ * were asked to read no more than this amount, then we don't
+ * need to check how many bytes are available for reading.
+ */
+ if (chain) {
+ free_space = CHAIN_SPACE_LEN(chain);
+#ifdef USE_IOVEC_IMPL
+ if (buf->last->off == 0 && buf->previous_to_last)
+ free_space += CHAIN_SPACE_LEN(buf->previous_to_last);
+#endif
+ }
+
+ if (howmuch < 0 || howmuch > free_space ||
+ howmuch > EVBUFFER_MAX_READ) {
#if defined(FIONREAD)
#ifdef WIN32
if (ioctlsocket(fd, FIONREAD, &lng) == -1 || (n=lng) <= 0) {
@@ -1659,6 +1675,7 @@ evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch)
#endif
if (howmuch < 0 || howmuch > n)
howmuch = n;
+ }
#ifdef USE_IOVEC_IMPL
/* Since we can use iovecs, we're willing to use the last