|
From: <gne...@us...> - 2008-12-27 00:36:46
|
Update of /cvsroot/aolserver/aolserver/nsd In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv24700/nsd Modified Files: pools.c nsd.h queue.c Log Message: New configure parameter "spread" for ns_pools: Background: Requests are distributed to idle threads via CondSignal, which delivers subsequent signals to idle threads in a circular manner (i.e. t1, t2, .. tn, then t1 again) determined by the scheduling policy of the operating system. This round robin behavior has the disadvantage that multiple threads terminate about at the same time, based on the maxconnections (or maxconns) value. The idle timeout will never be used on a sufficiently busy server. The mass termination of threads is performance-wise bad, especially when many connections threads are configured, since it is likely that about the same amount of threads will be recreated. The "spread" parameter introduces a random factor into threadtimeout and maxconnections to avoid these termination cycles. It adds +/- the specified percentage to maxconnections and threadtimeout (e.g. a spread of 20 means a random value between 0.80 to 1.20 of the specified value of maxconnections and threadtimeout for every connection thread). Index: pools.c =================================================================== RCS file: /cvsroot/aolserver/aolserver/nsd/pools.c,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** pools.c 5 Dec 2008 08:51:43 -0000 1.13 --- pools.c 27 Dec 2008 00:36:38 -0000 1.14 *************** *** 120,127 **** } opt; static CONST char *cfgs[] = { ! "-maxthreads", "-minthreads", "-maxconns", "-timeout", NULL }; enum { ! PCMaxThreadsIdx, PCMinThreadsIdx, PCMaxConnsIdx, PCTimeoutIdx } cfg; --- 120,127 ---- } opt; static CONST char *cfgs[] = { ! "-maxthreads", "-minthreads", "-maxconns", "-timeout", "-spread", NULL }; enum { ! PCMaxThreadsIdx, PCMinThreadsIdx, PCMaxConnsIdx, PCTimeoutIdx, PCSpreadIdx } cfg; *************** *** 183,186 **** --- 183,190 ---- poolPtr->threads.maxconns = val; break; + + case PCSpreadIdx: + poolPtr->threads.spread = val; + break; } } *************** *** 198,201 **** --- 202,213 ---- return TCL_ERROR; } + if (poolPtr->threads.maxconns < 1) { + Tcl_SetResult(interp, "maxconns cannot be less than 1", TCL_STATIC); + return TCL_ERROR; + } + if (poolPtr->threads.spread < 0 || poolPtr->threads.spread > 100 ) { + Tcl_SetResult(interp, "spread must be between 0 and 100", TCL_STATIC); + return TCL_ERROR; + } if (PoolResult(interp, poolPtr) != TCL_OK) { return TCL_ERROR; *************** *** 391,394 **** --- 403,407 ---- poolPtr->threads.timeout = 120; /* NB: Exit after 2 minutes idle. */ poolPtr->threads.maxconns = 0; /* NB: Never exit thread. */ + poolPtr->threads.spread = 20; /* NB: +-20% random variance on timeout and maxconns. */ } return poolPtr; *************** *** 421,425 **** !AppendPool(interp, "maxconns", poolPtr->threads.maxconns) || !AppendPool(interp, "queued", poolPtr->threads.queued) || ! !AppendPool(interp, "timeout", poolPtr->threads.timeout)) { return TCL_ERROR; } --- 434,440 ---- !AppendPool(interp, "maxconns", poolPtr->threads.maxconns) || !AppendPool(interp, "queued", poolPtr->threads.queued) || ! !AppendPool(interp, "timeout", poolPtr->threads.timeout) || ! !AppendPool(interp, "spread", poolPtr->threads.spread) ! ) { return TCL_ERROR; } Index: nsd.h =================================================================== RCS file: /cvsroot/aolserver/aolserver/nsd/nsd.h,v retrieving revision 1.119 retrieving revision 1.120 diff -C2 -d -r1.119 -r1.120 *** nsd.h 26 Oct 2007 23:14:17 -0000 1.119 --- nsd.h 27 Dec 2008 00:36:38 -0000 1.120 *************** *** 569,572 **** --- 569,573 ---- int timeout; int maxconns; + int spread; unsigned int queued; } threads; Index: queue.c =================================================================== RCS file: /cvsroot/aolserver/aolserver/nsd/queue.c,v retrieving revision 1.45 retrieving revision 1.46 diff -C2 -d -r1.45 -r1.46 *** queue.c 24 Sep 2008 11:25:33 -0000 1.45 --- queue.c 27 Dec 2008 00:36:38 -0000 1.46 *************** *** 371,374 **** --- 371,375 ---- int status, ncons; char *msg; + double spread; /* *************** *** 381,385 **** Ns_MutexUnlock(&poolPtr->lock); Ns_ThreadSetName(name); ! ncons = poolPtr->threads.maxconns; msg = "exceeded max connections per thread"; --- 382,391 ---- Ns_MutexUnlock(&poolPtr->lock); Ns_ThreadSetName(name); ! ! /* spread is a value of 1.0 +- specified percentage, ! i.e. between 0.0 and 2.0 when the configured percentage is 100 */ ! spread = 1.0 + (2 * poolPtr->threads.spread * Ns_DRand() - poolPtr->threads.spread) / 100.0; ! ! ncons = round(poolPtr->threads.maxconns * spread); msg = "exceeded max connections per thread"; *************** *** 404,408 **** } else { Ns_GetTime(&wait); ! Ns_IncrTime(&wait, poolPtr->threads.timeout, 0); timePtr = &wait; } --- 410,414 ---- } else { Ns_GetTime(&wait); ! Ns_IncrTime(&wait, round(poolPtr->threads.timeout * spread), 0); timePtr = &wait; } |