-
Notifications
You must be signed in to change notification settings - Fork 30.5k
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
events: make eventNames() use Reflect.ownKeys() #5818
Conversation
Consistency really triggers my OCD.
'use strict';
const benchmark = require('benchmark');
const o = {};
for (var i = 0; i < 10000; i++) o[i] = i;
const suite = new benchmark.Suite;
suite.add('Object.getOwnPropertyNames()', function () {
Object.getOwnPropertyNames(o);
});
suite.add('Object.keys()', function () {
Object.keys(o);
});
suite.on('cycle', function (event) {
console.log(event.target.toString());
});
suite.on('complete', function () {
console.log('Fastest is '+ this.filter('fastest').map('name'));
});
suite.run();
|
Previous discussion in #5817. |
I'm +1 on this since it guarantees that the order of the properties returned is preserved between versions of v8. LGTM |
Also note that your benchmark isn't great because it measures only numeric properties. Not that it's a big issue IMO. |
Updated benchmark with: for (let i = 0; i < 10000; i++) {
o[i % 2 === 0 ? i : `foo${i}`] = i;
}
|
Wouldn't it make sense to just call
Your new benchmark is also really strange since it checks an object with 10K properties and (code in https://github.com/v8/v8/blob/master/src/builtins.cc ) |
Sounds good, I didn't know about |
I'm getting quite the opposite results when testing with this benchmark on master: 'use strict';
var common = require('../common.js');
var EventEmitter = require('events').EventEmitter;
var v8 = require('v8');
var bench = common.createBenchmark(main, {n: [50e4]});
function main(conf) {
var n = conf.n | 0;
var ee = new EventEmitter();
for (var k = 0; k < 1000; k += 1) {
ee.on('dummy' + k, function() {});
}
// Force optimization before starting the benchmark
ee.eventNames().length;
v8.setFlagsFromString('--allow_natives_syntax');
eval('%OptimizeFunctionOnNextCall(ee.eventNames)');
ee.eventNames().length;
bench.start();
for (var i = 0; i < n; i += 1) {
ee.eventNames().length;
}
bench.end(n);
} Results:
and with
|
Yeah those benchmarks look a lot more in line with what the code looks like, to be fair that benchmark isn't very indicative of real usage - where the results would mutate between calls and the optimization would not always work. |
Just to be on the same boat, I ran the bechmark on node 5.9.0. |
@lpinca node v5.x uses an older branch of v8 (4.6) whereas master uses 4.9 (and will use 5.0 when node v6 is released). So there could very well be changes that affected performance. |
Yes my bad for running it on 5.9.0, making it irrelevant. |
I get this using master:
|
@lpinca But did you try running the benchmark I posted? It's always best to verify changes like this end-to-end because it's not always easy to guess what v8 will do in certain circumstances or if the change will matter in the grand scheme of things. |
@mscdex yes I totally understand and with your benchmark I get your same results:
|
Use `Reflect.ownKeys()` instead of `Object.keys()` and `Object.getOwnPropertySymbols()`.
I've updated the pr to use |
@lpinca FWIW I get about the same amount of performance degradation using just |
@mscdex yeah, same here and ~100% is significant haha. Do whatever you think it's better with this. |
It doesn't make sense, it's too slow compared to the current implementation, so I close this. |
Why did you close the PR? The benchmark is skewed since .keys uses caching but in practice objects are mutated between calls.. |
@benjamingr reopened as #5822, I didn't see #5818 (comment). |
@benjamingr It's still a valid use case that I don't think is exactly uncommon and as such it's pretty hard to ignore that kind of regression. It might be a different story if the existing solution performs worse for a "mutated" |
The |
@mscdex to be clear - this is an entirely valid use case and I am not suggesting we ignore that kind of regression. I just didn't realize why it was closed before we talked about it and made sure the benchmark is good, and there is no way to fix it that's simple - but that has been clarified. Apologies if it sounded like I was presenting it as a non-issue. |
Pull Request check-list
Please make sure to review and check all of these items:
make -j8 test
(UNIX) orvcbuild test nosign
(Windows) pass withthis change (including linting)?
test (or a benchmark) included?
existing APIs, or introduces new ones)?
Affected core subsystem(s)
events
Description of change
Use
Reflect.ownKeys()
instead ofObject.keys()
andObject.getOwnPropertySymbols()
.