Closed
Bug 1370195
Opened 7 years ago
Closed 7 years ago
Try to use only one array allocation when calling bound function with many arguments
Categories
(Core :: JavaScript Engine, enhancement)
Core
JavaScript Engine
Tracking
()
RESOLVED
FIXED
mozilla55
Tracking | Status | |
---|---|---|
firefox55 | --- | fixed |
People
(Reporter: anba, Assigned: anba)
Details
Attachments
(1 file)
9.80 KB,
patch
|
anba
:
review+
till
:
feedback+
|
Details | Diff | Splinter Review |
We're currently allocating two arrays when invoking bound functions with many parameters (one array to copy the call arguments and another array to merge the bound with the call arguments).
Assignee | ||
Comment 1•7 years ago
|
||
|boundArgs| is an empty array for bind_bindFunction0, so we don't actually need to call bind_invokeFunctionN to merge the bound with the call arguments and instead we can directly call FUN_APPLY for the [[Call]] case resp. we only need to map the arguments to an array for [[Construct]]. This improves this µ-benchmark from 525ms to 80ms: var r = 0; var bf1 = function(a,b,c,d,e,f,g,h,){ return a+b+c+d+e+f+g+h }.bind(); var bf2 = function(a,b,c,d,e,f,g,h,){ return a+b+c+d+e+f+g+h }.bind(); var bf3 = function(a,b,c,d,e,f,g,h,){ return a+b+c+d+e+f+g+h }.bind(); var bf4 = function(a,b,c,d,e,f,g,h,){ return a+b+c+d+e+f+g+h }.bind(); var bf5 = function(a,b,c,d,e,f,g,h,){ return a+b+c+d+e+f+g+h }.bind(); var t = Date.now(); for (var i = 0; i < 1000000; ++i) { r += bf1(1,2,3,4,5,6,7,8,) r += bf2(1,2,3,4,5,6,7,8,) r += bf3(1,2,3,4,5,6,7,8,) r += bf4(1,2,3,4,5,6,7,8,) r += bf5(1,2,3,4,5,6,7,8,) } print(Date.now() - t); To avoid two array allocations for the other binder functions, I've added a nested combiner function expression, so we only need to create a single array when merging the bound with the call arguments. I've tried various approaches and this one seems to give a performance improvement when many arguments are present without regressing the performance numbers when only few arguments are used. For example when the combiner function was either directly written inline in the bound() function code or when a function declaration was used, I saw a noticeable performance regression (~25% in µ-benchmarks similar to the one above) when invoking or constructing the bound function. The lazily created function expression approach didn't lead to these performance regressions - at least for µ-benchmarks! This µ-benchmark improves from 645ms to 380ms: var r = 0; var bf1 = function(a,b,c,d,e,f,g,h,i,j){ return a+b+c+d+e+f+g+h+i+j }.bind(null, 1); var bf2 = function(a,b,c,d,e,f,g,h,i,j){ return a+b+c+d+e+f+g+h+i+j }.bind(null, 1); var bf3 = function(a,b,c,d,e,f,g,h,i,j){ return a+b+c+d+e+f+g+h+i+j }.bind(null, 1); var bf4 = function(a,b,c,d,e,f,g,h,i,j){ return a+b+c+d+e+f+g+h+i+j }.bind(null, 1); var bf5 = function(a,b,c,d,e,f,g,h,i,j){ return a+b+c+d+e+f+g+h+i+j }.bind(null, 1); var t = Date.now(); for (var i = 0; i < 1000000; ++i) { r += bf1(2,3,4,5,6,7,8,9,10) r += bf2(2,3,4,5,6,7,8,9,10) r += bf3(2,3,4,5,6,7,8,9,10) r += bf4(2,3,4,5,6,7,8,9,10) r += bf5(2,3,4,5,6,7,8,9,10) } print(Date.now() - t); And this one improves from 545ms to 400ms: var r = 0; var bf1 = function(a,b,c,d,e,f,g,h,i,j){ return a+b+c+d+e+f+g+h+i }.bind(null, 1,2,3); var bf2 = function(a,b,c,d,e,f,g,h,i,j){ return a+b+c+d+e+f+g+h+i }.bind(null, 1,2,3,4); var bf3 = function(a,b,c,d,e,f,g,h,i,j){ return a+b+c+d+e+f+g+h+i }.bind(null, 1,2,3,4,5); var bf4 = function(a,b,c,d,e,f,g,h,i,j){ return a+b+c+d+e+f+g+h+i }.bind(null, 1,2,3,4,5,6); var bf5 = function(a,b,c,d,e,f,g,h,i,j){ return a+b+c+d+e+f+g+h+i }.bind(null, 1,2,3,4,5,6,7); var t = Date.now(); for (var i = 0; i < 1000000; ++i) { r += bf1(4,5,6,7,8,9,) r += bf2(5,6,7,8,9,) r += bf3(6,7,8,9,) r += bf4(7,8,9,) r += bf5(8,9,) } print(Date.now() - t); Do you think this approach works out in practice outside of µ-benchmarks?
Attachment #8874410 -
Flags: feedback?(till)
Comment 2•7 years ago
|
||
Comment on attachment 8874410 [details] [diff] [review] bug1370195.patch Review of attachment 8874410 [details] [diff] [review]: ----------------------------------------------------------------- Great results, thanks! I do think that the approach should improve real-world .bind()-happy code, yes. It seems likely that the lazily allocated combiner function is the best solution because it'll not penalize the cases where it's not needed, but will enable inlining the combiner with ideal type information in those cases where it is needed. Does this need more work for some reason? If not, feel free to treat the f=me as an r=me and land away.
Attachment #8874410 -
Flags: feedback?(till) → feedback+
Assignee | ||
Comment 3•7 years ago
|
||
(In reply to Till Schneidereit [:till] from comment #2) > Comment on attachment 8874410 [details] [diff] [review] > bug1370195.patch > > Review of attachment 8874410 [details] [diff] [review]: > ----------------------------------------------------------------- > > Great results, thanks! I do think that the approach should improve > real-world .bind()-happy code, yes. It seems likely that the lazily > allocated combiner function is the best solution because it'll not penalize > the cases where it's not needed, but will enable inlining the combiner with > ideal type information in those cases where it is needed. > > Does this need more work for some reason? If not, feel free to treat the > f=me as an r=me and land away. No, it doesn't need any further work. I f? instead of r? just in case there's some gotcha which would make this patch a non-starter.
Assignee | ||
Comment 4•7 years ago
|
||
Comment on attachment 8874410 [details] [diff] [review] bug1370195.patch Adding r+ flag per comment #2.
Attachment #8874410 -
Flags: review+
Assignee | ||
Comment 5•7 years ago
|
||
Try: https://treeherder.mozilla.org/#/jobs?repo=try&revision=5c2f4711c9d7c5e898216a8a1a893dded9170aa5
Keywords: checkin-needed
Pushed by ryanvm@gmail.com: https://hg.mozilla.org/integration/mozilla-inbound/rev/dbedc1b9a3cc Use fewer array allocations when invoking bound functions with many arguments. r=till
Keywords: checkin-needed
Comment 7•7 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/dbedc1b9a3cc
Status: ASSIGNED → RESOLVED
Closed: 7 years ago
status-firefox55:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla55
You need to log in
before you can comment on or make changes to this bug.
Description
•