Bug 1552077. Use medium high runnables for a few more imagelib runnables. r=smaug
authorTimothy Nikkel <tnikkel@gmail.com>
Fri, 17 May 2019 23:09:38 +0000
changeset 533242 0649547f4b2947c188067f0502733100b6d7f92d
parent 533241 197df45a8076f497c59951d3ab818af9ba7eedcc
child 533243 8e8ea33ecb3da138dbd0af56c2e5550902e7b05a
push id11276
push userrgurzau@mozilla.com
push dateMon, 20 May 2019 13:11:24 +0000
treeherdermozilla-beta@847755a7c325 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1552077
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 1552077. Use medium high runnables for a few more imagelib runnables. r=smaug speedindex runs show this to be a nice win. Differential Revision: https://phabricator.services.mozilla.com/D31370
image/ProgressTracker.cpp
image/ProgressTracker.h
image/imgRequest.cpp
--- a/image/ProgressTracker.cpp
+++ b/image/ProgressTracker.cpp
@@ -150,16 +150,41 @@ class AsyncNotifyRunnable : public Runna
 
  private:
   friend class ProgressTracker;
 
   RefPtr<ProgressTracker> mTracker;
   nsTArray<RefPtr<IProgressObserver>> mObservers;
 };
 
+ProgressTracker::MediumHighRunnable::MediumHighRunnable(
+    already_AddRefed<AsyncNotifyRunnable>&& aEvent)
+    : PrioritizableRunnable(std::move(aEvent),
+                            nsIRunnablePriority::PRIORITY_MEDIUMHIGH) {}
+
+void ProgressTracker::MediumHighRunnable::AddObserver(
+    IProgressObserver* aObserver) {
+  static_cast<AsyncNotifyRunnable*>(mRunnable.get())->AddObserver(aObserver);
+}
+
+void ProgressTracker::MediumHighRunnable::RemoveObserver(
+    IProgressObserver* aObserver) {
+  static_cast<AsyncNotifyRunnable*>(mRunnable.get())->RemoveObserver(aObserver);
+}
+
+/* static */
+already_AddRefed<ProgressTracker::MediumHighRunnable>
+ProgressTracker::MediumHighRunnable::Create(
+    already_AddRefed<AsyncNotifyRunnable>&& aEvent) {
+  MOZ_ASSERT(NS_IsMainThread());
+  RefPtr<ProgressTracker::MediumHighRunnable> event(
+      new ProgressTracker::MediumHighRunnable(std::move(aEvent)));
+  return event.forget();
+}
+
 void ProgressTracker::Notify(IProgressObserver* aObserver) {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (aObserver->NotificationsDeferred()) {
     // There is a pending notification, or the observer isn't ready yet.
     return;
   }
 
@@ -168,23 +193,21 @@ void ProgressTracker::Notify(IProgressOb
     LOG_FUNC_WITH_PARAM(gImgLog, "ProgressTracker::Notify async", "uri", image);
   }
 
   aObserver->MarkPendingNotify();
 
   // If we have an existing runnable that we can use, we just append this
   // observer to its list of observers to be notified. This ensures we don't
   // unnecessarily delay onload.
-  AsyncNotifyRunnable* runnable =
-      static_cast<AsyncNotifyRunnable*>(mRunnable.get());
-
-  if (runnable) {
-    runnable->AddObserver(aObserver);
+  if (mRunnable) {
+    mRunnable->AddObserver(aObserver);
   } else {
-    mRunnable = new AsyncNotifyRunnable(this, aObserver);
+    RefPtr<AsyncNotifyRunnable> ev = new AsyncNotifyRunnable(this, aObserver);
+    mRunnable = ProgressTracker::MediumHighRunnable::Create(ev.forget());
     mEventTarget->Dispatch(mRunnable, NS_DISPATCH_NORMAL);
   }
 }
 
 // A helper class to allow us to call SyncNotify asynchronously for a given,
 // fixed, state.
 class AsyncNotifyCurrentStateRunnable : public Runnable {
  public:
@@ -458,21 +481,18 @@ bool ProgressTracker::RemoveObserver(IPr
   // Observers can get confused if they don't get all the proper teardown
   // notifications. Part ways on good terms.
   if (removed && !aObserver->NotificationsDeferred()) {
     EmulateRequestFinished(aObserver);
   }
 
   // Make sure we don't give callbacks to an observer that isn't interested in
   // them any more.
-  AsyncNotifyRunnable* runnable =
-      static_cast<AsyncNotifyRunnable*>(mRunnable.get());
-
-  if (aObserver->NotificationsDeferred() && runnable) {
-    runnable->RemoveObserver(aObserver);
+  if (aObserver->NotificationsDeferred() && mRunnable) {
+    mRunnable->RemoveObserver(aObserver);
     aObserver->ClearPendingNotify();
   }
 
   return removed;
 }
 
 uint32_t ProgressTracker::ObserverCount() const {
   MOZ_ASSERT(NS_IsMainThread());
--- a/image/ProgressTracker.h
+++ b/image/ProgressTracker.h
@@ -203,18 +203,32 @@ class ProgressTracker : public mozilla::
   // Send some notifications that would be necessary to make |aObserver| believe
   // the request is finished downloading and decoding.  We only send
   // FLAG_LOAD_COMPLETE and FLAG_ONLOAD_UNBLOCKED, and only if necessary.
   void EmulateRequestFinished(IProgressObserver* aObserver);
 
   // Main thread only because it deals with the observer service.
   void FireFailureNotification();
 
+  // Wrapper for AsyncNotifyRunnable to make it have medium high priority like
+  // other imagelib runnables.
+  class MediumHighRunnable final : public PrioritizableRunnable {
+    explicit MediumHighRunnable(already_AddRefed<AsyncNotifyRunnable>&& aEvent);
+    virtual ~MediumHighRunnable() = default;
+
+   public:
+    void AddObserver(IProgressObserver* aObserver);
+    void RemoveObserver(IProgressObserver* aObserver);
+
+    static already_AddRefed<MediumHighRunnable> Create(
+        already_AddRefed<AsyncNotifyRunnable>&& aEvent);
+  };
+
   // The runnable, if any, that we've scheduled to deliver async notifications.
-  nsCOMPtr<nsIRunnable> mRunnable;
+  RefPtr<MediumHighRunnable> mRunnable;
 
   // mMutex protects access to mImage and mEventTarget.
   mutable Mutex mMutex;
 
   // mImage is a weak ref; it should be set to null when the image goes out of
   // scope.
   Image* mImage;
 
--- a/image/imgRequest.cpp
+++ b/image/imgRequest.cpp
@@ -1051,17 +1051,18 @@ imgRequest::OnDataAvailable(nsIRequest* 
       // Some property objects are not threadsafe, and we need to send
       // OnImageAvailable on the main thread, so finish on the main thread.
       if (!eventTarget) {
         MOZ_ASSERT(NS_IsMainThread());
         FinishPreparingForNewPart(result);
       } else {
         nsCOMPtr<nsIRunnable> runnable =
             new FinishPreparingForNewPartRunnable(this, std::move(result));
-        eventTarget->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
+        eventTarget->Dispatch(CreateMediumHighRunnable(runnable.forget()),
+                              NS_DISPATCH_NORMAL);
       }
     }
 
     if (!succeeded) {
       // Something went wrong; probably a content type issue.
       Cancel(NS_IMAGELIB_ERROR_FAILURE);
       return NS_BINDING_ABORTED;
     }