[Webkit-unassigned] [Bug 222098] Regression: Raw AudioBufferSourceNode playback causes repeated crackling sound

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Fri May 28 08:37:52 PDT 2021


https://bugs.webkit.org/show_bug.cgi?id=222098

--- Comment #18 from Chris Dumez <cdumez at apple.com> ---
(In reply to Chris Dumez from comment #17)
> (In reply to Chris Dumez from comment #16)
> > It definitely seems there is a garbage collection issue here. When I start
> > playing, I see some calls to
> > AudioScheduledSourceNode::virtualHasPendingActivity(), which return false
> > and I see JS wrappers getting garbage collection. HOWEVER, after this
> > initial period, we go for an extended period of time without
> > AudioScheduledSourceNode::virtualHasPendingActivity() getting called (which
> > seems to indicate the JS wrapper aren't getting visited). Since the JS is
> > constructing JS wrappers very aggressively and since we are not collecting
> > them, the number of JS wrappers grows pretty quickly, once we reach ~12k-15k
> > JS wrappers, the audio quality starts to deteriorate and craters very
> > quickly. 
> > 
> > I could use some help from our GC experts here to understand why our nodes
> > aren't getting visited in a timely fashion, allowing the number of wrappers
> > to grow so quickly.
> 
> The visitor logic is in generated bindings code, here:
> ```
> bool
> JSAudioScheduledSourceNodeOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::
> Unknown> handle, void*, AbstractSlotVisitor& visitor, const char** reason)
> {
>     auto* jsAudioScheduledSourceNode =
> jsCast<JSAudioScheduledSourceNode*>(handle.slot()->asCell());
>     auto& wrapped = jsAudioScheduledSourceNode->wrapped();
>     if (!wrapped.isContextStopped() && wrapped.hasPendingActivity()) {
>         if (UNLIKELY(reason))
>             *reason = "ActiveDOMObject with pending activity";
>         return true;
>      }
>     if (jsAudioScheduledSourceNode->wrapped().isFiringEventListeners()) {
>         if (UNLIKELY(reason))
>             *reason = "EventTarget firing event listeners";
>         return true;
>     }
>     UNUSED_PARAM(visitor);
>     UNUSED_PARAM(reason);
>     return false;
> }
> ```

Thinking about this more, it may be acceptable from GC's point of view to not collect if the memory usage doesn't get too high. I think part of the issue may be that our WebAudio implementation relies on the AudioNodes's JS wrappers to get collected promptly to maintain performance. I suspect the issue may be that AudioScheduledSourceNodes don't break their connections to other nodes when finishing (until their ref count goes to 0, which cannot happen while the JS wrapper is alive). As a result, the audio graph becomes very large very quickly and we have to traverse this very large audio graph for every render quantum, thus the big perf hit.

I'll see if I can take the AudioScheduledSourceNode out of the graph as soon as it's finished playing.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-unassigned/attachments/20210528/fdc6ba4f/attachment.htm>


More information about the webkit-unassigned mailing list