-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lib: copy arguments object instead of leaking it #4361
Conversation
@@ -85,7 +85,10 @@ Console.prototype.trace = function trace() { | |||
|
|||
Console.prototype.assert = function(expression) { | |||
if (!expression) { | |||
var arr = Array.prototype.slice.call(arguments, 1); | |||
var arr = []; |
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 not do new Array()
and copy the items like the previous changes?
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.
I thought it might look a little messy since there would need to be a couple - 1
s since the first item is being sliced off, but I agree it would be better to make it more similar to the other instances.
intuitively, asking the system to make extra copies does not seem to be the sort of programming that results in such speedup. of course the v8 compiler performs code transforms on our behalf as well as other robust forms of alchemy. I heard the arrow functions are an improvement on regular net.connect({port: 80, host: 'google.com'}, () => {}); can you point me to the benchmark code, I would like to check it out? |
@reqshark I'll admit that benchmark is a little sketchy. At first I tried making the benchmark asynchronous where I would use the callback to close the connection and then signal that the benchmark test was complete, but that caused a bunch of errors related to opening too many connections in a short amount of time. What I ended up doing is placing a return statement inside the net/tls.connect function to return before actually opening a connection and then just running that code that I provided. It's not an accurate benchmark. It's mainly just to show that there is some performance improvement. |
06019e0
to
abe2657
Compare
@woollybogger You are targeting the Perhaps using those would be better/faster than copying |
is this something we want to backport? If so using rest parameters would make that more difficult |
@thealphanerd Is there a reason not to use rest parameters in If rest parameters are good enough, those should be used in |
Rest parameters should turn this: Console.prototype.assert = function(expression) {
if (!expression) {
var argsLength = arguments.length || 1;
var arr = new Array(argsLength - 1);
for (var i = 1; i < argsLength; i++) {
arr[i - 1] = arguments[i];
}
require('assert').ok(false, util.format.apply(this, arr));
}
} into this: Console.prototype.assert = function(expression, ...arr) {
if (!expression) {
require('assert').ok(false, util.format.apply(this, arr));
}
} |
I thought rest parameters were still slow in v8? |
@mscdex In a single micro-benchmark, rest parameters are indeed about 2% slower than copying |
@mscdex Tested @woollybogger Disregard my previous comments about rest parameters for now, perhaps those will be good to use in some future v8 version. |
var args = new Array(argsLength); | ||
for (var i = 0; i < argsLength; i++) { | ||
args[i] = arguments[i]; | ||
} |
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.
While you're at it, I suggest just optimizing as much as possible:
https://gist.github.com/Fishrock123/98c35a0c745cb59d7496
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.
I thought traversing/setting arrays forwards was now faster than going backwards (see #3976)?
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.
I'm not sure about backwards vs. forwards, but generally I've seen that for loops are faster than while loops in V8. Take a look at this benchmark I just ran (I put some of my results in a comment at the bottom): https://gist.github.com/woollybogger/7364d4cf4599a1fc0ae7
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.
(It also just makes the statement smaller)
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.
The size of the statement really just depends on coding style. I could make it the same number of lines as the while loop if I changed it to this:
var argsLength = arguments.length;
var args = new Array(argsLength);
for (var i = 0; i < argsLength; i++) args[i] = arguments[i];
Would that style be preferable?
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.
IMHO I've always found that style (putting if
/loop/etc. bodies on the same line) less readable when visually scanning code, but I would suggest removing the braces for one line bodies.
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.
Alright, I'll remove the braces throughout the PR.
abe2657
to
ab61135
Compare
Marking as a watch for v4.x but we'll need to see how this ends up before landing it there. |
Are there 4 Windows test runs to show that at least one of them can pass? |
@woollybogger ... it's kind of like playing the powerball lottery, if you roll the dice and get all green, you win big! ... unfortunately there's some current wonkiness with the windows machines due to a number of issues (a bad commit that's being looked at + unrelated build machine failures). given that LTS is mostly green and the failures look unrelated, LGTM! |
Cool 👍 |
ab61135
to
3a9477e
Compare
Bump. Resolved merge conflicts. |
3a9477e
to
89d19b5
Compare
I completely rewrote my changes for assert.js and updated the benchmark results. |
@@ -608,10 +608,18 @@ ClientRequest.prototype.setTimeout = function(msecs, callback) { | |||
}; | |||
|
|||
ClientRequest.prototype.setNoDelay = function() { | |||
this._deferToConnect('setNoDelay', arguments); | |||
var argsLength = arguments.length; | |||
var args = new Array(argsLength); |
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.
minor nit: these can be const
now
LGTM with a nit |
Instead of leaking the arguments object by passing it as an argument to a function, copy it's contents to a new array, then pass the array. This allows V8 to optimize the function that contains this code, improving performance.
Notable changes: * **governance**: The following members have been added as collaborators: - Andreas Madsen (@AndreasMadsen) - Benjamin Gruenbaum (@benjamingr) - Claudio Rodriguez (@claudiorodriguez) - Glen Keane (@thekemkid) - Jeremy Whitlock (@whitlockjc) - Matt Loring (@matthewloring) - Phillip Johnsen (@phillipj) * **lib**: copy arguments object instead of leaking it (Nathan Woltman) #4361 * **src**: allow combination of -i and -e cli flags (Rich Trott) #5655 * **zlib**: add support for concatenated members (Kári Tristan Helgason) #5120 PR-URL: #5702
Notable changes: * **contextify**: Fixed a memory consumption issue related to heavy use of `vm.createContext` and `vm.runInNewContext`. (Ali Ijaz Sheikh) #5392 * **governance**: The following members have been added as collaborators: - Andreas Madsen (@AndreasMadsen) - Benjamin Gruenbaum (@benjamingr) - Claudio Rodriguez (@claudiorodriguez) - Glen Keane (@thekemkid) - Jeremy Whitlock (@whitlockjc) - Matt Loring (@matthewloring) - Phillip Johnsen (@phillipj) * **lib**: copy arguments object instead of leaking it (Nathan Woltman) #4361 * **src**: allow combination of -i and -e cli flags (Rich Trott) #5655 * **v8**: backport fb4ccae from v8 upstream (Vladimir Krivosheev) #4231 - breakout events from v8 to offer better support for external debuggers * **zlib**: add support for concatenated members (Kári Tristan Helgason) #5120 PR-URL: #5702
Notable changes: * **contextify**: Fixed a memory consumption issue related to heavy use of `vm.createContext` and `vm.runInNewContext`. (Ali Ijaz Sheikh) #5392 * **governance**: The following members have been added as collaborators: - Andreas Madsen (@AndreasMadsen) - Benjamin Gruenbaum (@benjamingr) - Claudio Rodriguez (@claudiorodriguez) - Glen Keane (@thekemkid) - Jeremy Whitlock (@whitlockjc) - Matt Loring (@matthewloring) - Phillip Johnsen (@phillipj) * **lib**: copy arguments object instead of leaking it (Nathan Woltman) #4361 * **src**: allow combination of -i and -e cli flags (Rich Trott) #5655 * **v8**: backport fb4ccae from v8 upstream (Vladimir Krivosheev) #4231 - breakout events from v8 to offer better support for external debuggers * **zlib**: add support for concatenated members (Kári Tristan Helgason) #5120 PR-URL: #5702
Instead of leaking the arguments object by passing it as an argument to a function, copy it's contents to a new array, then pass the array. This allows V8 to optimize the function that contains this code, improving performance. PR-URL: #4361 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Brian White <[email protected]>
Instead of leaking the arguments object by passing it as an argument to a function, copy it's contents to a new array, then pass the array. This allows V8 to optimize the function that contains this code, improving performance. PR-URL: #4361 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Brian White <[email protected]>
Notable Changes * https: - Under certain conditions ssl sockets may have been causing a memory leak when keepalive is enabled. This is no longer the case. - (Alexander Penev) #5713 * lib: - The way that we were internally passing arguments was causing a potential leak. By copying the arguments into an array we can avoid this - (Nathan Woltman) #4361 * repl: - Previously if you were using the repl in strict mode the column number would be wrong in a stack trace. This is no longer an issue. - (Prince J Wesley) #5416 PR-URL: #5961
Notable Changes * https: - Under certain conditions ssl sockets may have been causing a memory leak when keepalive is enabled. This is no longer the case. - (Alexander Penev) #5713 * lib: - The way that we were internally passing arguments was causing a potential leak. By copying the arguments into an array we can avoid this - (Nathan Woltman) #4361 * npm: - Upgrade to v2.15.1. (Forrest L Norvell) * repl: - Previously if you were using the repl in strict mode the column number would be wrong in a stack trace. This is no longer an issue. - (Prince J Wesley) #5416 PR-URL: #5961
Notable Changes * https: - Under certain conditions ssl sockets may have been causing a memory leak when keepalive is enabled. This is no longer the case. - (Alexander Penev) #5713 * lib: - The way that we were internally passing arguments was causing a potential leak. By copying the arguments into an array we can avoid this - (Nathan Woltman) #4361 * npm: - Upgrade to v2.15.1. Fixes a security flaw in the use of authentication tokens in HTTP requests that would allow an attacker to set up a server that could collect tokens from users of the command-line interface. Authentication tokens have previously been sent with every request made by the CLI for logged-in users, regardless of the destination of the request. This update fixes this by only including those tokens for requests made against the registry or registries used for the current install. (Forrest L Norvell) * repl: - Previously if you were using the repl in strict mode the column number would be wrong in a stack trace. This is no longer an issue. - (Prince J Wesley) #5416 PR-URL: #5961
Notable Changes * https: - Under certain conditions ssl sockets may have been causing a memory leak when keepalive is enabled. This is no longer the case. - (Alexander Penev) #5713 * lib: - The way that we were internally passing arguments was causing a potential leak. By copying the arguments into an array we can avoid this - (Nathan Woltman) #4361 * npm: - Upgrade to v2.15.1. Fixes a security flaw in the use of authentication tokens in HTTP requests that would allow an attacker to set up a server that could collect tokens from users of the command-line interface. Authentication tokens have previously been sent with every request made by the CLI for logged-in users, regardless of the destination of the request. This update fixes this by only including those tokens for requests made against the registry or registries used for the current install. (Forrest L Norvell) * repl: - Previously if you were using the repl in strict mode the column number would be wrong in a stack trace. This is no longer an issue. - (Prince J Wesley) #5416 PR-URL: #5961
Instead of leaking the arguments object by passing it as an argument to a function, copy it's contents to a new array, then pass the array. This allows V8 to optimize the function that contains this code, improving performance.
Benchmarks
Using benchmark.js
ClientRequest.setNoDelay / ClientRequest.setSocketKeepAlive
before: 15,286,485 ops/sec
after: 20,160,118 ops/sec
~33% faster
net.connect / tls.connect
before: 315,000 ops/sec
after: 345,000 ops/sec
~10% faster
code:
assert.throws
before:
98,403 ops/sec89,592 ops/secafter:
145,609 ops/sec146,464 ops/sec