From 91e96a8da8aeb28ab39ab6a2642533956f58b648 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Tue, 3 May 2022 02:11:59 -0700 Subject: [PATCH] ffi overhead bench --- bench/ffi/plus100/README.md | 14 +++++++++++-- bench/ffi/plus100/download-napi-plus100.sh | 2 +- bench/ffi/plus100/package.json | 4 ++-- bench/ffi/plus100/plus100.bun.js | 23 +++++++++++++++------ bench/ffi/plus100/plus100.c | 4 +++- bench/ffi/plus100/plus100.deno.js | 14 ++++++++++--- bench/ffi/plus100/plus100.dylib | Bin 16778 -> 16810 bytes bench/ffi/plus100/plus100.napi.mjs | 12 ++++++++--- bun.lockb | Bin 7689 -> 8001 bytes src/javascript/jsc/api/ffi.zig | 2 +- 10 files changed, 56 insertions(+), 19 deletions(-) diff --git a/bench/ffi/plus100/README.md b/bench/ffi/plus100/README.md index 418e7bd343..954eaa607e 100644 --- a/bench/ffi/plus100/README.md +++ b/bench/ffi/plus100/README.md @@ -1,6 +1,6 @@ ## FFI overhead comparison -This compares the cost of a simple function call going from JavaScript to native code and back in: +This compares the cost of simple function calls going from JavaScript to native code and back in: - Bun v0.0.79 - napi.rs (Node v17.7.1) @@ -18,10 +18,20 @@ To run the benchmark: bun bench ``` +**add 100 to a number**: + | 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) +**function that does nothing**: + +| Overhead | Using | Version | Platform | +| -------- | ------- | ------- | --------------- | +| 3ns | bun:ffi | 0.0.79 | macOS (aarch64) | +| 15ns | napi.rs | 17.7.1 | macOS (aarch64) | +| 431ns | Deno | 1.21.1 | macOS (aarch64) | + +The native [functions](./plus100.c) called in Deno & Bun are the same. The function called with napi.rs is based on napi's official [package-template](https://github.com/napi-rs/package-template) in https://github.com/Jarred-Sumner/napi-plus100 diff --git a/bench/ffi/plus100/download-napi-plus100.sh b/bench/ffi/plus100/download-napi-plus100.sh index 9cd2268570..431fa88b35 100644 --- a/bench/ffi/plus100/download-napi-plus100.sh +++ b/bench/ffi/plus100/download-napi-plus100.sh @@ -1,7 +1,7 @@ #!/bin/bash rm -rf plus100-napi -git clone https://github.com/napi-rs/package-template plus100-napi --depth=1 +git clone https://github.com/Jarred-Sumner/napi-plus100 plus100-napi --depth=1 cd plus100-napi npm install npm run build diff --git a/bench/ffi/plus100/package.json b/bench/ffi/plus100/package.json index ba7ef1fd72..6ac5d60e0a 100644 --- a/bench/ffi/plus100/package.json +++ b/bench/ffi/plus100/package.json @@ -5,8 +5,8 @@ "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", + "bench-bun": "bun ./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" + "bench": "bun run bench-bun && bun run bench-napi && bun run bench-deno" } } diff --git a/bench/ffi/plus100/plus100.bun.js b/bench/ffi/plus100/plus100.bun.js index ca4bf0f643..3ddaff9753 100644 --- a/bench/ffi/plus100/plus100.bun.js +++ b/bench/ffi/plus100/plus100.bun.js @@ -1,19 +1,30 @@ import { run, bench, group, baseline } from "mitata"; -import { dlopen } from "bun:ffi"; +import { dlopen, suffix } from "bun:ffi"; const { - symbols: { plus100: plus100 }, + symbols: { + plus100: { native: plus100 }, + noop, + }, close, -} = dlopen("./plus100.dylib", { +} = dlopen(`./plus100.${suffix}`, { plus100: { - params: ["int32_t"], + args: ["int32_t"], returns: "int32_t", }, + noop: { + args: [], + }, }); -bench("plus100(1) (Bun FFI)", () => { +bench("plus100(1) ", () => { plus100(1); }); +bench("noop() ", () => { + noop(); +}); + // collect option collects benchmark returned values into array // prevents gc and can help with jit optimizing out functions -run({ collect: false, percentiles: true }); +await run({ collect: false, percentiles: true }); +console.log("\n"); diff --git a/bench/ffi/plus100/plus100.c b/bench/ffi/plus100/plus100.c index c5b7933ea8..bdecda7e02 100644 --- a/bench/ffi/plus100/plus100.c +++ b/bench/ffi/plus100/plus100.c @@ -2,5 +2,7 @@ #include int32_t plus100(int32_t a); - int32_t plus100(int32_t a) { return a + 100; } + +void noop(void); +void noop(void) {} \ No newline at end of file diff --git a/bench/ffi/plus100/plus100.deno.js b/bench/ffi/plus100/plus100.deno.js index e6104efdd5..83e4fc317f 100644 --- a/bench/ffi/plus100/plus100.deno.js +++ b/bench/ffi/plus100/plus100.deno.js @@ -1,18 +1,26 @@ import { run, bench, group, baseline } from "https://esm.sh/mitata"; const { - symbols: { plus100: plus100 }, + symbols: { plus100: plus100, noop }, close, } = Deno.dlopen("./plus100.dylib", { plus100: { parameters: ["i32"], result: "i32", }, + noop: { + parameters: [], + result: "void", + }, }); -bench("plus100(1) (Deno FFI)", () => { +bench("plus100(1) ", () => { plus100(1); }); +bench("noop() ", () => { + noop(); +}); + // collect option collects benchmark returned values into array // prevents gc and can help with jit optimizing out functions -run({ collect: false, percentiles: true }); +await run({ collect: false, percentiles: true }); diff --git a/bench/ffi/plus100/plus100.dylib b/bench/ffi/plus100/plus100.dylib index 030d1afef2060b383ea3af0d80cb090cdf8bab5e..7b5ec3962dd9d2f80ed7c872b53d22f7f786e74b 100755 GIT binary patch delta 374 zcmeBbW?a?GIH5yujXeVx@IWYrH4|sfXIjNLc^{+L+#e zCa+}_X9dYHP2R|4K8cA#VE50UM}Jq_K3?+d;*G-e-m8-(m=hW-OulL#7tX-Sz*LY^T5M=wz#x{F zpI^Wr&CIZ-o`IQROFfVV84Pg}KO+Of7N}Q1q98uZYYGhUV6E{mlNcsvIoPsJP+(%< znS7B^ZSo}t355t3**_Pq2c7P%%#6*8*e(1{qO8yR2D`$^*Ss&7c52_4%;o6daNo)< z;!xnd4u(JbMJ%SZzs=3H*?3eg`EQP!qL~AmOP6kd!{U7(T^;^ftj;>8zGqgvb?Q4V Qt(5hj7l!9G9bGU906|)8B>(^b delta 336 zcmZ40%-Ge;IH5yugFOQna6l-A4HIY1XY876$rvpu0Tf~aVh|nRz`(!=q!WO&z~r@z z;;bMZ1kT;_)ONBl{y4pZEAZR9AdSfqOa*ElK(!!aHGx@%udTbm!-ttmWw75MSWfYx3yi=~U^^HlETXkD?vl+pSH0E8k>rpH%p`X&L*z k-8)ipdvbP0_)nZw*b~ZCDKkl@e!Kj2S?jhr*JiH<0J}F`&;S4c diff --git a/bench/ffi/plus100/plus100.napi.mjs b/bench/ffi/plus100/plus100.napi.mjs index f4adda8d37..aa8d2636f8 100644 --- a/bench/ffi/plus100/plus100.napi.mjs +++ b/bench/ffi/plus100/plus100.napi.mjs @@ -2,9 +2,15 @@ import { bench, run } from "mitata"; import module from "module"; -const { plus100 } = module.createRequire(import.meta.url)("./plus100-napi"); +const { plus100, noop } = module.createRequire(import.meta.url)( + "./plus100-napi" +); -bench("plus100(1) (napi.rs)", () => { +bench("plus100(1) ", () => { plus100(1); }); -run({ collect: false, percentiles: true }); +bench("noop() ", () => { + noop(); +}); +await run({ collect: false, percentiles: true }); +console.log("\n"); diff --git a/bun.lockb b/bun.lockb index 4e2475280d2f03bea253d7496719f1b241af8e0c..b4fe117478ee1118262168a35b0440a1d4b1d48b 100755 GIT binary patch delta 1224 zcmeCQIcPUQPcz;lJm34ot+z|x^wp(pI=DPdT;{5svfaNIN9SrW>^YyiQjP%(BqxT; zGc6IGSh0g6H?t(MB$0t(vH|0PfLs@WQ|ihGbmyx!=xDd5Cf$iM2->8*vzPJy^Sz7= z0_(M2+-7D3n&7|sXG75~RtAU9H*!IIIDqmaoXo3h3Y1oZ(i%V-q+T0J>oG7Gfeq4!Dli1nAb?JT#0HhK^{$w_!eFJx<4=_m3ftf^3nP{83og5|k8>0WXjvhAaSN^8qm^wvYk;WJX{T3=mIS^>V0-y;{SHmR0DnUsX8Gzgb_7IYwI5-=80Gc3x zBno1J5;i}Ym=ur?@(D7Kp8OH$1_x0VOHh_U2C_g7C@hcxD8Gv!3jo>jlO08cxjLXh z_CjoOoTw7W_mk^IMS<}4|4D<{QHfxKoW#RGwISvRqWG6q8)`P^%WPTY(t{qT`g>svtWY#kR E0Pv2xSpWb4 delta 990 zcmX?T*J(3BPjiOS>ymwD+c{NcNW5p-8W175&7;lCO>gtDM%L~bq4oZSvJ7A#F)>`8 z>4DJ1iXD?J7!P>NS8dSIZcR#Nqc86W5UzDj1A#yiuO3OFak9Q?RnWybc>at zU`;_Thz|n>P=3VoCwmzgGUGOTFfCx2tiYZl$pTaY!c0KS22~EC87Iebh}ZJ~St3wT z5Dii#2BjsSv=opA*(D9c%s?y$<;w$Uka|TZtqi4Ap|m=X2C3JA(z-wzWR4yXgY+3d zq`(Xy7Xk*gb0Ohpuvw6E4f|wKLGQ^Ng1nP+1wAYp0ty^;;*vmK__Pw_X9)OERRoST zj}-;E*uNekpYWFQITa7?}k)B|!Q zGLW8ZC?+f?0~F#$76!5#Ko$YP9nr~2VoHLbR0T>v>_7|(6!FP(#k@H=py6|3a-x{> zWEt@TTtA>9H>4*&6IYuoAYrmOPGSuUmjK8PAPA6|EF!Bn*+bTWs{tyMDZ6=+?0QB3 DgGqXH diff --git a/src/javascript/jsc/api/ffi.zig b/src/javascript/jsc/api/ffi.zig index ce162f890a..6e659837eb 100644 --- a/src/javascript/jsc/api/ffi.zig +++ b/src/javascript/jsc/api/ffi.zig @@ -418,7 +418,7 @@ pub const FFI = struct { // var function var return_type = ABIType.@"void"; - if (value.get(global, "return_type")) |ret_value| brk: { + if (value.get(global, "returns")) |ret_value| brk: { if (ret_value.isAnyInt()) { const int = ret_value.toInt32(); switch (int) {