]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Use a time-based limit for the Rock Store rebuild loop.
authorAlex Rousskov <rousskov@measurement-factory.com>
Tue, 30 Aug 2011 15:45:20 +0000 (09:45 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Tue, 30 Aug 2011 15:45:20 +0000 (09:45 -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. Similarly, a time-based limit often allows us to rebuild a much larger
number of entries at a time because most sequential read I/Os are very fast.

src/fs/rock/RockRebuild.cc

index 4fa92556613c0d82ab5ab5c3c26093bc00025c40..6becb797ccf777fbca71de731c8e4c5b724d948c 100644 (file)
@@ -8,6 +8,7 @@
 #include "fs/rock/RockRebuild.h"
 #include "fs/rock/RockSwapDir.h"
 #include "fs/rock/RockFile.h"
+#include "SquidTime.h"
 
 CBDATA_NAMESPACED_CLASS_INIT(Rock, Rebuild);
 
@@ -87,16 +88,33 @@ Rock::Rebuild::steps() {
     debugs(47,5, HERE << sd->index << " filen " << filen << " at " <<
         dbOffset << " <= " << dbSize);
 
-    const int maxCount = dbEntryLimit;
-    const int wantedCount = opt_foreground_rebuild ? maxCount : 50;
-    const int stepCount = min(wantedCount, maxCount);
-    for (int i = 0; i < stepCount && dbOffset < dbSize; ++i, ++filen) {
+    // Balance our desire to maximize the number of entries processed at once
+    // (and, hence, minimize overheads and total rebuild time) with a 
+    // requirement to also process Coordinator events, disk I/Os, etc.
+    const int maxSpentMsec = 50; // keep small: most RAM I/Os are under 1ms
+    const timeval loopStart = current_time;
+
+    int loaded = 0;
+    while (loaded < dbEntryLimit && dbOffset < dbSize) {
         doOneEntry();
         dbOffset += dbEntrySize;
+        ++filen;
+        ++loaded;
 
         if (counts.scancount % 1000 == 0)
-            storeRebuildProgress(sd->index, maxCount, counts.scancount);
-       }
+            storeRebuildProgress(sd->index, dbEntryLimit, counts.scancount);
+
+        if (opt_foreground_rebuild)
+            continue; // skip "few entries at a time" check below
+
+        getCurrentTime();
+        const double elapsedMsec = tvSubMsec(loopStart, current_time);
+        if (elapsedMsec > maxSpentMsec || elapsedMsec < 0) {
+            debugs(47, 5, HERE << "pausing after " << loaded << " entries in " <<
+               elapsedMsec << "ms; " << (elapsedMsec/loaded) << "ms per entry");
+            break;
+        }
+    }
 
     checkpoint();
 }