Bug 1162218 - Make worker idle thread timeouts more strict, r=baku.
authorBen Turner <bent.mozilla@gmail.com>
Thu, 07 May 2015 10:35:57 -0700
changeset 242801 4dc03fc3888594f7713747e8af689d12897e6c7f
parent 242800 8952a7fa40507660721df603fdf05434a318140d
child 242802 b6aa5c3d357933d065e1d302768a807b9d0624db
push id59513
push userbturner@mozilla.com
push dateThu, 07 May 2015 17:36:42 +0000
treeherdermozilla-inbound@4dc03fc38885 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1162218
milestone40.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 1162218 - Make worker idle thread timeouts more strict, r=baku.
dom/workers/RuntimeService.cpp
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -1782,17 +1782,17 @@ RuntimeService::ShutdownIdleThreads(nsIT
   AssertIsOnMainThread();
 
   RuntimeService* runtime = RuntimeService::GetService();
   NS_ASSERTION(runtime, "This should never be null!");
 
   NS_ASSERTION(aTimer == runtime->mIdleThreadTimer, "Wrong timer!");
 
   // Cheat a little and grab all threads that expire within one second of now.
-  TimeStamp now = TimeStamp::Now() + TimeDuration::FromSeconds(1);
+  TimeStamp now = TimeStamp::NowLoRes() + TimeDuration::FromSeconds(1);
 
   TimeStamp nextExpiration;
 
   nsAutoTArray<nsRefPtr<WorkerThread>, 20> expiredThreads;
   {
     MutexAutoLock lock(runtime->mMutex);
 
     for (uint32_t index = 0; index < runtime->mIdleThreadArray.Length();
@@ -1807,37 +1807,33 @@ RuntimeService::ShutdownIdleThreads(nsIT
       thread->swap(info.mThread);
     }
 
     if (!expiredThreads.IsEmpty()) {
       runtime->mIdleThreadArray.RemoveElementsAt(0, expiredThreads.Length());
     }
   }
 
-  NS_ASSERTION(nextExpiration.IsNull() || !expiredThreads.IsEmpty(),
-               "Should have a new time or there should be some threads to shut "
-               "down");
+  if (!nextExpiration.IsNull()) {
+    TimeDuration delta = nextExpiration - TimeStamp::NowLoRes();
+    uint32_t delay(delta > TimeDuration(0) ? delta.ToMilliseconds() : 0);
+
+    // Reschedule the timer.
+    MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
+      aTimer->InitWithFuncCallback(ShutdownIdleThreads,
+                                   nullptr,
+                                   delay,
+                                   nsITimer::TYPE_ONE_SHOT)));
+  }
 
   for (uint32_t index = 0; index < expiredThreads.Length(); index++) {
     if (NS_FAILED(expiredThreads[index]->Shutdown())) {
       NS_WARNING("Failed to shutdown thread!");
     }
   }
-
-  if (!nextExpiration.IsNull()) {
-    TimeDuration delta = nextExpiration - TimeStamp::Now();
-    uint32_t delay(delta > TimeDuration(0) ? delta.ToMilliseconds() : 0);
-
-    // Reschedule the timer.
-    if (NS_FAILED(aTimer->InitWithFuncCallback(ShutdownIdleThreads, nullptr,
-                                               delay,
-                                               nsITimer::TYPE_ONE_SHOT))) {
-      NS_ERROR("Can't schedule timer!");
-    }
-  }
 }
 
 nsresult
 RuntimeService::Init()
 {
   AssertIsOnMainThread();
 
   nsLayoutStatics::AddRef();
@@ -2497,50 +2493,53 @@ RuntimeService::ForgetSharedWorker(Worke
 }
 
 void
 RuntimeService::NoteIdleThread(WorkerThread* aThread)
 {
   AssertIsOnMainThread();
   MOZ_ASSERT(aThread);
 
-  static TimeDuration timeout =
-    TimeDuration::FromSeconds(IDLE_THREAD_TIMEOUT_SEC);
-
-  TimeStamp expirationTime = TimeStamp::Now() + timeout;
-
-  bool shutdown;
-  if (mShuttingDown) {
-    shutdown = true;
-  }
-  else {
+  bool shutdownThread = mShuttingDown;
+  bool scheduleTimer = false;
+
+  if (!shutdownThread) {
+    static TimeDuration timeout =
+      TimeDuration::FromSeconds(IDLE_THREAD_TIMEOUT_SEC);
+
+    TimeStamp expirationTime = TimeStamp::NowLoRes() + timeout;
+
     MutexAutoLock lock(mMutex);
 
-    if (mIdleThreadArray.Length() < MAX_IDLE_THREADS) {
+    uint32_t previousIdleCount = mIdleThreadArray.Length();
+
+    if (previousIdleCount < MAX_IDLE_THREADS) {
       IdleThreadInfo* info = mIdleThreadArray.AppendElement();
       info->mThread = aThread;
       info->mExpirationTime = expirationTime;
-      shutdown = false;
-    }
-    else {
-      shutdown = true;
+
+      scheduleTimer = previousIdleCount == 0;
+    } else {
+      shutdownThread = true;
     }
   }
 
+  MOZ_ASSERT_IF(shutdownThread, !scheduleTimer);
+  MOZ_ASSERT_IF(scheduleTimer, !shutdownThread);
+
   // Too many idle threads, just shut this one down.
-  if (shutdown) {
+  if (shutdownThread) {
     MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aThread->Shutdown()));
-    return;
+  } else if (scheduleTimer) {
+    MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
+      mIdleThreadTimer->InitWithFuncCallback(ShutdownIdleThreads,
+                                             nullptr,
+                                             IDLE_THREAD_TIMEOUT_SEC * 1000,
+                                             nsITimer::TYPE_ONE_SHOT)));
   }
-
-  // Schedule timer.
-  MOZ_ALWAYS_TRUE(NS_SUCCEEDED(mIdleThreadTimer->InitWithFuncCallback(
-                                                 ShutdownIdleThreads, nullptr,
-                                                 IDLE_THREAD_TIMEOUT_SEC * 1000,
-                                                 nsITimer::TYPE_ONE_SHOT)));
 }
 
 void
 RuntimeService::UpdateAllWorkerRuntimeOptions()
 {
   BROADCAST_ALL_WORKERS(UpdateRuntimeOptions, sDefaultJSSettings.runtimeOptions);
 }