Bug 1273009 - Prune AudioParam events in the main thread when inserting new events. r=karlt
authorPaul Adenot <paul@paul.cx>
Wed, 29 Jun 2016 10:25:58 +0200
changeset 303712 3f7577ec0b2c407e6be478ee21a727b06cad468e
parent 303711 a706323c0073b7cd72dc0c41a6601a91f15dea9b
child 303713 b8f47976eb5aa814e28278ce5ab71d75b2ff5b57
push id79147
push userpaul@paul.cx
push dateTue, 05 Jul 2016 16:44:15 +0000
treeherdermozilla-inbound@3f7577ec0b2c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs1273009
milestone50.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 1273009 - Prune AudioParam events in the main thread when inserting new events. r=karlt Running the test-case in the bug, and profiling under OSX using Instruments' time profiler, the time spent in `AudioEventTimeline::ValidateEvent` was the highest Web Audio API-related function. This patch makes it disappear from the profile. We already use the same technique on the MSG thread to keep the number of events low. MozReview-Commit-ID: GJLPRWBh7nQ
dom/media/webaudio/AudioEventTimeline.cpp
dom/media/webaudio/AudioEventTimeline.h
dom/media/webaudio/AudioParam.cpp
dom/media/webaudio/AudioParam.h
--- a/dom/media/webaudio/AudioEventTimeline.cpp
+++ b/dom/media/webaudio/AudioEventTimeline.cpp
@@ -148,20 +148,17 @@ AudioEventTimeline::GetValuesAtTimeHelpe
   auto TimeOf = [](const AudioTimelineEvent& aEvent) -> TimeType {
     return aEvent.template Time<TimeType>();
   };
 
   size_t eventIndex = 0;
   const AudioTimelineEvent* previous = nullptr;
 
   // Let's remove old events except the last one: we need it to calculate some curves.
-  while (mEvents.Length() > 1 &&
-         aTime > TimeOf(mEvents[1])) {
-    mEvents.RemoveElementAt(0);
-  }
+  CleanupEventsOlderThan(aTime);
 
   for (size_t bufferIndex = 0; bufferIndex < aSize; ++bufferIndex, ++aTime) {
 
     bool timeMatchesEventIndex = false;
     const AudioTimelineEvent* next;
     for (; ; ++eventIndex) {
 
       if (eventIndex >= mEvents.Length()) {
--- a/dom/media/webaudio/AudioEventTimeline.h
+++ b/dom/media/webaudio/AudioEventTimeline.h
@@ -331,16 +331,25 @@ public:
   }
 
   // Return the number of events scheduled
   uint32_t GetEventCount() const
   {
     return mEvents.Length();
   }
 
+  template<class TimeType>
+  void CleanupEventsOlderThan(TimeType aTime)
+  {
+    while (mEvents.Length() > 1 &&
+        aTime > mEvents[1].template Time<TimeType>()) {
+      mEvents.RemoveElementAt(0);
+    }
+  }
+
 private:
   template<class TimeType>
   void GetValuesAtTimeHelper(TimeType aTime, float* aBuffer, const size_t aSize);
 
   template<class TimeType>
   float GetValuesAtTimeHelperInternal(TimeType aTime,
                                       const AudioTimelineEvent* aPrevious,
                                       const AudioTimelineEvent* aNext);
--- a/dom/media/webaudio/AudioParam.cpp
+++ b/dom/media/webaudio/AudioParam.cpp
@@ -158,16 +158,25 @@ AudioParam::SendEventToEngine(const Audi
                       aEvent.mDuration : aEvent.mTimeConstant);
 
   AudioNodeStream* stream = mNode->GetStream();
   if (stream) {
     stream->SendTimelineEvent(mIndex, aEvent);
   }
 }
 
+void
+AudioParam::CleanupOldEvents()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  double currentTime = mNode->Context()->CurrentTime();
+
+  CleanupEventsOlderThan(currentTime);
+}
+
 float
 AudioParamTimeline::AudioNodeInputValue(size_t aCounter) const
 {
   MOZ_ASSERT(mStream);
 
   // If we have a chunk produced by the AudioNode inputs to the AudioParam,
   // get its value now.  We use aCounter to tell us which frame of the last
   // AudioChunk to look at.
--- a/dom/media/webaudio/AudioParam.h
+++ b/dom/media/webaudio/AudioParam.h
@@ -211,18 +211,22 @@ private:
 
     if (!ValidateEvent(event, aRv)) {
       return;
     }
 
     AudioEventTimeline::InsertEvent<double>(event);
 
     SendEventToEngine(event);
+
+    CleanupOldEvents();
   }
 
+  void CleanupOldEvents();
+
   void SendEventToEngine(const AudioTimelineEvent& aEvent);
 
   void DisconnectFromGraphAndDestroyStream();
 
   nsCycleCollectingAutoRefCnt mRefCnt;
   NS_DECL_OWNINGTHREAD
   RefPtr<AudioNode> mNode;
   // For every InputNode, there is a corresponding entry in mOutputParams of the