From 386d28bf99bb37ede705f7f244c9d9cfc98cf2ed Mon Sep 17 00:00:00 2001 From: Alex Rousskov Date: Tue, 30 Aug 2011 09:45:20 -0600 Subject: [PATCH] Use a time-based limit for the Rock Store rebuild 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. 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 | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/fs/rock/RockRebuild.cc b/src/fs/rock/RockRebuild.cc index 4fa9255661..6becb797cc 100644 --- a/src/fs/rock/RockRebuild.cc +++ b/src/fs/rock/RockRebuild.cc @@ -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(); } -- 2.47.3