Skip to content

Expose a faster way to create objects with properties for Node-API #45905

Open
@devongovett

Description

@devongovett

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 then napi_set_named_property for each property.
  • napi_create_object, and use napi_define_properties to set all properties at once (under the hood it still sets them one by one though).
  • use 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_property are slow, specifically v8::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 ObjectTemplate and FunctionTemplate->InstanceTemplate which 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 of ObjectTemplate for 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_properties function, which would accept a list of property descriptors like napi_define_properties and 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_attributes could be extended with a napi_instance attribute 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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestIssues that request new features to be added to Node.js.never-staleMark issue so that it is never considered stalenode-apiIssues and PRs related to the Node-API.

    Type

    No type

    Projects

    Status

    Awaiting Triage

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions