Bug 1425301 - Progressively decrease the 6 seconds maximum quantum delay of tracker script tailing, r=dragana
authorHonza Bambas <honzab.moz@firemni.cz>
Mon, 08 Jan 2018 06:01:00 +0200
changeset 450009 cf08f8b8d13bc8df6cacc40e0833d3199880464e
parent 450008 2ba9bb352b5d0d72644bf8498e332a812e2cff1b
child 450010 5a503850a497e892b8e4036bb7155194e6db3254
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdragana
bugs1425301
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1425301 - Progressively decrease the 6 seconds maximum quantum delay of tracker script tailing, r=dragana
modules/libpref/init/all.js
netwerk/base/RequestContextService.cpp
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2240,16 +2240,18 @@ pref("network.http.tailing.enabled", tru
 // When the page load has not yet reached DOMContentLoaded point, tail requestes are delayed
 // by (non-tailed requests count + 1) * delay-quantum milliseconds.
 pref("network.http.tailing.delay-quantum", 600);
 // The same as above, but applied after the document load reached DOMContentLoaded event.
 pref("network.http.tailing.delay-quantum-after-domcontentloaded", 100);
 // Upper limit for the calculated delay, prevents long standing and comet-like requests
 // tail forever.  This is in milliseconds as well.
 pref("network.http.tailing.delay-max", 6000);
+// Total limit we delay tailed requests since a page load beginning.
+pref("network.http.tailing.total-max", 45000);
 
 pref("permissions.default.image",           1); // 1-Accept, 2-Deny, 3-dontAcceptForeign
 
 pref("network.proxy.type",                  5);
 pref("network.proxy.ftp",                   "");
 pref("network.proxy.ftp_port",              0);
 pref("network.proxy.http",                  "");
 pref("network.proxy.http_port",             0);
--- a/netwerk/base/RequestContextService.cpp
+++ b/netwerk/base/RequestContextService.cpp
@@ -71,16 +71,22 @@ private:
   // Timestamp when the timer is expected to fire,
   // always less than or equal to mUntailAt
   TimeStamp mTimerScheduledAt;
   // Timestamp when we want to actually untail queued requets based on
   // the number of request count change in the past; iff this timestamp
   // is set, we tail requests
   TimeStamp mUntailAt;
 
+  // Timestamp of the navigation start time, set to Now() in BeginLoad().
+  // This is used to progressively lower the maximum delay time so that
+  // we can't get to a situation when a number of repetitive requests
+  // on the page causes forever tailing.
+  TimeStamp mBeginLoadTime;
+
   // This member is true only between DOMContentLoaded notification and
   // next document load beginning for this request context.
   // Top level request contexts are recycled.
   bool mAfterDOMContentLoaded;
 };
 
 NS_IMPL_ISUPPORTS(RequestContext, nsIRequestContext, nsITimerCallback)
 
@@ -112,16 +118,17 @@ RequestContext::BeginLoad()
     // Tailing is not supported on the child process
     if (gNeckoChild) {
       gNeckoChild->SendRequestContextLoadBegin(mID);
     }
     return NS_OK;
   }
 
   mAfterDOMContentLoaded = false;
+  mBeginLoadTime = TimeStamp::NowLoRes();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 RequestContext::DOMContentLoaded()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -246,16 +253,31 @@ RequestContext::ScheduleUnblock()
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!gHttpHandler) {
     return;
   }
 
   uint32_t quantum = gHttpHandler->TailBlockingDelayQuantum(mAfterDOMContentLoaded);
   uint32_t delayMax = gHttpHandler->TailBlockingDelayMax();
+  uint32_t totalMax = gHttpHandler->TailBlockingTotalMax();
+
+  if (!mBeginLoadTime.IsNull()) {
+    // We decrease the maximum delay progressively with the time since the page load
+    // begin.  This seems like a reasonable and clear heuristic allowing us to start
+    // loading tailed requests in a deterministic time after the load has started.
+
+    uint32_t sinceBeginLoad = static_cast<uint32_t>(
+      (TimeStamp::NowLoRes() - mBeginLoadTime).ToMilliseconds());
+    uint32_t tillTotal = totalMax - std::min(sinceBeginLoad, totalMax);
+    uint32_t proportion = totalMax // values clamped between 0 and 60'000
+      ? (delayMax * tillTotal) / totalMax
+      : 0;
+    delayMax = std::min(delayMax, proportion);
+  }
 
   CheckedInt<uint32_t> delay = quantum * mNonTailRequests;
 
   if (!mAfterDOMContentLoaded) {
     // Before DOMContentLoaded notification we want to make sure that tailed
     // requests don't start when there is a short delay during which we may
     // not have any active requests on the page happening.
     delay += quantum;
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -1750,16 +1750,20 @@ nsHttpHandler::PrefsChanged(nsIPrefBranc
     if (PREF_CHANGED(HTTP_PREF("tailing.delay-quantum-after-domcontentloaded"))) {
         Unused << prefs->GetIntPref(HTTP_PREF("tailing.delay-quantum-after-domcontentloaded"), &val);
         mTailDelayQuantumAfterDCL = (uint32_t)clamped(val, 0, 60000);
     }
     if (PREF_CHANGED(HTTP_PREF("tailing.delay-max"))) {
         Unused << prefs->GetIntPref(HTTP_PREF("tailing.delay-max"), &val);
         mTailDelayMax = (uint32_t)clamped(val, 0, 60000);
     }
+    if (PREF_CHANGED(HTTP_PREF("tailing.total-max"))) {
+        Unused << prefs->GetIntPref(HTTP_PREF("tailing.total-max"), &val);
+        mTailTotalMax = (uint32_t)clamped(val, 0, 60000);
+    }
 
     if (PREF_CHANGED(HTTP_PREF("focused_window_transaction_ratio"))) {
         float ratio = 0;
         rv = prefs->GetFloatPref(HTTP_PREF("focused_window_transaction_ratio"), &ratio);
         if (NS_SUCCEEDED(rv)) {
             if (ratio > 0 && ratio < 1) {
                 mFocusedWindowTransactionRatio = ratio;
             } else {
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -139,16 +139,17 @@ public:
 
     bool           PromptTempRedirect()      { return mPromptTempRedirect; }
     bool           IsUrgentStartEnabled() { return mUrgentStartEnabled; }
     bool           IsTailBlockingEnabled() { return mTailBlockingEnabled; }
     uint32_t       TailBlockingDelayQuantum(bool aAfterDOMContentLoaded) {
       return aAfterDOMContentLoaded ? mTailDelayQuantumAfterDCL : mTailDelayQuantum;
     }
     uint32_t       TailBlockingDelayMax() { return mTailDelayMax; }
+    uint32_t       TailBlockingTotalMax() { return mTailTotalMax; }
 
     uint32_t       ThrottlingReadLimit() { return mThrottleVersion == 1 ? 0 : mThrottleReadLimit; }
 
     // TCP Keepalive configuration values.
 
     // Returns true if TCP keepalive should be enabled for short-lived conns.
     bool TCPKeepaliveEnabledForShortLivedConns() {
       return mTCPKeepaliveShortLivedEnabled;
@@ -503,16 +504,17 @@ private:
     uint32_t mThrottleHoldTime;
     uint32_t mThrottleMaxTime;
 
     bool mUrgentStartEnabled;
     bool mTailBlockingEnabled;
     uint32_t mTailDelayQuantum;
     uint32_t mTailDelayQuantumAfterDCL;
     uint32_t mTailDelayMax;
+    uint32_t mTailTotalMax;
 
     uint8_t  mRedirectionLimit;
 
     // we'll warn the user if we load an URL containing a userpass field
     // unless its length is less than this threshold.  this warning is
     // intended to protect the user against spoofing attempts that use
     // the userpass field of the URL to obscure the actual origin server.
     uint8_t  mPhishyUserPassLength;