Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be faster to do
return slowToString.call(this, arguments[0], arguments[1], arguments[2]);? Or maybe passthisas the first argument and avoid.call()/.apply()altogether?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See this comment. The initial version called
slowToString(this, arguments[0], ...)but when I ran more benchmarks, it turned out that.apply()is faster by about 25-30% once the optimizing compiler kicks in.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't
function(encoding, start, end) {andreturn slowToString.apply(this, [encoding, start, end]);work here? There seems to be no reason to usearguments. Could you test that, please?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why create a new array every time when there is already
arguments?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, true, an array is slow.
In my local microbenchmark
function(encoding, start, end) {andreturn .call(this, encoding, start, end)wins for all number of arguments (except three, where.apply(this, arguments)is as fast).The problem with
return slowToString.call(this, arguments[0], arguments[1], arguments[2]);is inarguments, not in.call().There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. Can't get my test to perform accurately. Seems the true performance hit is using undefined
arguments[N]values. Welp, seems we have some cleaning up to do in places like: https://github.com/nodejs/io.js/blob/v2.3.0/src/node.js#L339-L350There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@trevnorris What do you mean cleaning up that particular section of code? That code is switching the arguments length and only passing that many arguments.
FWIW I already benchmarked various alternative function calling methods for this patch on top of the next branch (v8 4.3):
Replacing
apply()with.call(this, arguments[0], arguments[1], ...)slows down the cases when there are arguments passed, and there is a slight performance hit in the zero argument case (with apply I saw ~510% increase, but call showed ~470%).Replacing
apply()with a direct function call, passing in the context as an extra argument performs about the same as using.call().Replacing
apply()with a switch onarguments.lengthand using either.call()or passing the context in the < 3 cases (using.apply()as default), the zero argument case is a bit lower IIRC (~470% increase), but now the non-zero argument cases are no longer affected.So just using
.apply()instead of several-line switch is shorter and even a tad faster on the zero argument case. I haven't tested these scenarios on the master branch (v8 4.2) though.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mscdex Is
argsthere anargumentsobject or anArray? I'm aware that referencing undefined values on anargumentsobject does have significant overhead, but my benchmarks show that that is not the case for a real array.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@trevnorris I did not test with an array, just
arguments.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mscdex neither had I before this PR. Some testing showed that referencing undefined members in an array doesn't have any performance impact. Only side effect is the argument length being too long on the called function.