Title: [276883] trunk/Source/WebCore
Revision
276883
Author
jer.no...@apple.com
Date
2021-05-02 09:04:25 -0700 (Sun, 02 May 2021)

Log Message

[Perf] Creation of many video elements slows over time
https://bugs.webkit.org/show_bug.cgi?id=225273

Reviewed by Eric Carlson.

In PerformanceTests/Media/VideoElementCreation.html, 1000 video elements are created
per test, and the test reports how long each batch of 1000 element took to create. A
typical run shows the amount of time to run each batch slows over time. The underlying
cause appears to be the cost it takes to iterate over each MediaElementSession inside
PlatformMediaSessionManager and subclasses.

Before a HTMLMediaElement has a src (or after it's emptied) there's no reason for its
MediaElementSession to be tracked by the PlatformMediaSessionManager. It can't play,
pause, be interrupted, or accept remote control commands. So PlatformMediaSession will
be changed so that it does not add itself to the list of its manager's sessions at
creation time; instead a new method, setActive(bool), is added and will be called at
an appropriate time by its clients, HTMLMediaElement and AudioContext.

HTMLMediaElement will activate its mediaSession just before creating its MediaPlayer
inside prepareForLoad() or loadNextSourceChild(), and will deactivate after tearing
down its MediaPlayer inside mediaLoadingFailed().

AudioContext will activate its mediaSession during its own initialization, and deactivate
inside close().

Before this change, on this machine, VideoElementCreation.html showed an incresing time
to video element creation, levelling out at ~400ms per 1000 elements.  After this change,
VideoElelementCreation.html shows a constant time to video element creation, averaging
between 4ms and 7ms per 1000 elements.

* Modules/webaudio/AudioContext.cpp:
(WebCore::AudioContext::close):
(WebCore::AudioContext::lazyInitialize):
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::prepareForLoad):
(WebCore::HTMLMediaElement::mediaLoadingFailed):
* platform/audio/PlatformMediaSession.cpp:
(WebCore::PlatformMediaSession::PlatformMediaSession):
(WebCore::PlatformMediaSession::~PlatformMediaSession):
(WebCore::PlatformMediaSession::setActive):
* platform/audio/PlatformMediaSession.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (276882 => 276883)


--- trunk/Source/WebCore/ChangeLog	2021-05-02 05:22:49 UTC (rev 276882)
+++ trunk/Source/WebCore/ChangeLog	2021-05-02 16:04:25 UTC (rev 276883)
@@ -1,3 +1,47 @@
+2021-05-02  Jer Noble  <jer.no...@apple.com>
+
+        [Perf] Creation of many video elements slows over time
+        https://bugs.webkit.org/show_bug.cgi?id=225273
+
+        Reviewed by Eric Carlson.
+
+        In PerformanceTests/Media/VideoElementCreation.html, 1000 video elements are created
+        per test, and the test reports how long each batch of 1000 element took to create. A
+        typical run shows the amount of time to run each batch slows over time. The underlying
+        cause appears to be the cost it takes to iterate over each MediaElementSession inside
+        PlatformMediaSessionManager and subclasses.
+
+        Before a HTMLMediaElement has a src (or after it's emptied) there's no reason for its
+        MediaElementSession to be tracked by the PlatformMediaSessionManager. It can't play,
+        pause, be interrupted, or accept remote control commands. So PlatformMediaSession will
+        be changed so that it does not add itself to the list of its manager's sessions at
+        creation time; instead a new method, setActive(bool), is added and will be called at
+        an appropriate time by its clients, HTMLMediaElement and AudioContext.
+
+        HTMLMediaElement will activate its mediaSession just before creating its MediaPlayer
+        inside prepareForLoad() or loadNextSourceChild(), and will deactivate after tearing
+        down its MediaPlayer inside mediaLoadingFailed().
+
+        AudioContext will activate its mediaSession during its own initialization, and deactivate
+        inside close().
+
+        Before this change, on this machine, VideoElementCreation.html showed an incresing time
+        to video element creation, levelling out at ~400ms per 1000 elements.  After this change,
+        VideoElelementCreation.html shows a constant time to video element creation, averaging
+        between 4ms and 7ms per 1000 elements.
+
+        * Modules/webaudio/AudioContext.cpp:
+        (WebCore::AudioContext::close):
+        (WebCore::AudioContext::lazyInitialize):
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::prepareForLoad):
+        (WebCore::HTMLMediaElement::mediaLoadingFailed):
+        * platform/audio/PlatformMediaSession.cpp:
+        (WebCore::PlatformMediaSession::PlatformMediaSession):
+        (WebCore::PlatformMediaSession::~PlatformMediaSession):
+        (WebCore::PlatformMediaSession::setActive):
+        * platform/audio/PlatformMediaSession.h:
+
 2021-05-01  Antti Koivisto  <an...@apple.com>
 
         Share style resolvers between author shadow trees with identical style

Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp (276882 => 276883)


--- trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp	2021-05-02 05:22:49 UTC (rev 276882)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp	2021-05-02 16:04:25 UTC (rev 276883)
@@ -190,6 +190,7 @@
     destination().close([this, activity = makePendingActivity(*this)] {
         setState(State::Closed);
         uninitialize();
+        m_mediaSession->setActive(false);
     });
 }
 
@@ -310,6 +311,7 @@
 
     BaseAudioContext::lazyInitialize();
     if (isInitialized()) {
+        m_mediaSession->setActive(true);
         if (state() != State::Running) {
             // This starts the audio thread. The destination node's provideInput() method will now be called repeatedly to render audio.
             // Each time provideInput() is called, a portion of the audio stream is rendered. Let's call this time period a "render quantum".

Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (276882 => 276883)


--- trunk/Source/WebCore/html/HTMLMediaElement.cpp	2021-05-02 05:22:49 UTC (rev 276882)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp	2021-05-02 16:04:25 UTC (rev 276883)
@@ -1136,6 +1136,7 @@
     if (!document().hasBrowsingContext())
         return;
 
+    mediaSession().setActive(true);
     createMediaPlayer();
 
     // 2 - Let pending tasks be a list of all tasks from the media element's media element event task source in one of the task queues.
@@ -1422,6 +1423,8 @@
         return;
     }
 
+    mediaSession().setActive(true);
+
     // Recreate the media player for the new url
     createMediaPlayer();
 
@@ -2227,6 +2230,7 @@
     logMediaLoadRequest(document().page(), String(), convertEnumerationToString(error), false);
 
     mediaSession().clientCharacteristicsChanged();
+    mediaSession().setActive(false);
 }
 
 void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state)

Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSession.cpp (276882 => 276883)


--- trunk/Source/WebCore/platform/audio/PlatformMediaSession.cpp	2021-05-02 05:22:49 UTC (rev 276882)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSession.cpp	2021-05-02 16:04:25 UTC (rev 276883)
@@ -137,12 +137,25 @@
     , m_logIdentifier(uniqueLogIdentifier())
 #endif
 {
-    manager.addSession(*this);
 }
 
 PlatformMediaSession::~PlatformMediaSession()
 {
-    if (m_manager)
+    setActive(false);
+}
+
+void PlatformMediaSession::setActive(bool active)
+{
+    if (m_active == active)
+        return;
+    m_active = active;
+
+    if (!m_manager)
+        return;
+
+    if (m_active)
+        m_manager->addSession(*this);
+    else
         m_manager->removeSession(*this);
 }
 

Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSession.h (276882 => 276883)


--- trunk/Source/WebCore/platform/audio/PlatformMediaSession.h	2021-05-02 05:22:49 UTC (rev 276882)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSession.h	2021-05-02 16:04:25 UTC (rev 276883)
@@ -62,6 +62,8 @@
 
     virtual ~PlatformMediaSession();
 
+    void setActive(bool);
+
     enum class MediaType : uint8_t {
         None = 0,
         Video,
@@ -220,6 +222,7 @@
     State m_stateToRestore { Idle };
     InterruptionType m_interruptionType { NoInterruption };
     int m_interruptionCount { 0 };
+    bool m_active { false };
     bool m_notifyingClient { false };
     bool m_isPlayingToWirelessPlaybackTarget { false };
     bool m_hasPlayedSinceLastInterruption { false };
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to