Bug 1551203, Bug 1551203 - Give ThrottledEventQueues names, r=erahm
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Mon, 13 May 2019 18:12:24 +0000
changeset 532459 7b168d837392915c41fe70b506222115659ff078
parent 532458 e153188e2d93b251c16a6a1d74fd1e2d952fe2eb
child 532460 a6445a0726c098e5dda6ac514f3d90a00ff77f45
push id11268
push usercsabou@mozilla.com
push dateTue, 14 May 2019 15:24:22 +0000
treeherdermozilla-beta@5fb7fcd568d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerserahm
bugs1551203
milestone68.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 1551203, Bug 1551203 - Give ThrottledEventQueues names, r=erahm Differential Revision: https://phabricator.services.mozilla.com/D30920
dom/base/TabGroup.cpp
dom/workers/WorkerPrivate.cpp
xpcom/tests/gtest/TestEventTargetQI.cpp
xpcom/tests/gtest/TestThrottledEventQueue.cpp
xpcom/threads/ThrottledEventQueue.cpp
xpcom/threads/ThrottledEventQueue.h
--- a/dom/base/TabGroup.cpp
+++ b/dom/base/TabGroup.cpp
@@ -75,18 +75,24 @@ void TabGroup::EnsureThrottledEventQueue
   if (mThrottledQueuesInitialized) {
     return;
   }
 
   mThrottledQueuesInitialized = true;
 
   for (size_t i = 0; i < size_t(TaskCategory::Count); i++) {
     TaskCategory category = static_cast<TaskCategory>(i);
-    if (category == TaskCategory::Worker || category == TaskCategory::Timer) {
-      mEventTargets[i] = ThrottledEventQueue::Create(mEventTargets[i]);
+    if (category == TaskCategory::Worker) {
+      mEventTargets[i] =
+          ThrottledEventQueue::Create(mEventTargets[i],
+                                      "TabGroup worker queue");
+    } else if (category == TaskCategory::Timer) {
+      mEventTargets[i] =
+          ThrottledEventQueue::Create(mEventTargets[i],
+                                      "TabGroup timer queue");
     }
   }
 }
 
 /* static */
 TabGroup* TabGroup::GetChromeTabGroup() {
   if (!sChromeTabGroup) {
     sChromeTabGroup = new TabGroup(true /* chrome tab group */);
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -2142,25 +2142,28 @@ WorkerPrivate::WorkerPrivate(WorkerPriva
 
   if (!target) {
     target = GetMainThreadSerialEventTarget();
     MOZ_DIAGNOSTIC_ASSERT(target);
   }
 
   // Throttle events to the main thread using a ThrottledEventQueue specific to
   // this tree of worker threads.
-  mMainThreadEventTargetForMessaging = ThrottledEventQueue::Create(target);
+  mMainThreadEventTargetForMessaging =
+      ThrottledEventQueue::Create(target, "Worker queue for messaging");
   if (StaticPrefs::dom_worker_use_medium_high_event_queue()) {
     mMainThreadEventTarget =
         ThrottledEventQueue::Create(GetMainThreadSerialEventTarget(),
+                                    "Worker queue",
                                     nsIRunnablePriority::PRIORITY_MEDIUMHIGH);
   } else {
     mMainThreadEventTarget = mMainThreadEventTargetForMessaging;
   }
-  mMainThreadDebuggeeEventTarget = ThrottledEventQueue::Create(target);
+  mMainThreadDebuggeeEventTarget =
+      ThrottledEventQueue::Create(target, "Worker debuggee queue");
   if (IsParentWindowPaused() || IsFrozen()) {
     MOZ_ALWAYS_SUCCEEDS(mMainThreadDebuggeeEventTarget->SetIsPaused(true));
   }
 }
 
 WorkerPrivate::~WorkerPrivate() {
   DropJSObjects(this);
 
--- a/xpcom/tests/gtest/TestEventTargetQI.cpp
+++ b/xpcom/tests/gtest/TestEventTargetQI.cpp
@@ -57,17 +57,18 @@ TEST(TestEventTargetQI, Thread)
   EXPECT_TRUE(TestQITo<nsISerialEventTarget>(thing));
 
   EXPECT_TRUE(TestQITo<nsIEventTarget>(thing));
 }
 
 TEST(TestEventTargetQI, ThrottledEventQueue)
 {
   nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
-  RefPtr<ThrottledEventQueue> thing = ThrottledEventQueue::Create(thread);
+  RefPtr<ThrottledEventQueue> thing =
+      ThrottledEventQueue::Create(thread, "test queue");
   EXPECT_TRUE(thing);
 
   EXPECT_TRUE(TestQITo<nsISerialEventTarget>(thing));
 
   EXPECT_TRUE(TestQITo<nsIEventTarget>(thing));
 }
 
 TEST(TestEventTargetQI, LazyIdleThread)
--- a/xpcom/tests/gtest/TestThrottledEventQueue.cpp
+++ b/xpcom/tests/gtest/TestThrottledEventQueue.cpp
@@ -117,32 +117,34 @@ TEST(ThrottledEventQueue, RunnableQueue)
   ASSERT_EQ(log, "abc");
 }
 
 TEST(ThrottledEventQueue, SimpleDispatch)
 {
   string log;
 
   auto base = MakeRefPtr<RunnableQueue>();
-  RefPtr<ThrottledEventQueue> throttled = ThrottledEventQueue::Create(base);
+  RefPtr<ThrottledEventQueue> throttled =
+      ThrottledEventQueue::Create(base, "test queue 1");
 
   Enqueue(throttled, [&]() { log += 'a'; });
   ASSERT_TRUE(NS_SUCCEEDED(base->Run()));
   ASSERT_EQ(log, "a");
 
   ASSERT_TRUE(base->IsEmpty());
   ASSERT_TRUE(throttled->IsEmpty());
 }
 
 TEST(ThrottledEventQueue, MixedDispatch)
 {
   string log;
 
   auto base = MakeRefPtr<RunnableQueue>();
-  RefPtr<ThrottledEventQueue> throttled = ThrottledEventQueue::Create(base);
+  RefPtr<ThrottledEventQueue> throttled =
+      ThrottledEventQueue::Create(base, "test queue 2");
 
   // A ThrottledEventQueue limits its impact on the base target by only queuing
   // its next event on the base once the prior event has been run. What it
   // actually queues on the base is a sort of proxy event called an
   // "executor": the base running the executor draws an event from the
   // ThrottledEventQueue and runs that. If the ThrottledEventQueue has further
   // events, it re-queues the executor on the base, effectively "going to the
   // back of the line".
@@ -177,17 +179,18 @@ TEST(ThrottledEventQueue, MixedDispatch)
   ASSERT_TRUE(throttled->IsEmpty());
 }
 
 TEST(ThrottledEventQueue, EnqueueFromRun)
 {
   string log;
 
   auto base = MakeRefPtr<RunnableQueue>();
-  RefPtr<ThrottledEventQueue> throttled = ThrottledEventQueue::Create(base);
+  RefPtr<ThrottledEventQueue> throttled =
+      ThrottledEventQueue::Create(base, "test queue 3");
 
   // When an event from the throttled queue dispatches a new event directly to
   // the base target, it is queued after the executor, so the next event from
   // the throttled queue will run before it.
   Enqueue(base, [&]() { log += 'a'; });
   Enqueue(throttled, [&]() {
     log += 'b';
     Enqueue(base, [&]() { log += 'c'; });
@@ -202,17 +205,18 @@ TEST(ThrottledEventQueue, EnqueueFromRun
   ASSERT_TRUE(throttled->IsEmpty());
 }
 
 TEST(ThrottledEventQueue, RunFromRun)
 {
   string log;
 
   auto base = MakeRefPtr<RunnableQueue>();
-  RefPtr<ThrottledEventQueue> throttled = ThrottledEventQueue::Create(base);
+  RefPtr<ThrottledEventQueue> throttled =
+      ThrottledEventQueue::Create(base, "test queue 4");
 
   // Running the event queue from within an event (i.e., a nested event loop)
   // does not stall the ThrottledEventQueue.
   Enqueue(throttled, [&]() {
     log += '(';
     // This should run subsequent events from throttled.
     ASSERT_TRUE(NS_SUCCEEDED(base->Run()));
     log += ')';
@@ -231,17 +235,18 @@ TEST(ThrottledEventQueue, RunFromRun)
 TEST(ThrottledEventQueue, DropWhileRunning)
 {
   string log;
 
   auto base = MakeRefPtr<RunnableQueue>();
 
   // If we drop the event queue while it still has events, they still run.
   {
-    RefPtr<ThrottledEventQueue> throttled = ThrottledEventQueue::Create(base);
+    RefPtr<ThrottledEventQueue> throttled =
+        ThrottledEventQueue::Create(base, "test queue 5");
     Enqueue(throttled, [&]() { log += 'a'; });
   }
 
   ASSERT_EQ(log, "");
   ASSERT_TRUE(NS_SUCCEEDED(base->Run()));
   ASSERT_EQ(log, "a");
 }
 
@@ -250,17 +255,18 @@ TEST(ThrottledEventQueue, AwaitIdle)
   Mutex mutex("TEQ AwaitIdle");
   CondVar cond(mutex, "TEQ AwaitIdle");
 
   string dequeue_await;           // mutex
   bool threadFinished = false;    // mutex & cond
   bool runnableFinished = false;  // main thread only
 
   auto base = MakeRefPtr<RunnableQueue>();
-  RefPtr<ThrottledEventQueue> throttled = ThrottledEventQueue::Create(base);
+  RefPtr<ThrottledEventQueue> throttled =
+      ThrottledEventQueue::Create(base, "test queue 6");
 
   // Put an event in the queue so the AwaitIdle might block.
   Enqueue(throttled, [&]() { runnableFinished = true; });
 
   // Create a separate thread that waits for the queue to become idle, and
   // then takes observable action.
   nsCOMPtr<nsIRunnable> await = NS_NewRunnableFunction("TEQ AwaitIdle", [&]() {
     throttled->AwaitIdle();
@@ -313,17 +319,18 @@ TEST(ThrottledEventQueue, AwaitIdleMixed
   CondVar cond(mutex, "AwaitIdleMixed");
 
   // The following are protected by mutex and cond, above.
   string log;
   bool threadStarted = false;
   bool threadFinished = false;
 
   auto base = MakeRefPtr<RunnableQueue>();
-  RefPtr<ThrottledEventQueue> throttled = ThrottledEventQueue::Create(base);
+  RefPtr<ThrottledEventQueue> throttled =
+      ThrottledEventQueue::Create(base, "test queue 7");
 
   Enqueue(throttled, [&]() {
     MutexAutoLock lock(mutex);
     log += 'a';
   });
 
   Enqueue(throttled, [&]() {
     MutexAutoLock lock(mutex);
@@ -392,17 +399,18 @@ TEST(ThrottledEventQueue, AwaitIdleMixed
   ASSERT_TRUE(NS_SUCCEEDED(thread->Shutdown()));
 }
 
 TEST(ThrottledEventQueue, SimplePauseResume)
 {
   string log;
 
   auto base = MakeRefPtr<RunnableQueue>();
-  RefPtr<ThrottledEventQueue> throttled = ThrottledEventQueue::Create(base);
+  RefPtr<ThrottledEventQueue> throttled =
+      ThrottledEventQueue::Create(base, "test queue 8");
 
   ASSERT_FALSE(throttled->IsPaused());
 
   Enqueue(throttled, [&]() { log += 'a'; });
 
   ASSERT_EQ(log, "");
   ASSERT_TRUE(NS_SUCCEEDED(base->Run()));
   ASSERT_EQ(log, "a");
@@ -427,17 +435,18 @@ TEST(ThrottledEventQueue, SimplePauseRes
   ASSERT_TRUE(throttled->IsEmpty());
 }
 
 TEST(ThrottledEventQueue, MixedPauseResume)
 {
   string log;
 
   auto base = MakeRefPtr<RunnableQueue>();
-  RefPtr<ThrottledEventQueue> throttled = ThrottledEventQueue::Create(base);
+  RefPtr<ThrottledEventQueue> throttled =
+      ThrottledEventQueue::Create(base, "test queue 9");
 
   ASSERT_FALSE(throttled->IsPaused());
 
   Enqueue(base, [&]() { log += 'A'; });
   Enqueue(throttled, [&]() {
     log += 'b';
     MOZ_ALWAYS_TRUE(NS_SUCCEEDED(throttled->SetIsPaused(true)));
   });
@@ -472,17 +481,18 @@ TEST(ThrottledEventQueue, AwaitIdlePause
   Mutex mutex("AwaitIdlePaused");
   CondVar cond(mutex, "AwaitIdlePaused");
 
   string dequeue_await;           // mutex
   bool threadFinished = false;    // mutex & cond
   bool runnableFinished = false;  // main thread only
 
   auto base = MakeRefPtr<RunnableQueue>();
-  RefPtr<ThrottledEventQueue> throttled = ThrottledEventQueue::Create(base);
+  RefPtr<ThrottledEventQueue> throttled =
+      ThrottledEventQueue::Create(base, "test queue 10");
 
   ASSERT_TRUE(NS_SUCCEEDED(throttled->SetIsPaused(true)));
 
   // Put an event in the queue so the AwaitIdle might block. Since throttled is
   // paused, this should not enqueue an executor in the base target.
   Enqueue(throttled, [&]() { runnableFinished = true; });
   ASSERT_TRUE(base->IsEmpty());
 
@@ -540,17 +550,18 @@ TEST(ThrottledEventQueue, AwaitIdlePause
   ASSERT_TRUE(NS_SUCCEEDED(thread->Shutdown()));
 }
 
 TEST(ThrottledEventQueue, ExecutorTransitions)
 {
   string log;
 
   auto base = MakeRefPtr<RunnableQueue>();
-  RefPtr<ThrottledEventQueue> throttled = ThrottledEventQueue::Create(base);
+  RefPtr<ThrottledEventQueue> throttled =
+      ThrottledEventQueue::Create(base, "test queue 11");
 
   ASSERT_TRUE(NS_SUCCEEDED(throttled->SetIsPaused(true)));
 
   // Since we're paused, queueing an event on throttled shouldn't queue the
   // executor on the base target.
   Enqueue(throttled, [&]() { log += 'a'; });
   ASSERT_EQ(throttled->Length(), 1U);
   ASSERT_EQ(base->Length(), 0U);
--- a/xpcom/threads/ThrottledEventQueue.cpp
+++ b/xpcom/threads/ThrottledEventQueue.cpp
@@ -108,28 +108,34 @@ class ThrottledEventQueue::Inner final :
   nsCOMPtr<nsISerialEventTarget> mBaseTarget;
 
   // The Executor that we dispatch to mBaseTarget to draw runnables from our
   // queue. mExecutor->mInner points to this Inner, forming a reference loop.
   //
   // Used from any thread; protected by mMutex.
   nsCOMPtr<nsIRunnable> mExecutor;
 
+  const char* mName;
+
   const uint32_t mPriority;
 
   // True if this queue is currently paused.
   // Used from any thread; protected by mMutex.
   bool mIsPaused;
 
-  explicit Inner(nsISerialEventTarget* aBaseTarget, uint32_t aPriority)
+  explicit Inner(nsISerialEventTarget* aBaseTarget, const char* aName,
+                 uint32_t aPriority)
       : mMutex("ThrottledEventQueue"),
         mIdleCondVar(mMutex, "ThrottledEventQueue:Idle"),
         mBaseTarget(aBaseTarget),
+        mName(aName),
         mPriority(aPriority),
-        mIsPaused(false) {}
+        mIsPaused(false) {
+          MOZ_ASSERT(mName, "Must pass a valid name!");
+        }
 
   ~Inner() {
 #ifdef DEBUG
     MutexAutoLock lock(mMutex);
 
     // As long as an executor exists, it had better keep us alive, since it's
     // going to call ExecuteRunnable on us.
     MOZ_ASSERT(!mExecutor);
@@ -180,17 +186,17 @@ class ThrottledEventQueue::Inner final :
       MOZ_ALWAYS_TRUE(event);
     }
 
     if (nsCOMPtr<nsINamed> named = do_QueryInterface(event)) {
       nsresult rv = named->GetName(aName);
       return rv;
     }
 
-    aName.AssignLiteral("non-nsINamed ThrottledEventQueue runnable");
+    aName.AssignASCII(mName);
     return NS_OK;
   }
 
   void ExecuteRunnable() {
     // Any thread
     nsCOMPtr<nsIRunnable> event;
 
 #ifdef DEBUG
@@ -240,22 +246,23 @@ class ThrottledEventQueue::Inner final :
     }
 
     // Execute the event now that we have unlocked.
     Unused << event->Run();
   }
 
  public:
   static already_AddRefed<Inner> Create(nsISerialEventTarget* aBaseTarget,
+                                        const char* aName,
                                         uint32_t aPriority) {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(ClearOnShutdown_Internal::sCurrentShutdownPhase ==
                ShutdownPhase::NotInShutdown);
 
-    RefPtr<Inner> ref = new Inner(aBaseTarget, aPriority);
+    RefPtr<Inner> ref = new Inner(aBaseTarget, aName, aPriority);
     return ref.forget();
   }
 
   bool IsEmpty() const {
     // Any thread
     return Length() == 0;
   }
 
@@ -353,21 +360,21 @@ NS_IMPL_ISUPPORTS(ThrottledEventQueue, T
                   nsISerialEventTarget);
 
 ThrottledEventQueue::ThrottledEventQueue(already_AddRefed<Inner> aInner)
     : mInner(aInner) {
   MOZ_ASSERT(mInner);
 }
 
 already_AddRefed<ThrottledEventQueue> ThrottledEventQueue::Create(
-    nsISerialEventTarget* aBaseTarget, uint32_t aPriority) {
+    nsISerialEventTarget* aBaseTarget, const char* aName, uint32_t aPriority) {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aBaseTarget);
 
-  RefPtr<Inner> inner = Inner::Create(aBaseTarget, aPriority);
+  RefPtr<Inner> inner = Inner::Create(aBaseTarget, aName, aPriority);
 
   RefPtr<ThrottledEventQueue> ref = new ThrottledEventQueue(inner.forget());
   return ref.forget();
 }
 
 bool ThrottledEventQueue::IsEmpty() const { return mInner->IsEmpty(); }
 
 uint32_t ThrottledEventQueue::Length() const { return mInner->Length(); }
--- a/xpcom/threads/ThrottledEventQueue.h
+++ b/xpcom/threads/ThrottledEventQueue.h
@@ -64,16 +64,17 @@ class ThrottledEventQueue final : public
 
   explicit ThrottledEventQueue(already_AddRefed<Inner> aInner);
   ~ThrottledEventQueue() = default;
 
  public:
   // Create a ThrottledEventQueue for the given target.
   static already_AddRefed<ThrottledEventQueue> Create(
       nsISerialEventTarget* aBaseTarget,
+      const char* aName,
       uint32_t aPriority = nsIRunnablePriority::PRIORITY_NORMAL);
 
   // Determine if there are any events pending in the queue.
   bool IsEmpty() const;
 
   // Determine how many events are pending in the queue.
   uint32_t Length() const;