2010/1/30 Péter Szabó <[email protected]>:
> 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

Reply via email to