diff options
Diffstat (limited to 'bench')
| -rw-r--r-- | bench/ffi/ffi-overhead.js | 106 | ||||
| -rw-r--r-- | bench/ffi/noop.c | 6 | ||||
| -rwxr-xr-x | bench/ffi/noop.dylib | bin | 16759 -> 16759 bytes | |||
| -rw-r--r-- | bench/ffi/noop.js | 5 | ||||
| -rw-r--r-- | bench/ffi/plus100/.gitignore | 1 | ||||
| -rw-r--r-- | bench/ffi/plus100/README.md | 27 | ||||
| -rw-r--r-- | bench/ffi/plus100/download-napi-plus100.sh | 7 | ||||
| -rwxr-xr-x | bench/ffi/plus100/libadd.dylib | bin | 0 -> 396768 bytes | |||
| -rw-r--r-- | bench/ffi/plus100/package.json | 12 | ||||
| -rw-r--r-- | bench/ffi/plus100/plus100.bun.js | 19 | ||||
| -rw-r--r-- | bench/ffi/plus100/plus100.c | 6 | ||||
| -rw-r--r-- | bench/ffi/plus100/plus100.deno.js | 18 | ||||
| -rwxr-xr-x | bench/ffi/plus100/plus100.dylib | bin | 0 -> 16778 bytes | |||
| -rw-r--r-- | bench/ffi/plus100/plus100.napi.mjs | 10 |
14 files changed, 158 insertions, 59 deletions
diff --git a/bench/ffi/ffi-overhead.js b/bench/ffi/ffi-overhead.js index 841c59992..4f63cebe5 100644 --- a/bench/ffi/ffi-overhead.js +++ b/bench/ffi/ffi-overhead.js @@ -12,221 +12,221 @@ import { bench, group, run } from "mitata"; const types = { returns_true: { - return_type: "bool", + returns: "bool", args: [], }, returns_false: { - return_type: "bool", + returns: "bool", args: [], }, returns_42_char: { - return_type: "char", + returns: "char", args: [], }, // returns_42_float: { - // return_type: "float", + // returns: "float", // args: [], // }, // returns_42_double: { - // return_type: "double", + // returns: "double", // args: [], // }, returns_42_uint8_t: { - return_type: "uint8_t", + returns: "uint8_t", args: [], }, returns_neg_42_int8_t: { - return_type: "int8_t", + returns: "int8_t", args: [], }, returns_42_uint16_t: { - return_type: "uint16_t", + returns: "uint16_t", args: [], }, returns_42_uint32_t: { - return_type: "uint32_t", + returns: "uint32_t", args: [], }, // // returns_42_uint64_t: { - // // return_type: "uint64_t", + // // returns: "uint64_t", // // args: [], // // }, returns_neg_42_int16_t: { - return_type: "int16_t", + returns: "int16_t", args: [], }, returns_neg_42_int32_t: { - return_type: "int32_t", + returns: "int32_t", args: [], }, // returns_neg_42_int64_t: { - // return_type: "int64_t", + // returns: "int64_t", // args: [], // }, identity_char: { - return_type: "char", + returns: "char", args: ["char"], }, // identity_float: { - // return_type: "float", + // returns: "float", // args: ["float"], // }, identity_bool: { - return_type: "bool", + returns: "bool", args: ["bool"], }, // identity_double: { - // return_type: "double", + // returns: "double", // args: ["double"], // }, identity_int8_t: { - return_type: "int8_t", + returns: "int8_t", args: ["int8_t"], }, identity_int16_t: { - return_type: "int16_t", + returns: "int16_t", args: ["int16_t"], }, identity_int32_t: { - return_type: "int32_t", + returns: "int32_t", args: ["int32_t"], }, // identity_int64_t: { - // return_type: "int64_t", + // returns: "int64_t", // args: ["int64_t"], // }, identity_uint8_t: { - return_type: "uint8_t", + returns: "uint8_t", args: ["uint8_t"], }, identity_uint16_t: { - return_type: "uint16_t", + returns: "uint16_t", args: ["uint16_t"], }, identity_uint32_t: { - return_type: "uint32_t", + returns: "uint32_t", args: ["uint32_t"], }, // identity_uint64_t: { - // return_type: "uint64_t", + // returns: "uint64_t", // args: ["uint64_t"], // }, add_char: { - return_type: "char", + returns: "char", args: ["char", "char"], }, add_float: { - return_type: "float", + returns: "float", args: ["float", "float"], }, add_double: { - return_type: "double", + returns: "double", args: ["double", "double"], }, add_int8_t: { - return_type: "int8_t", + returns: "int8_t", args: ["int8_t", "int8_t"], }, add_int16_t: { - return_type: "int16_t", + returns: "int16_t", args: ["int16_t", "int16_t"], }, add_int32_t: { - return_type: "int32_t", + returns: "int32_t", args: ["int32_t", "int32_t"], }, // add_int64_t: { - // return_type: "int64_t", + // returns: "int64_t", // args: ["int64_t", "int64_t"], // }, add_uint8_t: { - return_type: "uint8_t", + returns: "uint8_t", args: ["uint8_t", "uint8_t"], }, add_uint16_t: { - return_type: "uint16_t", + returns: "uint16_t", args: ["uint16_t", "uint16_t"], }, add_uint32_t: { - return_type: "uint32_t", + returns: "uint32_t", args: ["uint32_t", "uint32_t"], }, does_pointer_equal_42_as_int32_t: { - return_type: "bool", + returns: "bool", args: ["ptr"], }, ptr_should_point_to_42_as_int32_t: { - return_type: "ptr", + returns: "ptr", args: [], }, identity_ptr: { - return_type: "ptr", + returns: "ptr", args: ["ptr"], }, // add_uint64_t: { - // return_type: "uint64_t", + // returns: "uint64_t", // args: ["uint64_t", "uint64_t"], // }, cb_identity_true: { - return_type: "bool", + returns: "bool", args: ["ptr"], }, cb_identity_false: { - return_type: "bool", + returns: "bool", args: ["ptr"], }, cb_identity_42_char: { - return_type: "char", + returns: "char", args: ["ptr"], }, // cb_identity_42_float: { - // return_type: "float", + // returns: "float", // args: ["ptr"], // }, // cb_identity_42_double: { - // return_type: "double", + // returns: "double", // args: ["ptr"], // }, cb_identity_42_uint8_t: { - return_type: "uint8_t", + returns: "uint8_t", args: ["ptr"], }, cb_identity_neg_42_int8_t: { - return_type: "int8_t", + returns: "int8_t", args: ["ptr"], }, cb_identity_42_uint16_t: { - return_type: "uint16_t", + returns: "uint16_t", args: ["ptr"], }, cb_identity_42_uint32_t: { - return_type: "uint32_t", + returns: "uint32_t", args: ["ptr"], }, // cb_identity_42_uint64_t: { - // return_type: "uint64_t", + // returns: "uint64_t", // args: ["ptr"], // }, cb_identity_neg_42_int16_t: { - return_type: "int16_t", + returns: "int16_t", args: ["ptr"], }, cb_identity_neg_42_int32_t: { - return_type: "int32_t", + returns: "int32_t", args: ["ptr"], }, // cb_identity_neg_42_int64_t: { - // return_type: "int64_t", + // returns: "int64_t", // args: ["ptr"], // }, return_a_function_ptr_to_function_that_returns_true: { - return_type: "ptr", + returns: "ptr", args: [], }, }; diff --git a/bench/ffi/noop.c b/bench/ffi/noop.c index 6b93beeaf..de15eb5e0 100644 --- a/bench/ffi/noop.c +++ b/bench/ffi/noop.c @@ -1,5 +1,5 @@ -// clang -O3 -shared -undefined dynamic_lookup ./noop.c -o noop.dylib +// clang -O3 -shared -mtune=native ./noop.c -o noop.dylib -int noop(); +void noop(); -int noop() { return 1; }
\ No newline at end of file +void noop() {}
\ No newline at end of file diff --git a/bench/ffi/noop.dylib b/bench/ffi/noop.dylib Binary files differindex 74a1d3155..66c00c17c 100755 --- a/bench/ffi/noop.dylib +++ b/bench/ffi/noop.dylib diff --git a/bench/ffi/noop.js b/bench/ffi/noop.js index e28ea0629..13c8aef28 100644 --- a/bench/ffi/noop.js +++ b/bench/ffi/noop.js @@ -6,11 +6,10 @@ const { } = dlopen("./noop.dylib", { noop: { args: [], - return_type: "i32", + returns: "void", }, }); -var raw = Object.keys(noop); bench("noop", () => { - raw(); + noop(); }); run({ collect: false, percentiles: true }); diff --git a/bench/ffi/plus100/.gitignore b/bench/ffi/plus100/.gitignore new file mode 100644 index 000000000..8911651ed --- /dev/null +++ b/bench/ffi/plus100/.gitignore @@ -0,0 +1 @@ +./napi-plus100 diff --git a/bench/ffi/plus100/README.md b/bench/ffi/plus100/README.md new file mode 100644 index 000000000..418e7bd34 --- /dev/null +++ b/bench/ffi/plus100/README.md @@ -0,0 +1,27 @@ +## FFI overhead comparison + +This compares the cost of a simple function call going from JavaScript to native code and back in: + +- Bun v0.0.79 +- napi.rs (Node v17.7.1) +- Deno v1.21.1 + +To set up: + +```bash +bun setup +``` + +To run the benchmark: + +```bash +bun bench +``` + +| Overhead | Using | Version | Platform | +| -------- | ------- | ------- | --------------- | +| 7ns | bun:ffi | 0.0.79 | macOS (aarch64) | +| 18ns | napi.rs | 17.7.1 | macOS (aarch64) | +| 580ns | Deno | 1.21.1 | macOS (aarch64) | + +The native [function](./plus100.c) called in Deno & Bun are the same. The function called with napi.rs is from napi's official [package-template](https://github.com/napi-rs/package-template) diff --git a/bench/ffi/plus100/download-napi-plus100.sh b/bench/ffi/plus100/download-napi-plus100.sh new file mode 100644 index 000000000..9cd226857 --- /dev/null +++ b/bench/ffi/plus100/download-napi-plus100.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +rm -rf plus100-napi +git clone https://github.com/napi-rs/package-template plus100-napi --depth=1 +cd plus100-napi +npm install +npm run build diff --git a/bench/ffi/plus100/libadd.dylib b/bench/ffi/plus100/libadd.dylib Binary files differnew file mode 100755 index 000000000..a2a1039ee --- /dev/null +++ b/bench/ffi/plus100/libadd.dylib diff --git a/bench/ffi/plus100/package.json b/bench/ffi/plus100/package.json new file mode 100644 index 000000000..ba7ef1fd7 --- /dev/null +++ b/bench/ffi/plus100/package.json @@ -0,0 +1,12 @@ +{ + "name": "plus100", + "scripts": { + "setup": "bun run napi-setup && bun run compile", + "bench-deno": "deno run --allow-ffi --unstable -A plus100.deno.js", + "napi-setup": "bash download-napi-plus100.sh", + "bench-napi": "node plus100.napi.mjs", + "bench-bun": "bun run ./plus100.bun.js", + "compile": "clang -mtune=native -O3 -shared ./plus100.c -o plus100.dylib", + "bench": "echo -e '\n--- Bun:\n' && bun run bench-bun && echo -e '\n--- Node:\n' && bun run bench-napi && echo -e '\n--- Deno:\n' && bun run bench-deno" + } +} diff --git a/bench/ffi/plus100/plus100.bun.js b/bench/ffi/plus100/plus100.bun.js new file mode 100644 index 000000000..ca4bf0f64 --- /dev/null +++ b/bench/ffi/plus100/plus100.bun.js @@ -0,0 +1,19 @@ +import { run, bench, group, baseline } from "mitata"; +import { dlopen } from "bun:ffi"; + +const { + symbols: { plus100: plus100 }, + close, +} = dlopen("./plus100.dylib", { + plus100: { + params: ["int32_t"], + returns: "int32_t", + }, +}); +bench("plus100(1) (Bun FFI)", () => { + plus100(1); +}); + +// collect option collects benchmark returned values into array +// prevents gc and can help with jit optimizing out functions +run({ collect: false, percentiles: true }); diff --git a/bench/ffi/plus100/plus100.c b/bench/ffi/plus100/plus100.c new file mode 100644 index 000000000..c5b7933ea --- /dev/null +++ b/bench/ffi/plus100/plus100.c @@ -0,0 +1,6 @@ +// clang -mtune=native -O3 -shared ./plus100.c -o plus100.dylib +#include <stdint.h> + +int32_t plus100(int32_t a); + +int32_t plus100(int32_t a) { return a + 100; } diff --git a/bench/ffi/plus100/plus100.deno.js b/bench/ffi/plus100/plus100.deno.js new file mode 100644 index 000000000..e6104efdd --- /dev/null +++ b/bench/ffi/plus100/plus100.deno.js @@ -0,0 +1,18 @@ +import { run, bench, group, baseline } from "https://esm.sh/mitata"; + +const { + symbols: { plus100: plus100 }, + close, +} = Deno.dlopen("./plus100.dylib", { + plus100: { + parameters: ["i32"], + result: "i32", + }, +}); +bench("plus100(1) (Deno FFI)", () => { + plus100(1); +}); + +// collect option collects benchmark returned values into array +// prevents gc and can help with jit optimizing out functions +run({ collect: false, percentiles: true }); diff --git a/bench/ffi/plus100/plus100.dylib b/bench/ffi/plus100/plus100.dylib Binary files differnew file mode 100755 index 000000000..030d1afef --- /dev/null +++ b/bench/ffi/plus100/plus100.dylib diff --git a/bench/ffi/plus100/plus100.napi.mjs b/bench/ffi/plus100/plus100.napi.mjs new file mode 100644 index 000000000..f4adda8d3 --- /dev/null +++ b/bench/ffi/plus100/plus100.napi.mjs @@ -0,0 +1,10 @@ +import { bench, run } from "mitata"; + +import module from "module"; + +const { plus100 } = module.createRequire(import.meta.url)("./plus100-napi"); + +bench("plus100(1) (napi.rs)", () => { + plus100(1); +}); +run({ collect: false, percentiles: true }); |
