From: Alex Rousskov Date: Mon, 29 Aug 2011 23:14:17 +0000 (-0600) Subject: Use a time-based limit for the disker I/O loop. X-Git-Tag: take08~37 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fdb3059bfb1fbcbbe7d7df6ed5b15f773986b9c5;p=thirdparty%2Fsquid.git Use a time-based limit for the disker I/O loop. Compared to the old counter-based limit, a time-based limit is better because it allows us to quit right after a blocked I/O or quit sooner when I/Os become slower. Polished comments. --- diff --git a/src/DiskIO/IpcIo/IpcIoFile.cc b/src/DiskIO/IpcIo/IpcIoFile.cc index 316c70540c..b706d5b00b 100644 --- a/src/DiskIO/IpcIo/IpcIoFile.cc +++ b/src/DiskIO/IpcIo/IpcIoFile.cc @@ -639,23 +639,38 @@ void IpcIoFile::DiskerHandleRequests() { // Balance our desire to maximize the number of concurrent I/O requests - // (for the OS to reorder to minimize seek time) with a requirement to + // (reordred by OS to minimize seek time) with a requirement to // send 1st-I/O notification messages, process Coordinator events, etc. - const int maxPopped = 1; + const int maxSpentMsec = 10; // keep small: most RAM I/Os are under 1ms + const timeval loopStart = current_time; + int popped = 0; int workerId = 0; IpcIoMsg ipcIo; - for (; popped < maxPopped && queue->pop(workerId, ipcIo); ++popped) + while (queue->pop(workerId, ipcIo)) { + ++popped; + + // at least one I/O per call is guaranteed if the queue is not empty DiskerHandleRequest(workerId, ipcIo); - if (popped >= maxPopped && !DiskerHandleMoreRequestsScheduled) { - eventAdd("IpcIoFile::DiskerHandleMoreRequests", - &IpcIoFile::DiskerHandleMoreRequests, - NULL, 0.001, 0, false); - DiskerHandleMoreRequestsScheduled = true; + getCurrentTime(); + const double elapsedMsec = tvSubMsec(loopStart, current_time); + if (elapsedMsec > maxSpentMsec || elapsedMsec < 0) { + if (!DiskerHandleMoreRequestsScheduled) { + // the gap must be positive for select(2) to be given a chance + const double minBreakSecs = 0.001; + eventAdd("IpcIoFile::DiskerHandleMoreRequests", + &IpcIoFile::DiskerHandleMoreRequests, + NULL, minBreakSecs, 0, false); + DiskerHandleMoreRequestsScheduled = true; + } + debugs(47, 3, HERE << "pausing after " << popped << " I/Os in " << + elapsedMsec << "ms; " << (elapsedMsec/popped) << "ms per I/O"); + break; + } } - // TODO: consider adding an "elevator" optimization where we pop a few + // TODO: consider using O_DIRECT with "elevator" optimization where we pop // requests first, then reorder the popped requests to optimize seek time, // then do I/O, then take a break, and come back for the next set of I/O // requests.