Overview
This pages presents the execution time of Koffi calls on three benchmarks, where it is compared to a theoretical ideal FFI implementation (approximated with pre-compiled static Node-API glue code), and other FFI implementations:
- The first benchmark is based on
atoi()calls - The second benchmark is based on
memset()calls - The third benchmark is based on Raylib
Linux x86_64
The results presented below were measured on my x86_64 Linux machine (Intel® Core™ Ultra 9 185H).
atoi results for Linux x86_64
This test is based on atoi, which takes a string parameter. Javascript (V8) to C string conversion is relatively slow and heavy.
memset results for Linux x86_64
This test is based around repeated calls to the standard C function memset. All implementations pass a Node.js Buffer for the pointer argument.
Raylib results for Linux x86_64
This benchmark uses the CPU-based image drawing functions in Raylib. The calls are much heavier than in the atoi benchmark, thus the FFI overhead is reduced. In this implementation, Koffi is compared to:
- node-raylib (baseline): This is a native wrapper implemented with N-API
- Raylib C++: C++ implementation of the benchmark, without any Javascript
The node-raylib project seems to be somewhat abandoned as of 2026. It is based on an older version of Raylib than the other implentations. It could likely be slightly faster than Koffi with some effort and more build optimizations (such as PGO).
macOS ARM64
The results presented below were measured on an Apple Mac mini M2 hosted by Scaleway.
atoi results for macOS ARM64
This test is based on atoi, which takes a string parameter. Javascript (V8) to C string conversion is relatively slow and heavy.
memset results for macOS ARM64
This test is based around repeated calls to the standard C function memset. All implementations pass a Node.js Buffer for the pointer argument.
Windows x86_64
The results presented below were measured on my x86_64 Windows machine (AMD Ryzen™ 5 2600).
atoi results for Windows x86_64
This test is based on atoi, which takes a string parameter. Javascript (V8) to C string conversion is relatively slow and heavy.
memset results for Windows x86_64
This test is based around repeated calls to the standard C function memset. All implementations pass a Node.js Buffer for the pointer argument.
Raylib results for Windows x86_64
This benchmark uses the CPU-based image drawing functions in Raylib. The calls are much heavier than in the atoi benchmark, thus the FFI overhead is reduced. In this implementation, Koffi is compared to:
- node-raylib (baseline): This is a native wrapper implemented with N-API
- Raylib C++: C++ implementation of the benchmark, without any Javascript
The node-raylib project seems to be somewhat abandoned as of 2026. It is based on an older version of Raylib than the other implentations. It could likely be slightly faster than Koffi with some effort and more build optimizations (Clang instead of MSVC, PGO, etc.).
Running benchmarks
Please note that all benchmark results on this page are made with Clang-built binaries.
cd src/koffi
node ../cnoke/cnoke.js --clang --release
cd benchmark
node ../../cnoke/cnoke.js --clang --release
Once everything is built and ready, run:
node benchmark.js