Title: [274677] trunk/Source/WebCore
Revision
274677
Author
[email protected]
Date
2021-03-18 15:42:27 -0700 (Thu, 18 Mar 2021)

Log Message

Avoid heap allocation under AudioWorkletNode::process()
https://bugs.webkit.org/show_bug.cgi?id=223452

Reviewed by Darin Adler.

Always use arrays of size 128 (render quantum) for AudioParam values. We used to
dynamically choose between a size of 128 and 1 (when there is no automation
scheduled and the value is constant for the quantum). This avoids having to make
heap allocations on the audio thread, which are bad for performance.

Content (and existing AudioWorklet tests) can handle either size because the
specification says [1]:
"""
For each array, the array contains the computedValue of the parameter for all
frames in the render quantum. However, if no automation is scheduled during this
render quantum, the array MAY have length 1 with the array element being the
constant value of the AudioParam for the render quantum.
"""

Note that the specification uses "MAY" so this is not a requirement for us to use
an array of size 1 in such case. I also verified that Blink is never using an
array of size 1 either. They always use arrays of 128 (render quantum size) and
std::fill() them with the constant value when there is no automation. Our new
behavior is thus consistent with Blink.

[1] https://webaudio.github.io/web-audio-api/#audioworkletprocess-callback-parameters

* Modules/webaudio/AudioWorkletNode.cpp:
(WebCore::AudioWorkletNode::initializeAudioParameters):
(WebCore::AudioWorkletNode::process):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (274676 => 274677)


--- trunk/Source/WebCore/ChangeLog	2021-03-18 22:24:49 UTC (rev 274676)
+++ trunk/Source/WebCore/ChangeLog	2021-03-18 22:42:27 UTC (rev 274677)
@@ -1,3 +1,36 @@
+2021-03-18  Chris Dumez  <[email protected]>
+
+        Avoid heap allocation under AudioWorkletNode::process()
+        https://bugs.webkit.org/show_bug.cgi?id=223452
+
+        Reviewed by Darin Adler.
+
+        Always use arrays of size 128 (render quantum) for AudioParam values. We used to
+        dynamically choose between a size of 128 and 1 (when there is no automation
+        scheduled and the value is constant for the quantum). This avoids having to make
+        heap allocations on the audio thread, which are bad for performance.
+
+        Content (and existing AudioWorklet tests) can handle either size because the
+        specification says [1]:
+        """
+        For each array, the array contains the computedValue of the parameter for all
+        frames in the render quantum. However, if no automation is scheduled during this
+        render quantum, the array MAY have length 1 with the array element being the
+        constant value of the AudioParam for the render quantum.
+        """
+
+        Note that the specification uses "MAY" so this is not a requirement for us to use
+        an array of size 1 in such case. I also verified that Blink is never using an
+        array of size 1 either. They always use arrays of 128 (render quantum size) and
+        std::fill() them with the constant value when there is no automation. Our new
+        behavior is thus consistent with Blink.
+
+        [1] https://webaudio.github.io/web-audio-api/#audioworkletprocess-callback-parameters
+
+        * Modules/webaudio/AudioWorkletNode.cpp:
+        (WebCore::AudioWorkletNode::initializeAudioParameters):
+        (WebCore::AudioWorkletNode::process):
+
 2021-03-18  Rob Buis  <[email protected]>
 
         Protect frame before calling setPrinting

Modified: trunk/Source/WebCore/Modules/webaudio/AudioWorkletNode.cpp (274676 => 274677)


--- trunk/Source/WebCore/Modules/webaudio/AudioWorkletNode.cpp	2021-03-18 22:24:49 UTC (rev 274676)
+++ trunk/Source/WebCore/Modules/webaudio/AudioWorkletNode.cpp	2021-03-18 22:42:27 UTC (rev 274677)
@@ -173,7 +173,7 @@
     }
 
     for (auto& parameterName : m_parameters->map().keys())
-        m_paramValuesMap.add(parameterName, makeUnique<AudioFloatArray>());
+        m_paramValuesMap.add(parameterName, makeUnique<AudioFloatArray>(AudioUtilities::renderQuantumSize));
 }
 
 void AudioWorkletNode::setProcessor(RefPtr<AudioWorkletProcessor>&& processor)
@@ -208,15 +208,11 @@
     for (auto& audioParam : m_parameters->map().values()) {
         auto* paramValues = m_paramValuesMap.get(audioParam->name());
         ASSERT(paramValues);
-        if (audioParam->hasSampleAccurateValues() && audioParam->automationRate() == AutomationRate::ARate) {
-            paramValues->resize(framesToProcess);
+        RELEASE_ASSERT(paramValues->size() >= framesToProcess);
+        if (audioParam->hasSampleAccurateValues() && audioParam->automationRate() == AutomationRate::ARate)
             audioParam->calculateSampleAccurateValues(paramValues->data(), framesToProcess);
-        } else {
-            // If no automation is scheduled during this render quantum, the array may have length 1
-            // with the array element being the constant value of the AudioParam for the render quantum.
-            paramValues->resize(1);
-            *paramValues->data() = audioParam->finalValue();
-        }
+        else
+            std::fill_n(paramValues->data(), framesToProcess, audioParam->finalValue());
     }
 
     bool threwException = false;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to