From d072e3a1d26bd20e3145499d936c8c745f40739c Mon Sep 17 00:00:00 2001 From: wessels <> Date: Fri, 2 Oct 1998 04:28:26 +0000 Subject: [PATCH] avoid scanning loops in comm_select(); from Jeff Mogul patches --- src/comm.cc | 4 +- src/comm_select.cc | 117 ++++++++++++++++++++++++++++++++++++++------- src/fd.cc | 4 +- src/protos.h | 5 +- 4 files changed, 109 insertions(+), 21 deletions(-) diff --git a/src/comm.cc b/src/comm.cc index 04020b1fb9..ca9440e433 100644 --- a/src/comm.cc +++ b/src/comm.cc @@ -1,7 +1,7 @@ /* - * $Id: comm.cc,v 1.286 1998/09/14 23:35:24 wessels Exp $ + * $Id: comm.cc,v 1.287 1998/10/01 22:28:26 wessels Exp $ * * DEBUG: section 5 Socket Functions * AUTHOR: Harvest Derived @@ -626,10 +626,12 @@ commSetSelect(int fd, unsigned int type, PF * handler, void *client_data, time_t if (type & COMM_SELECT_READ) { F->read_handler = handler; F->read_data = client_data; + commUpdateReadBits(fd, handler); } if (type & COMM_SELECT_WRITE) { F->write_handler = handler; F->write_data = client_data; + commUpdateWriteBits(fd, handler); } if (timeout) F->timeout = squid_curtime + timeout; diff --git a/src/comm_select.cc b/src/comm_select.cc index 7c4bc14816..6e763c52b9 100644 --- a/src/comm_select.cc +++ b/src/comm_select.cc @@ -1,7 +1,6 @@ - /* - * $Id: comm_select.cc,v 1.12 1998/09/30 04:34:06 wessels Exp $ + * $Id: comm_select.cc,v 1.13 1998/10/01 22:28:27 wessels Exp $ * * DEBUG: section 5 Socket Functions * @@ -57,6 +56,10 @@ static int comm_check_incoming_select_handlers(int nfds, int *fds); #endif static struct timeval zero_tv; +static fd_set global_readfds; +static fd_set global_writefds; +static int nreadfds; +static int nwritefds; /* * Automatic tuning for incoming requests: @@ -523,9 +526,13 @@ comm_select(int msec) int fd; int i; int maxfd; - int nfds; int num; int callicp = 0, callhttp = 0; + int maxindex; + int k; + int j; + int *fdsp; + int tmask; static time_t last_timeout = 0; struct timeval poll_time; double timeout = current_dtime + (msec / 1000.0); @@ -536,27 +543,33 @@ comm_select(int msec) #if USE_ASYNC_IO aioCheckCallbacks(); #endif - FD_ZERO(&readfds); - FD_ZERO(&writefds); if (commCheckICPIncoming) comm_select_icp_incoming(); if (commCheckHTTPIncoming) comm_select_http_incoming(); callicp = callhttp = 0; - nfds = 0; maxfd = Biggest_FD + 1; + /* copy whole integers. XXX breaks if fd_mask is long */ + xmemcpy(&readfds, &global_readfds, ((maxfd + 31) / 32) * 4); + xmemcpy(&writefds, &global_writefds, ((maxfd + 31) / 32) * 4); + /* remove stalled FDs */ + for (i = 0; i < maxfd; i++) { + if (FD_ISSET(i, &readfds)) + if (commDeferRead(i)) + FD_CLR(i, &readfds); + } +#if DEBUG_FDBITS for (i = 0; i < maxfd; i++) { /* Check each open socket for a handler. */ if (fd_table[i].read_handler && !commDeferRead(i)) { - nfds++; - FD_SET(i, &readfds); + assert(FD_ISSET(i, &readfds)); } if (fd_table[i].write_handler) { - nfds++; - FD_SET(i, &writefds); + assert(FD_ISSET(i, &writefds)); } } - if (nfds == 0) { +#endif + if (nreadfds + nwritefds == 0) { assert(shutting_down); return COMM_SHUTDOWN; } @@ -591,12 +604,26 @@ comm_select(int msec) } if (num == 0) continue; - /* scan each socket but the accept socket. Poll this - * more frequently to minimize losses due to the 5 connect - * limit in SunOS */ - for (fd = 0; fd < maxfd; fd++) { - if (!FD_ISSET(fd, &readfds) && !FD_ISSET(fd, &writefds)) + /* Scan return fd masks for ready descriptors */ +#ifndef howmany +#define howmany(x, y) (((x)+((y)-1))/(y)) +#endif +#ifndef NBBY +#define NBBY 8 +#endif + maxindex = howmany(maxfd, (sizeof(int) * NBBY)); + fdsp = (int *) &readfds; + for (j = 0; j < maxindex; j++) { + if ((tmask = fdsp[j]) == 0) + continue; /* no bits here */ + for (k = 0; k < (sizeof(int) * NBBY); k++) { + if ((tmask & (1 << k)) == 0) continue; + /* Found a set bit */ + fd = (j * (sizeof(int) * NBBY)) + k; +#if DEBUG_FDBITS + assert(FD_ISSET(fd, &readfds)); +#endif if (fdIsIcp(fd)) { callicp = 1; continue; @@ -605,11 +632,11 @@ comm_select(int msec) callhttp = 1; continue; } - if (FD_ISSET(fd, &readfds)) { debug(5, 6) ("comm_select: FD %d ready for reading\n", fd); if (fd_table[fd].read_handler) { hdl = fd_table[fd].read_handler; fd_table[fd].read_handler = NULL; + commUpdateReadBits(fd, NULL); hdl(fd, fd_table[fd].read_data); Counter.select_fds++; } @@ -617,12 +644,36 @@ comm_select(int msec) comm_select_icp_incoming(); if (commCheckHTTPIncoming) comm_select_http_incoming(); + tmask = tmask - (1 << k); /* this bit is done */ + if (tmask == 0) + break; /* and no more bits left */ + } + } + fdsp = (int *) &writefds; + for (j = 0; j < maxindex; j++) { + if ((tmask = fdsp[j]) == 0) + continue; /* no bits here */ + for (k = 0; k < (sizeof(int) * NBBY); k++) { + if ((tmask & (1 << k)) == 0) + continue; + /* Found a set bit */ + fd = (j * (sizeof(int) * NBBY)) + k; +#if DEBUG_FDBITS + assert(FD_ISSET(fd, &writefds)); +#endif + if (fdIsIcp(fd)) { + callicp = 1; + continue; + } + if (fdIsHttp(fd)) { + callhttp = 1; + continue; } - if (FD_ISSET(fd, &writefds)) { debug(5, 5) ("comm_select: FD %d ready for writing\n", fd); if (fd_table[fd].write_handler) { hdl = fd_table[fd].write_handler; fd_table[fd].write_handler = NULL; + commUpdateWriteBits(fd, NULL); hdl(fd, fd_table[fd].write_data); Counter.select_fds++; } @@ -630,6 +681,9 @@ comm_select(int msec) comm_select_icp_incoming(); if (commCheckHTTPIncoming) comm_select_http_incoming(); + tmask = tmask - (1 << k); /* this bit is done */ + if (tmask == 0) + break; /* and no more bits left */ } } if (callicp) @@ -651,6 +705,9 @@ comm_select_init(void) cachemgrRegister("comm_incoming", "comm_incoming() stats", commIncomingStats, 0, 1); + FD_ZERO(&global_readfds); + FD_ZERO(&global_writefds); + nreadfds = nwritefds = 0; } #if !HAVE_POLL @@ -771,3 +828,27 @@ commIncomingStats(StoreEntry * sentry) #endif statHistDump(&f->comm_http_incoming, sentry, statHistIntDumper); } + +void +commUpdateReadBits(int fd, PF *handler) +{ + if (handler && !FD_ISSET(fd, &global_readfds)) { + FD_SET(fd, &global_readfds); + nreadfds++; + } else if (!handler && FD_ISSET(fd, &global_readfds)) { + FD_CLR(fd, &global_readfds); + nreadfds--; + } +} + +void +commUpdateWriteBits(int fd, PF *handler) +{ + if (handler && !FD_ISSET(fd, &global_writefds)) { + FD_SET(fd, &global_writefds); + nwritefds++; + } else if (!handler && FD_ISSET(fd, &global_writefds)) { + FD_CLR(fd, &global_writefds); + nwritefds--; + } +} diff --git a/src/fd.cc b/src/fd.cc index a1088d2ad4..b0e6fb7e72 100644 --- a/src/fd.cc +++ b/src/fd.cc @@ -1,6 +1,6 @@ /* - * $Id: fd.cc,v 1.27 1998/09/09 20:05:49 wessels Exp $ + * $Id: fd.cc,v 1.28 1998/10/01 22:28:28 wessels Exp $ * * DEBUG: section 51 Filedescriptor Functions * AUTHOR: Duane Wessels @@ -79,6 +79,8 @@ fd_close(int fd) Number_FD--; if (F->type == FD_FILE) open_disk_fd--; + commUpdateReadBits(fd, NULL); + commUpdateWriteBits(fd, NULL); memset(F, '\0', sizeof(fde)); F->timeout = 0; } diff --git a/src/protos.h b/src/protos.h index 76d6401122..ac9889ca46 100644 --- a/src/protos.h +++ b/src/protos.h @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.274 1998/09/30 04:34:08 wessels Exp $ + * $Id: protos.h,v 1.275 1998/10/01 22:28:29 wessels Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -153,6 +153,7 @@ extern void commSetDefer(int fd, DEFER * func, void *); extern int ignoreErrno(int); extern void commCloseAllSockets(void); + /* * comm_select.c */ @@ -162,6 +163,8 @@ extern int comm_poll(int); #else extern int comm_select(int); #endif +extern void commUpdateReadBits(int, PF *); +extern void commUpdateWriteBits(int, PF *); extern void packerToStoreInit(Packer * p, StoreEntry * e); extern void packerToMemInit(Packer * p, MemBuf * mb); -- 2.47.3