Node.jsのN-APIをRustから使ってみた。

Node.jsにてRustのプログラムをffiしたいと思い、node-ffiを調べてみたが、しばらく更新されておらず、Node.js 12以降だと利用できない模様。

GitHub - node-ffi/node-ffi: Node.js Foreign Function Interface

RPCではない方法で他に連携する方法はないかと調べてみた結果Node.jsにはネイティブアドオンを作成するためのAPIが用意されているらしい。

nodejs.org

今回はこれをRustから利用できる形で提供してくれているnapi-rsを使用してみる。

github.com

今回検証する環境の各バージョン

  • Windows 10 1909
  • Node.js v14.15.0
    • napi-rs 0.3.9
  • Rust 1.47.0
    • napi 0.5.1
    • napi-derive 0.5.1
    • napi-build 0.2.1

napi-rsのドキュメントに従いcargo buildしてみたところ以下のエラーが発生

thread 'main' panicked at 'Unable to find libclang: "couldn\'t find any valid shared libraries matching: [\'clang.dll\', \'libclang.dll\'], set the LIBCLANG_PATH environment variable to a path where one of these files can be found (invalid: [])"'

clangが必要なようのでLLVMをインストール

今回インストールしたバージョンは11.0.0

The LLVM Compiler Infrastructure Project

他は特に問題なくcargo buildすることができた。

Node.jsからRustのfibonacci関数を呼び出すサンプル

github.com

Node.jsとRustのfibonacci関数を比較

 PASS  ./fib.test.js (14.479 s)
  √ fibonacci(30) for rust (3 ms)
  √ fibonacci(30) for js (16 ms)
  √ fibonacci(31) for rust (2 ms)
  √ fibonacci(31) for js (24 ms)
  √ fibonacci(32) for rust (3 ms)
  √ fibonacci(32) for js (39 ms)
  √ fibonacci(33) for rust (5 ms)
  √ fibonacci(33) for js (64 ms)
  √ fibonacci(34) for rust (13 ms)
  √ fibonacci(34) for js (102 ms)
  √ fibonacci(35) for rust (15 ms)
  √ fibonacci(35) for js (168 ms)
  √ fibonacci(36) for rust (26 ms)
  √ fibonacci(36) for js (263 ms)
  √ fibonacci(37) for rust (47 ms)
  √ fibonacci(37) for js (432 ms)
  √ fibonacci(38) for rust (68 ms)
  √ fibonacci(38) for js (701 ms)
  √ fibonacci(39) for rust (108 ms)
  √ fibonacci(39) for js (1119 ms)
  √ fibonacci(40) for rust (168 ms)
  √ fibonacci(40) for js (1828 ms)
  √ fibonacci(41) for rust (294 ms)
  √ fibonacci(41) for js (3061 ms)
  √ fibonacci(42) for rust (474 ms)
  √ fibonacci(42) for js (4855 ms)

Rust版のほうが概ね10倍程度は高速なようだ。 fibonacci関数は本来キャッシュすべきとか、Rust版は末尾再帰最適化がかかっているとかはあるがnapi-rsの検証が目的なのでパフォーマンスは次回以降にちゃんと検証したい。