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
Expose a faster way to create objects with properties for Node-API #45905
Comments
Dictionary mode happens when an object has too many properties. In that respect Instantiating an As a practical concern: support for JS engines other than V8 is a design goal of n-api and I don't think other engines have a concept that maps cleanly to |
Hmm, in my benchmark all the objects I created have exactly 2 properties. Did I misinterpret the profile (what MigrateToMap does)?
They must have some way of constructing an object with properties upfront through, similar to creating an object literal. And if not, the API could always fall back to constructing an object and assigning properties one by one internally. |
"Map" in V8 nomenclature is what other JS engines call "object shape" or "hidden class", it's a piece of metadata that describes the object's layout. It's used every time an object's layout changes (at least in C++ code), not just when switching from fast to slow mode.
Oh yeah, they probably do. I was thinking of lifetime issues. A It's probably not insurmountable but some upfront research is necessary. (I'm not volunteering!) |
|
I created a simple benchmark in this repo showing the difference between various methods. Each creates 100000 objects with 2 properties and appends them to an array. Even with ObjectTemplate, JS object literals are still significantly faster. |

Formed in 2009, the Archive Team (not to be confused with the archive.org Archive-It Team) is a rogue archivist collective dedicated to saving copies of rapidly dying or deleted websites for the sake of history and digital heritage. The group is 100% composed of volunteers and interested parties, and has expanded into a large amount of related projects for saving online and digital history.

devongovett commentedDec 19, 2022
•
edited
What is the problem this feature will solve?
At the moment, there are a few ways to create objects using the napi C APIs.
napi_create_object, and thennapi_set_named_propertyfor each property.napi_create_object, and usenapi_define_propertiesto set all properties at once (under the hood it still sets them one by one though).napi_define_class+napi_new_instance, and then add properties using one of the above methods. You can define accessors on the prototype, or primitive values but instance properties must be set the same way as above.In my use case I need to create a lot of small objects of the same shape. I've noticed in profiling that v8 functions under
napi_set_named_propertyare slow, specificallyv8::internal::JSObject::MigrateToMap. From my research in the v8 source code, this indicates that the object is transitioning from a fast struct/class-like object to a slower dictionary representation (I could be wrong here).I think v8 exposes
ObjectTemplateandFunctionTemplate->InstanceTemplatewhich are meant to help with this by defining the instance properties up front. This way, the object property slots can be allocated in the object itself rather than in a separate hash map. I found some useful info about v8 object representations here. I see that Node makes use ofObjectTemplatefor internal objects, and a previous issue nodejs/node-addon-api#1074 also found this to be the fastest way to create objects (though still not as fast as doing it in JS).My problem is that napi does not expose a way to create an object together with its properties, or a way to define a template for class instance properties. This means, as far as I can tell, all objects constructed through napi will end up in the slow dictionary mode, leading to slower perf when both constructing and accessing properties.
What is the feature you are proposing to solve the problem?
It would be awesome if node exposed a new
napi_create_object_with_propertiesfunction, which would accept a list of property descriptors likenapi_define_propertiesand allocate an object and assign properties all at once. This could potentially allow using faster v8 methods to create the object and assign properties so that it doesn't go into hashmap mode when adding properties one by one.Alternatively, a way to define an instance property template for classes would also work for me. For example,
napi_property_attributescould be extended with anapi_instanceattribute for defining properties on the instance template rather than the prototype template.What alternatives have you considered?
I'm not a node or v8 internal expert, just noticed that setting properties on objects seemed slower than expected, so I could be totally wrong about everything above. Opening this issue to get a conversation started. Totally open to other suggestions!
The text was updated successfully, but these errors were encountered: