为了账号安全,请及时绑定邮箱和手机立即绑定

基于C++和Rust两种方式扩展nodejs对比

标签:
C++

C++ 方式

  1. npm install node-gyp -g

  2. mkdir demo && cd Demo &&  npm init

  3. 创建 fib.cc

  4. 创建binding.gyp

  5. node-gyp configure build

  6. 创建 测试 index.js 文件

node-gyp https://github.com/nodejs/nod...

为了测试性能对比,算法用了斐波那契的递归实现。
fib.cc:

// addon.cc
#include <node.h>

namespace demo {    using v8::Exception;
    using v8::FunctionCallbackInfo;
    using v8::Isolate;
    using v8::Local;
    using v8::Number;
    using v8::Object;
    using v8::String;
    using v8::Value;

    
    unsigned int Fib_Recursive(unsigned int fib) {
        if (fib > 2) {
            return (Fib_Recursive(fib - 1) + Fib_Recursive(fib - 2));
        }
        else if (2 == fib) {
            return 1;
        }
        else if (1 == fib) {
            return 1;
        }
        return 1;
    }

    void Fib(const FunctionCallbackInfo<Value>& args) {
        Isolate* isolate = args.GetIsolate();
       

        if (!args[0]->IsNumber()) {
            isolate->ThrowException(Exception::TypeError(
                String::NewFromUtf8(isolate, "Wrong arguments")));
            return;
        }

        int value = Fib_Recursive(args[0]->NumberValue());
        Local<Number> num = Number::New(isolate, value);

        args.GetReturnValue().Set(num);
    }

    void Init(Local<Object> exports) {
        NODE_SET_METHOD(exports, "fib", Fib);
    }

    NODE_MODULE(Fib, Init)
}  // namespace demo

bing.gyp:

{
    "targets": [
        {
            "target_name": "fib",
            "sources": [ "fib.cc" ]
        }
    ]
}

nodejs 引用使用:

const Fib = require('./build/Release/fib');
// js
console.time('c++')
console.log(Fib.fib(40)); // 'world
console.timeEnd('c++')


function fib(n) {
  if (n === 1 || n === 2) {
    return 1
  }
  return fib(n - 1) + fib(n - 2)
}

function fib2(n) { 
    if (n < 2) { 
        return 1; 
    } 
    var a = 1, b = 1; 
    for (var i = 2; i < n - 1 ;i++ ) { 
        b = a + b; 
        a = b - a; 
    } 
    return a + b; 
}


// js
console.time('node')
console.log(fib(40))
console.timeEnd('node')

console.log(process.memoryUsage());

最后执行 node index.js 输出

102334155
c++: 273.243ms102334155node: 1081.281ms
{ rss: 22708224,
  heapTotal: 7159808,
  heapUsed: 4478104,
  external: 8236 }

注释掉c++代码再次执行 输出:

node: 1037.292ms
{ rss: 22581248,
  heapTotal: 7159808,
  heapUsed: 4457040,
  external: 8236 }

这个主要看c++代码的内存使用情况: 4457040 - 4478104 = 20k。
整体性能提高很多,消耗内存较少。

基于Rust扩展

Rust语言特点:
优点:

  • AOT编译器

  • 没有垃圾收集器

  • 内存安全默认

  • 编译的可执行文件性能类似于C ++

  • 具有依赖关系管理的包管理器

  • Packages host

  • 更好的社区

  • 比C++写起来容易

缺点:

  • 入门曲线非常陡峭,足以让很多人望而却步

  • 对编程意识要求较高,要能主动分辨去除可能会出现的同时读写的变量的情况,否则编译不会通过

  • 虽然官方的文档是中文的,但是官方的标准库的文档是英文的

实现步骤:

  1. 安装Rust:curl https://sh.rustup.rs -sSf | sh

  2. 安装carco : $ curl -sSf https://static.rust-lang.org/... | sh

  3. cargo new demo

  4. cd demo && npm init -y

  5. npm i ffi —save

  6. 在src/lib下 编写lib.rs

  7. 设置 Cargo.toml 为crate-type = [“dylib”]

  8. cargo build --release

  9. 编写测试index.js

lib.rs

#[no_mangle]
pub extern fn fib(n: i32) -> i32 {
  return match n {
    1 | 2 => 1,
    n => fib(n - 1) + fib(n - 2)
  }
}

Cargo.toml

[package]
name = "cargo_test"
version = "0.1.0"
authors = ["zhangpeng53 <zhangpeng53@baidu.com>"]

[lib]
name = "ffi"
crate-type = ["dylib"]

测试index.js

const ffi = require('ffi');

const rust = ffi.Library('target/release/libffi', {
  fib: ['int', ['int']]
});

// rust
console.time('rust');
console.log(rust.fib(40));
console.timeEnd('rust');

function fib(n) {
  if (n === 1 || n === 2) {
    return 1
  }
  return fib(n - 1) + fib(n - 2)
}

function fib2(n) { 
    if (n < 2) { 
        return 1; 
    } 
    var a = 1, b = 1; 
    for (var i = 2; i < n - 1 ;i++ ) { 
        b = a + b; 
        a = b - a; 
    } 
    return a + b; 
}



// js
console.time('node')
console.log(fib(40))
console.timeEnd('node')

console.log(process.memoryUsage());

执行node index 输出结果:

102334155
rust: 221.232ms102334155node: 1031.842ms
{ rss: 24068096,
  heapTotal: 10330112,
  heapUsed: 5375584,
  external: 46765 }

注释rust代码输出结果

102334155
node: 1051.661ms
{ rss: 22671360,
  heapTotal: 7708672,
  heapUsed: 4460048,
  external: 8236 }

rust 内存使用: 5375584 - 4460048 = 915k

总结:
两者对比性能相似,rust使用内存较高,开发相对简单。看你如何取舍了。

原文出处

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消