]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Use a time-based limit for the disker I/O loop.
authorAlex Rousskov <rousskov@measurement-factory.com>
Mon, 29 Aug 2011 23:14:17 +0000 (17:14 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Mon, 29 Aug 2011 23:14:17 +0000 (17:14 -0600)
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.

src/DiskIO/IpcIo/IpcIoFile.cc

index 316c70540ca2eb167283a9f0ee01bc791ec3a37f..b706d5b00b49c85a3b6929639ebf09a563ae5949 100644 (file)
@@ -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.