Title: [274672] trunk/Source/WebCore
- Revision
- 274672
- Author
- [email protected]
- Date
- 2021-03-18 13:58:23 -0700 (Thu, 18 Mar 2021)
Log Message
Avoid heap allocation under BaseAudioContext::sourceNodeDidFinishPlayback()
https://bugs.webkit.org/show_bug.cgi?id=223461
Reviewed by Jer Noble.
BaseAudioContext::sourceNodeDidFinishPlayback() was appending to a m_finishedSourceNodes
Vector, which would cause heap allocations on the audio thread. To avoid such heap
allocations (which are bad for performance), we now set a "isFinishedSourceNode" flag
on the AudioNode. When BaseAudioContext::derefFinishedSourceNodes(), it relies on
this new isFinishedSourceNode flag instead of using the m_finishedSourceNodes Vector.
* Modules/webaudio/AudioNode.h:
(WebCore::AudioNode::isFinishedSourceNode const):
(WebCore::AudioNode::setIsFinishedSourceNode):
* Modules/webaudio/BaseAudioContext.cpp:
(WebCore::BaseAudioContext::~BaseAudioContext):
(WebCore::BaseAudioContext::uninitialize):
(WebCore::isFinishedSourceNode):
(WebCore::BaseAudioContext::derefFinishedSourceNodes):
(WebCore::BaseAudioContext::sourceNodeDidFinishPlayback):
* Modules/webaudio/BaseAudioContext.h:
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (274671 => 274672)
--- trunk/Source/WebCore/ChangeLog 2021-03-18 20:42:10 UTC (rev 274671)
+++ trunk/Source/WebCore/ChangeLog 2021-03-18 20:58:23 UTC (rev 274672)
@@ -1,3 +1,27 @@
+2021-03-18 Chris Dumez <[email protected]>
+
+ Avoid heap allocation under BaseAudioContext::sourceNodeDidFinishPlayback()
+ https://bugs.webkit.org/show_bug.cgi?id=223461
+
+ Reviewed by Jer Noble.
+
+ BaseAudioContext::sourceNodeDidFinishPlayback() was appending to a m_finishedSourceNodes
+ Vector, which would cause heap allocations on the audio thread. To avoid such heap
+ allocations (which are bad for performance), we now set a "isFinishedSourceNode" flag
+ on the AudioNode. When BaseAudioContext::derefFinishedSourceNodes(), it relies on
+ this new isFinishedSourceNode flag instead of using the m_finishedSourceNodes Vector.
+
+ * Modules/webaudio/AudioNode.h:
+ (WebCore::AudioNode::isFinishedSourceNode const):
+ (WebCore::AudioNode::setIsFinishedSourceNode):
+ * Modules/webaudio/BaseAudioContext.cpp:
+ (WebCore::BaseAudioContext::~BaseAudioContext):
+ (WebCore::BaseAudioContext::uninitialize):
+ (WebCore::isFinishedSourceNode):
+ (WebCore::BaseAudioContext::derefFinishedSourceNodes):
+ (WebCore::BaseAudioContext::sourceNodeDidFinishPlayback):
+ * Modules/webaudio/BaseAudioContext.h:
+
2021-03-18 Devin Rousso <[email protected]>
CSP headers can block default <video> controls
Modified: trunk/Source/WebCore/Modules/webaudio/AudioNode.h (274671 => 274672)
--- trunk/Source/WebCore/Modules/webaudio/AudioNode.h 2021-03-18 20:42:10 UTC (rev 274671)
+++ trunk/Source/WebCore/Modules/webaudio/AudioNode.h 2021-03-18 20:58:23 UTC (rev 274672)
@@ -191,6 +191,9 @@
ChannelInterpretation channelInterpretation() const { return m_channelInterpretation; }
virtual ExceptionOr<void> setChannelInterpretation(ChannelInterpretation);
+ bool isFinishedSourceNode() const { return m_isFinishedSourceNode; }
+ void setIsFinishedSourceNode() { m_isFinishedSourceNode = true; }
+
protected:
// Inputs and outputs must be created before the AudioNode is initialized.
void addInput();
@@ -248,6 +251,7 @@
bool m_isMarkedForDeletion { false };
bool m_isDisabled { false };
+ bool m_isFinishedSourceNode { false };
#if DEBUG_AUDIONODE_REFERENCES
static bool s_isNodeCountInitialized;
Modified: trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp (274671 => 274672)
--- trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp 2021-03-18 20:42:10 UTC (rev 274671)
+++ trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp 2021-03-18 20:58:23 UTC (rev 274672)
@@ -171,7 +171,6 @@
ASSERT(m_isStopScheduled);
ASSERT(m_nodesToDelete.isEmpty());
ASSERT(m_referencedSourceNodes.isEmpty());
- ASSERT(m_finishedSourceNodes.isEmpty());
ASSERT(m_automaticPullNodes.isEmpty());
if (m_automaticPullNodesNeedUpdating)
m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size());
@@ -244,7 +243,7 @@
AutoLocker locker(*this);
// This should have been called from handlePostRenderTasks() at the end of rendering.
// However, in case of lock contention, the tryLock() call could have failed in handlePostRenderTasks(),
- // leaving nodes in m_finishedSourceNodes. Now that the audio thread is gone, make sure we deref those nodes
+ // leaving nodes in m_referencedSourceNodes. Now that the audio thread is gone, make sure we deref those nodes
// before the BaseAudioContext gets destroyed.
derefFinishedSourceNodes();
}
@@ -575,14 +574,21 @@
return IIRFilterNode::create(scriptExecutionContext, *this, WTFMove(options));
}
+static bool isFinishedSourceNode(const AudioConnectionRefPtr<AudioNode>& node)
+{
+ return node->isFinishedSourceNode();
+}
+
void BaseAudioContext::derefFinishedSourceNodes()
{
ASSERT(isGraphOwner());
ASSERT(isAudioThread() || isAudioThreadFinished());
- for (auto& node : m_finishedSourceNodes)
- derefSourceNode(*node);
- m_finishedSourceNodes.clear();
+ if (!m_hasFinishedAudioSourceNodes)
+ return;
+
+ m_referencedSourceNodes.removeAllMatching(isFinishedSourceNode);
+ m_hasFinishedAudioSourceNodes = false;
}
void BaseAudioContext::refSourceNode(AudioNode& node)
@@ -1055,7 +1061,8 @@
{
ASSERT(isAudioThread());
- m_finishedSourceNodes.append(&node);
+ node.setIsFinishedSourceNode();
+ m_hasFinishedAudioSourceNodes = true;
}
void BaseAudioContext::workletIsReady()
Modified: trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.h (274671 => 274672)
--- trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.h 2021-03-18 20:42:10 UTC (rev 274671)
+++ trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.h 2021-03-18 20:58:23 UTC (rev 274672)
@@ -319,9 +319,9 @@
void workletIsReady();
// When source nodes begin playing, the BaseAudioContext keeps them alive inside m_referencedSourceNodes.
- // When the nodes stop playing, they get added to m_finishedSourceNodes. After each rendering quantum,
- // we call derefSourceNode() on every node in m_finishedSourceNodes since we no longer need to keep them
- // alive.
+ // When the nodes stop playing, a flag gets set on the AudioNode accordingly. After each rendering quantum,
+ // we call derefFinishedSourceNodes() to remove those nodes from m_referencedSourceNodes since we no longer
+ // need to keep them alive.
void refSourceNode(AudioNode&);
void derefSourceNode(AudioNode&);
@@ -350,9 +350,6 @@
Ref<AudioWorklet> m_worklet;
- // Only accessed in the audio thread.
- Vector<AudioNode*> m_finishedSourceNodes;
-
// Either accessed when the graph lock is held, or on the main thread when the audio thread has finished.
Vector<AudioConnectionRefPtr<AudioNode>> m_referencedSourceNodes;
@@ -412,6 +409,7 @@
AudioIOPosition m_outputPosition;
HashMap<String, Vector<AudioParamDescriptor>> m_parameterDescriptorMap;
+ bool m_hasFinishedAudioSourceNodes { false };
// These are cached per audio context for performance reasons. They cannot be
// static because they rely on the sample rate.
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes