Skip to content

ffi: add V8 fast-call path#63140

Draft
bengl wants to merge 1 commit intonodejs:mainfrom
bengl:bengl/ffi-fastcalls
Draft

ffi: add V8 fast-call path#63140
bengl wants to merge 1 commit intonodejs:mainfrom
bengl:bengl/ffi-fastcalls

Conversation

@bengl
Copy link
Copy Markdown
Member

@bengl bengl commented May 6, 2026

HEADS UP: This likely isn't done yet. It's mainly here to compare approaches with @ShogunPanda.


Add a parallel dispatch path that uses V8 fast API calls instead of libffi for eligible native calls. At DynamicLibrary.getFunction time, generate a per-function JIT'd trampoline that strips V8's receiver argument and tail-calls the target. Signatures with callbacks, unsupported argument types, or more register-passed args than the platform ABI permits transparently fall back to libffi.

Stub emitters cover Linux/macOS/FreeBSD on x86_64 and AArch64, Windows on x86_64 and AArch64, and Linux on AArch32. JIT memory is allocated per isolate via direct mmap with MAP_JIT on macOS and W^X enforcement elsewhere. The JS wrapper validates each argument per declared type, mirroring the libffi slow callback so the contract is identical across both paths and across V8 optimization tiers.

The path is gated behind --experimental-ffi and can be disabled at build time with --without-ffi-fastcall. The previous shared-buffer JS fast path is removed, replaced by this fast-call path.


Some benchmarks:

                                   confidence improvement accuracy (*)     (**)    (***)
  ffi/add-f64.js n=10000000               ***    746.34 %      ±46.27%  ±64.21%  ±89.28%
  ffi/add-i32.js n=10000000               ***    807.83 %      ±44.39%  ±61.59%  ±85.62%
  ffi/getpid.js n=10000000                ***   1173.51 %     ±156.05% ±216.56% ±301.12%
  ffi/many-args.js n=10000000             ***    481.97 %       ±6.47%   ±8.96%  ±12.42%
  ffi/pointer-bigint.js n=10000000        ***    901.32 %      ±61.08%  ±84.75% ±117.82%
  ffi/sum-buffer.js n=10000000             **      9.51 %       ±5.38%   ±7.44%  ±10.28%
  

@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/ffi
  • @nodejs/gyp
  • @nodejs/startup
  • @nodejs/tsc

@nodejs-github-bot nodejs-github-bot added lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. labels May 6, 2026
Add a parallel dispatch path that uses V8 fast API calls instead of
libffi for eligible native calls. At DynamicLibrary.getFunction time,
generate a per-function JIT'd trampoline that strips V8's receiver
argument and tail-calls the target. Signatures with callbacks,
unsupported argument types, or more register-passed args than the
platform ABI permits transparently fall back to libffi.

Stub emitters cover Linux/macOS/FreeBSD on x86_64 and AArch64, Windows
on x86_64 and AArch64, and Linux on AArch32. JIT memory is allocated per
isolate via direct mmap with MAP_JIT on macOS and W^X enforcement
elsewhere. The JS wrapper validates each argument per declared type,
mirroring the libffi slow callback so the contract is identical across
both paths and across V8 optimization tiers.

The path is gated behind --experimental-ffi and can be disabled at
build time with --without-ffi-fastcall. The previous shared-buffer JS
fast path is removed, replaced by this fast-call path.

Signed-off-by: Bryan English <bryan@bryanenglish.com>
@bengl bengl force-pushed the bengl/ffi-fastcalls branch from a8f73a3 to 8c767ff Compare May 6, 2026 04:12
@ronag
Copy link
Copy Markdown
Member

ronag commented May 6, 2026

With this. How does ffi compare to napi? Do we have any guidelines in regards to when to use which?

@ShogunPanda
Copy link
Copy Markdown
Contributor

@ronag On my PR (which yields similar results as Bryan's) we're beating it by like 100x.

@ronag
Copy link
Copy Markdown
Member

ronag commented May 6, 2026

So ffi is 100x faster than napi?

@ShogunPanda
Copy link
Copy Markdown
Contributor

So ffi is 100x faster than napi?

Sorry, I thought you meant https://github.com/node-ffi-napi/node-ffi-napi.

We probably have to measure that once we agree on the direction.

@dmazzella
Copy link
Copy Markdown

So ffi is 100x faster than napi?

Sorry, I thought you meant https://github.com/node-ffi-napi/node-ffi-napi.

We probably have to measure that once we agree on the direction.

node-ffi-napi isn't a good benchmark for performance, but koffi is. Version 3 performs even better than version 2; it's still in beta (but can already be used for testing).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants