WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
217685
Cache JS arguments in AudioWorkletProcessor::process() for performance
https://bugs.webkit.org/show_bug.cgi?id=217685
Summary
Cache JS arguments in AudioWorkletProcessor::process() for performance
Chris Dumez
Reported
2020-10-13 17:07:10 PDT
Cache JS arguments in AudioWorkletProcessor::process() for performance.
Attachments
Patch
(11.42 KB, patch)
2020-10-13 17:19 PDT
,
Chris Dumez
ews-feeder
: commit-queue-
Details
Formatted Diff
Diff
Patch
(12.29 KB, patch)
2020-10-13 17:44 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(18.80 KB, patch)
2020-10-13 21:18 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Show Obsolete
(2)
View All
Add attachment
proposed patch, testcase, etc.
Chris Dumez
Comment 1
2020-10-13 17:19:18 PDT
Created
attachment 411282
[details]
Patch
Chris Dumez
Comment 2
2020-10-13 17:44:25 PDT
Created
attachment 411286
[details]
Patch
Darin Adler
Comment 3
2020-10-13 18:01:07 PDT
Comment on
attachment 411286
[details]
Patch I don’t understand why all these jsCast are safe. What guarantees the objects have the correct type?
Chris Dumez
Comment 4
2020-10-13 18:04:30 PDT
(In reply to Darin Adler from
comment #3
)
> Comment on
attachment 411286
[details]
> Patch > > I don’t understand why all these jsCast are safe. What guarantees the > objects have the correct type?
We construct those arrays ourselves and freeze before passing them to JavaScript. Since those are frozen arrays, the JS cannot modify them.
Sam Weinig
Comment 5
2020-10-13 18:11:29 PDT
Comment on
attachment 411286
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=411286&action=review
> Source/WebCore/ChangeLog:8 > + Cache JS arguments in AudioWorkletProcessor::process() for performance.
Got any numbers?
Geoffrey Garen
Comment 6
2020-10-13 20:18:18 PDT
Comment on
attachment 411286
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=411286&action=review
> Source/WebCore/Modules/webaudio/AudioWorkletProcessor.h:73 > + JSC::Strong<JSC::JSArray> m_jsInputs; > + JSC::Strong<JSC::JSArray> m_jsOutputs; > + JSC::Strong<JSC::JSObject> m_jsParamValues;
Is the AudioWorkletProcessor in scope in JavaScript somewhere in the worklet? If so, I believe that "Array.prototype.customProperty = audioWorkletProcessor" would be a retain cycle. Since this is just a cache, one alternative is to use JSC::Weak.
Chris Dumez
Comment 7
2020-10-13 20:36:05 PDT
(In reply to Geoffrey Garen from
comment #6
)
> Comment on
attachment 411286
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=411286&action=review
> > > Source/WebCore/Modules/webaudio/AudioWorkletProcessor.h:73 > > + JSC::Strong<JSC::JSArray> m_jsInputs; > > + JSC::Strong<JSC::JSArray> m_jsOutputs; > > + JSC::Strong<JSC::JSObject> m_jsParamValues; > > Is the AudioWorkletProcessor in scope in JavaScript somewhere in the > worklet? If so, I believe that "Array.prototype.customProperty = > audioWorkletProcessor" would be a retain cycle.
Yes, the processor is an object in JS. This is actually the process we call the process() function on in JS. I had thought about this potential leak issue but thought it could not happen because the arrays are frozen. I had not thought about setting a property on the prototype.
> Since this is just a cache, one alternative is to use JSC::Weak.
I did not use Weak because I don’t think it would work. What keeps the JS arrays alive if they are weak? There are constructed in c++ side and only passed in argument to the JS process() function. It is not expected or even common that the JS side will hold on to these arrays in between process() function calls. Do I need some kind of visitor maybe?
Chris Dumez
Comment 8
2020-10-13 20:39:01 PDT
(In reply to Sam Weinig from
comment #5
)
> Comment on
attachment 411286
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=411286&action=review
> > > Source/WebCore/ChangeLog:8 > > + Cache JS arguments in AudioWorkletProcessor::process() for performance. > > Got any numbers?
I checked that the cache is used most of the time since the topology rarely changes. As such, this avoids a lot of JS object allocations (since the process() function is called super frequently to process audio). Besides avoiding bad peaks of memory usage, this also means less GC. I don’t have actual CPU time numbers yet. I can probably get some tomorrow. I was personally satisfied with avoiding some many JS object allocations in the common case.
Yusuke Suzuki
Comment 9
2020-10-13 20:49:09 PDT
Comment on
attachment 411286
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=411286&action=review
>>> Source/WebCore/Modules/webaudio/AudioWorkletProcessor.h:73 >>> + JSC::Strong<JSC::JSObject> m_jsParamValues; >> >> Is the AudioWorkletProcessor in scope in JavaScript somewhere in the worklet? If so, I believe that "Array.prototype.customProperty = audioWorkletProcessor" would be a retain cycle. >> >> Since this is just a cache, one alternative is to use JSC::Weak. > > Yes, the processor is an object in JS. This is actually the process we call the process() function on in JS. I had thought about this potential leak issue but thought it could not happen because the arrays are frozen. I had not thought about setting a property on the prototype.
It is possible that this causes leaks even if this is frozen. For example, let map = new WeakMap; map.set(frozenArray, wrapperOfAudioWorkletProcessor); then, cyclic reference is created. I recommend using JSC::Weak, or JSValueInWrappedObject.
Chris Dumez
Comment 10
2020-10-13 20:51:10 PDT
Comment on
attachment 411286
[details]
Patch Ok. I will look into using JSValueInWrappedObject tomorrow. I see that it has a visit() function, I guess this is what I need to do to keep those arrays alive.
Chris Dumez
Comment 11
2020-10-13 21:18:37 PDT
Created
attachment 411297
[details]
Patch
Chris Dumez
Comment 12
2020-10-13 21:19:30 PDT
(In reply to Chris Dumez from
comment #10
)
> Comment on
attachment 411286
[details]
> Patch > > Ok. I will look into using JSValueInWrappedObject tomorrow. I see that it > has a visit() function, I guess this is what I need to do to keep those > arrays alive.
JSValueInWrappedObject is great, was super easy to use. I used to know about this class and then forgot about it. The latest patch iteration uses it.
Chris Dumez
Comment 13
2020-10-14 08:33:56 PDT
(In reply to Chris Dumez from
comment #8
)
> (In reply to Sam Weinig from
comment #5
) > > Comment on
attachment 411286
[details]
> > Patch > > > > View in context: > >
https://bugs.webkit.org/attachment.cgi?id=411286&action=review
> > > > > Source/WebCore/ChangeLog:8 > > > + Cache JS arguments in AudioWorkletProcessor::process() for performance. > > > > Got any numbers? > > I checked that the cache is used most of the time since the topology rarely > changes. As such, this avoids a lot of JS object allocations (since the > process() function is called super frequently to process audio). Besides > avoiding bad peaks of memory usage, this also means less GC. > > I don’t have actual CPU time numbers yet. I can probably get some tomorrow. > I was personally satisfied with avoiding some many JS object allocations in > the common case.
I tweaked imported/w3c/web-platform-tests/webaudio/the-audio-api/the-audioworklet-interface/simple-input-output.https.html to turn it into a perf test. I basically made the buffer very large and checked how long it takes to process the buffer. Note that the test has a fairly simple but common topology. Without optimization: ~23 seconds With optimization: ~15 seconds
Darin Adler
Comment 14
2020-10-14 11:27:26 PDT
(In reply to Chris Dumez from
comment #12
)
> JSValueInWrappedObject is great, was super easy to use. I used to know about > this class and then forgot about it. The latest patch iteration uses it.
One small editorial comment: When I originally added JSValueInWrappedObject, I also came up with a testing technique for verifying that reference cycles were not keeping objects alive. I suggest we add tests like that for these references. Let me know if you need a pointer to those tests so you can see the techniques they use.
Chris Dumez
Comment 15
2020-10-15 12:33:04 PDT
Comment on
attachment 411297
[details]
Patch Ping review? I think the performance results are pretty compelling and I have stopped using JSC::Strong.
Geoffrey Garen
Comment 16
2020-10-15 16:38:51 PDT
Comment on
attachment 411297
[details]
Patch r=me
EWS
Comment 17
2020-10-15 16:41:57 PDT
Committed
r268560
: <
https://trac.webkit.org/changeset/268560
> All reviewed patches have been landed. Closing bug and clearing flags on
attachment 411297
[details]
.
Radar WebKit Bug Importer
Comment 18
2020-10-15 16:42:26 PDT
<
rdar://problem/70357674
>
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug