Bug 1620113 - part2 : replace nsTArray with LinkedList. r=chunmin
authoralwu <alwu@mozilla.com>
Thu, 26 Mar 2020 19:02:25 +0000
changeset 520626 d3f1873dfae9d4ab0386d0c5893bbe1a784d9cc1
parent 520625 2511ace99c5ee25e81c48749173b34b31eb2dfce
child 520627 1185f5a8daf848069785f9ac35216a2f2ef7174c
push id37254
push usernerli@mozilla.com
push dateFri, 27 Mar 2020 04:48:07 +0000
treeherdermozilla-central@2d758b42bd73 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerschunmin
bugs1620113
milestone76.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 1620113 - part2 : replace nsTArray with LinkedList. r=chunmin When we remove a controller from the list of controllers, which is a `nsTarray`, the array needs to be reconstructed if the removed controller is not the first or last element of the array. Eg. If we have a list of controllers, [A, B, C, ....., Z] and in some situation we would like to reoroder it to [A, C, D, ......, Z, B]. If we use nsTArray, then doing this kinds of reorder is expensive because it can't arbitrarily move the element back and forth, but the linked list can. So we replace the `nsTArray` with `LinkedList`, then this operation would become `O(1)` which could improve the performance Differential Revision: https://phabricator.services.mozilla.com/D66855
dom/media/mediacontrol/MediaControlService.cpp
dom/media/mediacontrol/MediaControlService.h
dom/media/mediacontrol/MediaController.h
--- a/dom/media/mediacontrol/MediaControlService.cpp
+++ b/dom/media/mediacontrol/MediaControlService.cpp
@@ -165,38 +165,40 @@ MediaControlService::ControllerManager::
     MediaControlService* aService)
     : mSource(aService->GetMediaControlKeysEventSource()) {
   MOZ_ASSERT(mSource);
 }
 
 bool MediaControlService::ControllerManager::AddController(
     MediaController* aController) {
   MOZ_DIAGNOSTIC_ASSERT(aController);
-  if (mControllers.Contains(aController)) {
+  if (mControllers.contains(aController)) {
     return false;
   }
-  mControllers.AppendElement(aController);
+  mControllers.insertBack(aController);
   UpdateMainController(aController);
   return true;
 }
 
 bool MediaControlService::ControllerManager::RemoveController(
     MediaController* aController) {
   MOZ_DIAGNOSTIC_ASSERT(aController);
-  if (!mControllers.Contains(aController)) {
+  if (!mControllers.contains(aController)) {
     return false;
   }
-  mControllers.RemoveElement(aController);
-  UpdateMainController(
-      mControllers.IsEmpty() ? nullptr : mControllers.LastElement().get());
+  // This is LinkedListElement's method which will remove controller from
+  // `mController`.
+  aController->remove();
+  UpdateMainController(mControllers.isEmpty() ? nullptr
+                                              : mControllers.getLast());
   return true;
 }
 
 void MediaControlService::ControllerManager::Shutdown() {
-  mControllers.Clear();
+  mControllers.clear();
   DisconnectMainControllerEvents();
 }
 
 void MediaControlService::ControllerManager::ControllerPlaybackStateChanged(
     MediaSessionPlaybackState aState) {
   MOZ_ASSERT(NS_IsMainThread());
   mSource->SetPlaybackState(aState);
   if (StaticPrefs::media_mediacontrol_testingevents_enabled()) {
@@ -260,13 +262,13 @@ void MediaControlService::ControllerMana
 }
 
 MediaController* MediaControlService::ControllerManager::GetMainController()
     const {
   return mMainController.get();
 }
 
 uint64_t MediaControlService::ControllerManager::GetControllersNum() const {
-  return mControllers.Length();
+  return mControllers.length();
 }
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/media/mediacontrol/MediaControlService.h
+++ b/dom/media/mediacontrol/MediaControlService.h
@@ -105,17 +105,17 @@ class MediaControlService final : public
     void ControllerPlaybackStateChanged(MediaSessionPlaybackState aState);
     void ControllerMetadataChanged(const MediaMetadataBase& aMetadata);
 
    private:
     void UpdateMainController(MediaController* aController);
     void ConnectToMainControllerEvents();
     void DisconnectMainControllerEvents();
 
-    nsTArray<RefPtr<MediaController>> mControllers;
+    LinkedList<RefPtr<MediaController>> mControllers;
     RefPtr<MediaController> mMainController;
 
     // These member are use to listen main controller's play state changes and
     // update the playback state to the event source.
     RefPtr<MediaControlKeysEventSource> mSource;
     MediaEventListener mPlayStateChangedListener;
     MediaEventListener mMetadataChangedListener;
   };
--- a/dom/media/mediacontrol/MediaController.h
+++ b/dom/media/mediacontrol/MediaController.h
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef DOM_MEDIA_MEDIACONTROL_MEDIACONTROLLER_H_
 #define DOM_MEDIA_MEDIACONTROL_MEDIACONTROLLER_H_
 
 #include "ContentMediaController.h"
 #include "MediaEventSource.h"
 #include "mozilla/dom/MediaSessionController.h"
+#include "mozilla/LinkedList.h"
 #include "nsDataHashtable.h"
 #include "nsISupportsImpl.h"
 
 namespace mozilla {
 namespace dom {
 
 class BrowsingContext;
 enum class MediaControlKeysEvent : uint32_t;
@@ -38,17 +39,19 @@ enum class MediaControlKeysEvent : uint3
  * in the tab, then we would say the controller is `playing`. If there is at
  * least one controlled media is playing and audible, then we would say the
  * controller is `audible`.
  *
  * Note that, if we don't enable audio competition, then we might have multiple
  * tabs playing media at the same time, we can use the ID to query the specific
  * controller from `MediaControlService`.
  */
-class MediaController final : public MediaSessionController {
+class MediaController final
+    : public MediaSessionController,
+      public LinkedListElement<RefPtr<MediaController>> {
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaController, override);
 
   explicit MediaController(uint64_t aContextId);
 
   void Play();
   void Pause();
   void Stop();