原文链接: node 使用 node-gyp 做 c++ 拓展 比原生js 计算fib快了近三倍

上一篇: 米哈游人工桌面YOYO鹿鸣

下一篇: multipass 尝鲜失败

参考

https://segmentfault.com/a/1190000023544791

由于bindings使用了node的fs等模块, 所以好像没办法在浏览器中使用...

安装依赖

yarn add  node-gyp -g

yarn add bindings
yarn add node-addon-api 


npm i -g node-gyp

npm i bindings -D
npm i node-addon-api -D

up-dbb6426740bff19971c8bafd5f1ffa790fa.png

window10  会比较麻烦点, 需要安装vs, 我实在不想装那玩意,算了吧

npm install --global --production windows-build-tools@4.0.0
choco upgrade python2 visualstudio2017-workload-vctools

up-98bd2793a1458bef638397871fa8bbd2244.png

add.cc

#include <napi.h>

Napi::Value Add(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();

  if (info.Length() < 2) {
    Napi::TypeError::New(env, "Wrong number of arguments")
        .ThrowAsJavaScriptException();
    return env.Null();
  }

  if (!info[0].IsNumber() || !info[1].IsNumber()) {
    Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
    return env.Null();
  }

  double arg0 = info[0].As<Napi::Number>().DoubleValue();
  double arg1 = info[1].As<Napi::Number>().DoubleValue();
  Napi::Number num = Napi::Number::New(env, arg0 + arg1);

  return num;
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
  exports.Set(Napi::String::New(env, "add"), Napi::Function::New(env, Add));
  return exports;
}

NODE_API_MODULE(add, Init)

binding.gyp

{
  "targets": [
    {
      "target_name": "add",
      "cflags!": [ "-fno-exceptions" ],
      "cflags_cc!": [ "-fno-exceptions" ],
      "sources": [ "add.cc" ],
      "include_dirs": [
        "<!@(node -p \"require('node-addon-api').include\")"
      ],
      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
    }
  ]
}

add.js

const { add } = require('bindings')('add.node')

console.log(add(1, 2))     // 3
console.log(add(0.1, 0.2)) // 熟悉的 0.3XXXXX

构建运行

node-gyp configure


node-gyp build

up-d737322f5f520b6891784de74a0686040b5.png

fib.cc

#include <napi.h>

int fibCc(int n){
  return n < 2 ? n : fibCc(n-1) + fibCc(n-2);
}
Napi::Value Fib(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();

  int n = info[0].As<Napi::Number>().Int32Value();
  Napi::Number num = Napi::Number::New(env, fibCc(n));

  return num;
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
  exports.Set(Napi::String::New(env, "fib"), Napi::Function::New(env, Fib));
  return exports;
}

NODE_API_MODULE(fib, Init)

binding.gyp

{
  "targets": [
    {
      "target_name": "fib",
      "cflags!": [ "-fno-exceptions" ],
      "cflags_cc!": [ "-fno-exceptions" ],
      "sources": [ "fib.cc" ],
      "include_dirs": [
        "<!@(node -p \"require('node-addon-api').include\")"
      ],
      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
    }
  ]
}

性能对比

居然快了近三倍???

up-742582ae7d6fd0e6488efc022f34f8dd352.png

const { fib } = require('bindings')('fib.node')
const fibJs = n => n < 2 ? n : fibJs(n - 1) + fibJs(n - 2)
for (let i = 0; i < 5; i++)
    console.log(i, fib(i), fibJs(i))
const count = 40
const jsStart = +new Date()
for (let i = 0; i < count; i++)
    fibJs(i)
const jsTime = +new Date() - jsStart

const ccStart = +new Date()
for (let i = 0; i < count; i++)
    fib(i)
const ccTime = +new Date() - ccStart

console.log('js', jsTime)
console.log('cc', ccTime, ccTime / jsTime, jsTime / ccTime)

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐