-
Notifications
You must be signed in to change notification settings - Fork 30.1k
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
tls: replace forEach with for #15053
Conversation
d0bd60b
to
ab9ca09
Compare
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 this is CrackshaftScript...
Could you show a benchmark
I run a micro benchmark: > function A(arg) { global.arg = arg }
undefined
> var a = [1,2,3]
undefined
> console.time('of'); for (let i = 0; i < 1e8; ++i) {for (const i of a) A(i)};console.timeEnd('of')
of: 1808.680ms
undefined
> console.time('in'); for (let i = 0; i < 1e8; ++i) {for (const i in a) A(a[i])};console.timeEnd('in')
in: 36703.466ms
undefined
> console.time('in2'); for (let i = 0; i < 1e8; ++i) {for (const i in a) {const v = a[i]; A(v);} };console.timeEnd('in2')
in2: 36739.227ms
undefined
> console.time('forEach'); for (let i = 0; i < 1e8; ++i) { a.forEach((i) => A(i)) };console.timeEnd('forEach')
forEach: 10563.082ms That show a significant advantage for tl;drI would love to see some benchmarks |
another data point (removing the allocation of the iterator) > var j = 0
undefined
> console.time('in3'); for (let i = 0; i < 1e7; ++i) {for (const j in a) A(a[j]); };console.timeEnd('in3')
in3: 3683.538ms
undefined
> console.time('in3'); for (let i = 0; i < 1e7; ++i) {for (j in a) A(a[j]); };console.timeEnd('in3')
in3: 3748.282ms
undefined
> console.time('of'); for (let i = 0; i < 1e7; ++i) {for (v of a) A(v); };console.timeEnd('of')
of: 199.984ms
undefined TF&I seems like a crazy new world |
@refack Using a simple, ordinary for-loop is not "crankshaftscript." Secondly, we have an existing benchmark that compares these loops. Here is one run to give you some idea of how things currently perform in master (separated for better readability):
|
@bmeurer does this ^^^ makes sense, or are my micro-benchmarks over simplistic? |
FWIW these loops had been plain for-loops up until #14807, which was landed just recently, so it can be seen as a partial revert of that PR. |
I'm so sorry, I was sure I saw But I did add add the following benchmark: function forWithAssign(n, items, count) {
bench.start();
for (let i = 0; i < n; i++) {
for (let j = 0; j < count; j++) {
/* eslint-disable no-unused-vars */
var item = items[j];
/* esline-enable no-unused-vars */
}
}
bench.end(n / 1e6);
} to get:
So IMHO the variable assignment should be lowered into the loops. |
var ca = options.ca; | ||
if (ca !== undefined) { | ||
if (Array.isArray(ca)) { | ||
for (i = 0; i < ca.length; ++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.
nit: i
and val
should be lowered into this scope.
var cert = options.cert; | ||
if (cert !== undefined) { | ||
if (Array.isArray(cert)) { | ||
for (i = 0; i < cert.length; ++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.
nit: i
and val
should be lowered into this scope.
var passphrase = options.passphrase; | ||
if (key !== undefined) { | ||
if (Array.isArray(key)) { | ||
for (i = 0; i < key.length; ++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.
nit: i
and val
should be lowered into this scope.
|
@mscdex thanks for the reply. I gave my POV, and for this PR I believe that final style decisions should be made by the OP. |
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.
for...of
is optimized in TurboFan, can we use that instead @mscdex?
@benjamingr Did you see the benchmark results I posted above? |
|
Found it https://github.com/v8/v8/blob/master/src/compiler/js-builtin-reducer.cc#L208-L326 @bmeurer can you comment on why the benchmarks @mscdex is seeing (comparing for.. of vs. for) are showing slower results for for.. of in #15053 (comment) |
Come to think of it, even if |
@benjamingr our current microbenchmarks (#15053 (comment)) show that |
I'll clarify - I don't believe these benchmarks and am convinced |
@benjamingr ... it's entirely possible that the microbenchmarks are emphasizing the wrong thing. What would be helpful, however, is an improved benchmark that would give a more realistic, real world picture. I'll see if I can come up with one, but if you have a suggestion on that, it would be helpful! |
Landed in 5723c4c |
PR-URL: #15053 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
[academic discussion] > function A(arg) { global.arg = arg }
> var a = [1,2,3,4,5]
> console.time('of'); for (let i = 0; i < 1e8; ++i) {
for (const j of a) A(j);
};console.timeEnd('of')
of: 19053.156ms
> console.time('i+pow2'); for (let i = 0; i < 1e8; ++i) {
for (let j = 0; j < a.length; ++j) { const val = a[j]; A(val**2); }
};console.timeEnd('i+assign')
i+assign: 18272.780ms |
PR-URL: nodejs#15053 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
5723c4c was an unintentional breaking change in that it changed the behaviour of `tls.createSecureContext()` to throw on false-y input rather than ignoring it. This breaks real-world applications like `npm`. This restores the previous behaviour. Ref: nodejs#15053
Marking as don’t land for now since this is breaking, see #15131 |
PR-URL: nodejs/node#15053 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
5723c4c was an unintentional breaking change in that it changed the behaviour of `tls.createSecureContext()` to throw on false-y input rather than ignoring it. This breaks real-world applications like `npm`. This restores the previous behaviour. PR-URL: #15131 Ref: #15053 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com> Reviewed-By: MichaëZasso <targos@protonmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Timothy Gu <timothygu99@gmail.com> Reviewed-By: Brian White <mscdex@mscdex.net>
5723c4c was an unintentional breaking change in that it changed the behaviour of `tls.createSecureContext()` to throw on false-y input rather than ignoring it. This breaks real-world applications like `npm`. This restores the previous behaviour. PR-URL: nodejs#15131 Ref: nodejs#15053 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com> Reviewed-By: MichaëZasso <targos@protonmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Timothy Gu <timothygu99@gmail.com> Reviewed-By: Brian White <mscdex@mscdex.net>
CI: https://ci.nodejs.org/job/node-test-pull-request/9855/
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)