C++ 方式
npm install node-gyp -g
mkdir demo && cd Demo && npm init
创建 fib.cc
创建binding.gyp
node-gyp configure build
创建 测试 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++写起来容易
缺点:
入门曲线非常陡峭,足以让很多人望而却步
对编程意识要求较高,要能主动分辨去除可能会出现的同时读写的变量的情况,否则编译不会通过
虽然官方的文档是中文的,但是官方的标准库的文档是英文的
实现步骤:
安装Rust:curl https://sh.rustup.rs -sSf | sh
安装carco : $ curl -sSf https://static.rust-lang.org/... | sh
cargo new demo
cd demo && npm init -y
npm i ffi —save
在src/lib下 编写lib.rs
设置 Cargo.toml 为crate-type = [“dylib”]
cargo build --release
编写测试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使用内存较高,开发相对简单。看你如何取舍了。