Node.js と Rust による native code のマーシャリング手法は NEON と node-ffi-napi の2種類が現時点で有力です。マーシャリング部分のコストの特徴を大雑把に掴むため雑なベンチマーキングをしました。
Note: 理論的にはもう1つ N-API を直接リンクして cdylib を out してもできますが、手間暇、標準化、実用性などから今回は人生のリソースを節約しました。
結果 2020-03-31 版
| pure | NEON | node-ffi-napi | |
|---|---|---|---|
| empty | 47.92550206 | 128.3124983 | 5800.287876 |
| rng | 35.47475487 | 175.1873791 | 5176.462751 |
| buffer | 175394.375 | 534.950003 | 59332.4 |
単位は [ns/function-call] です。
empty: 何もしない関数を何度も呼びつけて1回あたりのコストを算術平均で評価しています。rng:f32な unorm 値域の擬似乱数を何度も呼びつけて1回あたりのコストを算術平均で評価しています。buffer:ArrayBuffer(ES) またはBuffer(Node.js) を Node.js 側で生成し、単純な加算処理をその領域全域に適用する関数を何度も呼びつけて1回あたりのコストを算術平均で評価しています。
詳細は参考からソースを眺めて下さい。また、具体的な個々の数値だけを見てもあまり意味はありません。この結果からわかる事は:
- 軽量な処理しか行わないなら native code は必要ありません。寧ろ、 native code とのマーシャリングコストは native code によるメリットを大きく上回るかもしれません。
- 特別な事情が無い限り、 native code とのマーシャリングが必要な場合は
NEONをnode-ffi-napiより優先しましょう。 - もし
ArrayBuffer,Bufferのようなバッファーを操作する必要がある場合は native code を使うのが良い選択となる可能性がとても高いです。
マーシャリングコードのコストはNEONもnode-ffi-napiもやり方がわかっていれば同じくらいなので、よほど特別な状況が無ければ node-ffi-napi の出番は無さそうです。