C++ ときどき ごはん、わりとてぃーぶれいく☆

USAGI.NETWORKのなかのひとのブログ。主にC++。

Node.js & native code: NEON vs. node-ffi-napi vs. pure Node.js

Node.js と Rust による native code のマーシャリング手法は NEONnode-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] です。

  1. empty: 何もしない関数を何度も呼びつけて1回あたりのコストを算術平均で評価しています。
  2. rng: f32 な unorm 値域の擬似乱数を何度も呼びつけて1回あたりのコストを算術平均で評価しています。
  3. buffer: ArrayBuffer(ES) または Buffer(Node.js) を Node.js 側で生成し、単純な加算処理をその領域全域に適用する関数を何度も呼びつけて1回あたりのコストを算術平均で評価しています。

詳細は参考からソースを眺めて下さい。また、具体的な個々の数値だけを見てもあまり意味はありません。この結果からわかる事は:

  1. 軽量な処理しか行わないなら native code は必要ありません。寧ろ、 native code とのマーシャリングコストは native code によるメリットを大きく上回るかもしれません。
  2. 特別な事情が無い限り、 native code とのマーシャリングが必要な場合は NEONnode-ffi-napi より優先しましょう。
  3. もし ArrayBuffer, Buffer のようなバッファーを操作する必要がある場合は native code を使うのが良い選択となる可能性がとても高いです。

マーシャリングコードのコストはNEONnode-ffi-napiもやり方がわかっていれば同じくらいなので、よほど特別な状況が無ければ node-ffi-napi の出番は無さそうです。

参考