nodejs / performance

Node.js team focusing on performance
MIT License
377 stars 7 forks source link

Add support for V8 fast call #23

Open ronag opened 1 year ago

ronag commented 1 year ago

V8 has support for fast call from js to cpp which NodeJS currently does not implement.

ronag commented 1 year ago

https://source.chromium.org/chromium/chromium/src/+/main:v8/include/v8-fast-api-calls.h

joyeecheung commented 1 year ago

We actually use it in some places (https://github.com/nodejs/node/blob/be525d7d04ec839fd2bb47affef00bb3c1302aca/src/node_process_methods.cc#L471-L475), just not a lot

joyeecheung commented 1 year ago

I think the main reason that they aren't used a lot is this

 * By design, fast calls are limited by the following requirements, which
 * the embedder should enforce themselves:
 *   - they should not allocate on the JS heap;
 *   - they should not trigger JS execution.

And in many performance-critical bindings, we are either directly calling back from native to JS because that's just how the API works, or we need to invoke various kinds of hooks or make sure that process.nextTick() callbacks are processed. Or that we need to synthesize the return results as JS objects from native in a way that's cannot be easily worked around using AliasedStruct or AliasedBuffer. Though at least for APIs that are only calling native from JS without the need of a callback can certainly use more of the fast API calls.

ronag commented 1 year ago

Could napi support it?

joyeecheung commented 1 year ago

So far this has been a pretty V8 thing. If we no longer prioritize engine-agnosticism then I suppose yes?

anonrig commented 1 year ago

node_process_methods.cc uses fast api, and I believe it is the only place its used.

  SetFastMethod(ctx, object(), "hrtime", SlowNumber, &fast_number_);
  SetFastMethod(ctx, object(), "hrtimeBigInt", SlowBigInt, &fast_bigint_);
anonrig commented 1 year ago

Here's the list of fast_api calls Deno uses: https://github.com/search?q=repo%3Adenoland%2Fdeno+%23%5Bop%28fast%29%5D&type=code

This will be a good reference to where we can also do it. (Thanks to Deno team)

ronag commented 1 year ago

I think many of the Buffer calls could make use of it, e.g. indexOf.

tniessen commented 1 year ago

V8 has support for fast call from js to cpp which NodeJS currently does not implement.

As @joyeecheung pointed out, we do use them in some places. Aside from the restrictions that Joyee mentioned, there is also a significant maintenance burden: there is no guarantee that V8 will actually use the fast API call, it depends on various compiler heuristics and runtime data types, so we have to maintain both the regular and the fast API call variant of the same API. It also only really helps much when the overhead of crossing the JS/C++ boundary really is significant compared to the complexity of the C++ function itself.

anonrig commented 1 year ago

Newly committed to v8 repo https://github.com/v8/v8/commit/bc831f8ba33b79e2eb670faf1f84c4e39aeb0f9f

anonrig commented 1 year ago

I’ll be happy to help someone to write a documentation about this and open a pull request to Node repository.

krk commented 1 year ago

Hi @anonrig, I would like to work on this issue.

anonrig commented 1 year ago

I'm removing the performance-agenda label due to the open pull request.

One of the questions we (@ronag) had in the meeting was whether it is possible to add a function to NAPI to support v8 fast APIs. I need to find the right team for it, but let's investigate & ask if it's possible.

tniessen commented 1 year ago

I think, while it's possible, Node-API has so far tried not to be too V8-specific. Also, one of the main motivations behind Node-API is stability and ABI compatibility, and V8 APIs don't typically guarantee that. (Native addons can already use V8 APIs, including fast API calls, if they don't need stability guarantees.)

cc @nodejs/node-api

legendecas commented 1 year ago

Yes, new node-api must be validated that the api is agnostic towards the underlying JavaScript VM: https://github.com/nodejs/node/blob/main/doc/contributing/adding-new-napi-api.md -- i.e. it can be implemented on other JavaScript engines too, like other node-api implementations mentioned at https://github.com/nodejs/abi-stable-node/blob/doc/node-api-engine-bindings.md#node-api-bindings-for-other-runtimes.