httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Marc Slemko <ma...@znep.com>
Subject non-buffered CGIs suck
Date Fri, 06 Mar 1998 02:33:23 GMT
...from a network perspective.

Try running this:

#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

#define HEADERS "Content-type: text/plain\n\n"
int main () {
        char *s = "this is a line that is being sent\n ";
        int i;
        write(STDOUT_FILENO, HEADERS, strlen(HEADERS));
        for (i = 0; i < 200; i++) {
                write(STDOUT_FILENO, s, strlen(s));
                usleep(1);

        }
}

And you will see many small packets, it will take twice as long to
transfer as buffered CGI did, etc.  It is not very nice to the network.
While many CGIs will have their own buffering (eg. stdio), I'm still not
comfortable.

How about something like the below?  Note that this isn't complete; there
really should be a limit on the total length of time we will do this for
before we flush.  eg. a client writing a byte every 50 ms won't get
flushed in this case.  This is one of those (few) times I wish the world
were a Linux, since it would be easy then. 

For everything else, I really think that loosing this bit of "realtime" is
worthwhile and has minimal impact.  If we didn't disable Nagle, we
wouldn't have to worry about it, however currently we do disable Nagle so
we have to fake our own without being able to do it right.

Index: http_protocol.c
===================================================================
RCS file: /export/home/cvs//apache-1.3/src/main/http_protocol.c,v
retrieving revision 1.194
diff -u -r1.194 http_protocol.c
--- http_protocol.c	1998/03/04 02:28:16	1.194
+++ http_protocol.c	1998/03/06 02:28:47
@@ -1658,11 +1658,27 @@
             len = IOBUFSIZE;
 
         do {
+	    struct timeval tv;
+
             n = bread(fb, buf, len);
             if (n >= 0 || r->connection->aborted)
                 break;
             if (n < 0 && errno != EAGAIN)
                 break;
+
+	    /*
+	     * we really don't want to be shoving lots of small data out
+	     * to the network, so hang around for 100ms to see if we can
+	     * grab anything else.
+	     */
+	    tv.tv_sec = 0;
+	    tv.tv_usec = 100000;
+	    FD_SET(fd, &fds);
+	    if (ap_select(fd + 1, &fds, NULL, &fds, &tv) > 0) {
+		/* something more to read, lets give it a shot */
+		continue;
+	    }
+
             /* we need to block, so flush the output first */
             bflush(r->connection->client);
             if (r->connection->aborted)


Mime
View raw message