-
Notifications
You must be signed in to change notification settings - Fork 7
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
Class over raw object #113
Comments
There are multiple performance bottle necks at the same time.
const NullObject = function NullObject () { }
NullObject.prototype = Object.create(null) as it is by a magnitute faster than Actually it makes sense to use it for e.g. as QuerystringResult object,
|
I actually tested proto: null yesterday in relative depth and it does produce slower code and I found out why V8 uses a heuristic that assumes objects with proto: null are used as dictionaries so they're more prone to be dictionaries instead of hidden classes. Here is a screenshot of an object with two properties with the only difference being proto set to null |
Also closures aren't free and we should really avoid them more in hot paths |
Here's a small benchmark output of the impact of
|
@anonrig Can you try to do the trick of |
@H4ad I tried it in 2022 - nodejs/node#44627 |
The change in EE would need to have a more throughout anaylis over the large codebase. Our benchmarks that improves (https://github.com/nodejs/node/blob/3116c378d22b0afa420ea0f395049912792579da/benchmark/events/ee-add-remove.js#L26-L29), use the same events name making it better to optimize. If I recall correctly, we switched them to |
From what i can see null prototype objects are slow when created with function objectCreateNull() {
const events = {};
ObjectSetPrototypeOf(events, null);
return events;
} Which returns an object with null prototype that is optimized but i wonder how it compares with the following sample code when it comes to performance: function createNullPrototypeObject() {
const obj = {};
obj.__proto__ = null;
return obj;
} Both this methods return objects that are optimized by v8 and i think using one of them instead of |
It's not a matter of optimized vs. unoptimized really, dictionary mode is faster when you have many event types and One thing we can and probably should do is to pass a different kind of |
FYI, moving from objects to classes uses more memory (the number of fields in the class are higher than in object - verified in system analyzer) |
@rluvaton what do you mean ? With the following test: class A {
constructor(a, b) {
this.a = a;
this.b = b
}
}
function B(a, b) {
this.a = a;
this.b = b;
}
function objFactory(a, b) {
return {
a,
b,
}
}
function warmShapes() {
const a = new A(1, 2);
const b = new B(1, 2);
const c = objFactory(1, 2);
return [a, b, c];
}
for (let i = 0; i < 1e6; i++) {
warmShapes();
}
// logs: true true true
console.log(%HasFastProperties(new A(1, 2)), %HasFastProperties(new B(1,2)), %HasFastProperties(objFactory(1,2))); On v20.7.0 I see all shapes are the same same instance size (24) with similar stability and just a different prototype? |
That's a bit subjective. IIRC classes share the same function space in the memory, so if you create more than one object, classes won't use more memory than objects - in fact, objects may happen to be using more memory than classes. I conducted several experiments on this matter in the past. Although it may have changed, I highly doubt it. |
Oops, my bad my test was bad 😅 |
I checked the IR and the code and it's identical. Funnily looking over the code I also found the |
And because of the dictionary mode of I tried to replace timerListMap on Maybe we can search places where we use |
Nice finding. @mcollina |
It's a little bit more complicated than that. If an object is in dictionary mode, accessing all keys is slower in optimized functions. Deleting objects from the dictionary do not cause further slowdowns. |
I don't know if this is a pattern but:
pipeTo
node#49690All of these PRs improved performance by changing object creation to an instantiation of a class, this could not be the primary reason for the third PR but I think was the main reason for the first two PRs.
Should we look for more patterns like this?
The text was updated successfully, but these errors were encountered: