node >=16
Express api
先用express 构建一个服务,用于我们测试
const express = require('express');
const {readdir , stat} = require("fs/promises");
const {join} = require("path");
const app = express();
const port = 3000;
const dirSize = async dir =>{
const files = await readdir(dir,{withFileTypes:true})
const paths = files.map( async file =>{
const path = join(dir, file.name)
if (file.isDirectory()) {
return await dirSize(path)
}
if (file.isFile()){
const {size } = await stat(path)
return size
}
return 0
})
return (await Promise.all(paths)).flat(Infinity).reduce((i,size) => i+ size , 0)
}
app.get("/v1" , async (req,res)=>{
console.time("dir")
let size = await dirSize("./assets/")
console.timeEnd('dir')
res.json(size)
})
现在在assert文件夹下面大约有400个文件, 还有很多txt文件
启动服务后, curl -v http://127.0.0.1:3000/v1 测试一下, node大约需要68ms可以运行完成.
让我们来切换相同语法的Rust尝试
可以直接使用 Nodejs bindings 库来直接使用rust
先在Cargo.toml 里加载我们所需要的依赖项
[package]
name = "nodewith_rust"
version = "0.1.0"
edition = "2021"
[dependencies]
node-bindgen = {version = "5.0"}
[build-dependencies]
node-bindgen = {version = "5.0", features =["build"]}
[lib]
name = "nodewith_rust"
crate-type = ["cdylib"]
创建一个build.rs 文件
fn main (){
node_bindgen::build::configure();
}
然后创建一个 src/lib.rs 文件, 用于做和node 相同的事情
use node_bindgen::derive::node_bindgen;
use std::{fs, io ,path::PathBuf};
fn get_size (path: impl Into<PathBuf>) -> io::Result<u64>{
fn dir_size (mut dir: fs::ReadDir) -> io::Result<u64>{
dir.try_fold(0 , |acc, file | {
let file = file?;
let size = match file.metadata()? {
data if data.is_dir() => dir_size(fs::read_dir(file.path())?)?,
data => data.len(),
};
Ok(acc+size )
})
}
dir_size(fs::read_dir(path.into())?)
}
#[node_bindgen]
async fn size(path :String) -> u64 {
if let Ok(dir_size) = get_size(path){
return dir_size;
}
else{
return 0;
}
}
现在要构建项目, 使用cargo install nj-cli
先运行 cargo build
然后运行 nj-cli build
会发现生成一个 dist/index.node 文件, 引用一下这个库来重新对比测试一下
const express = require('express');
const {readdir , stat} = require("fs/promises");
const {join} = require("path");
// 加载我们的rust module
const rustmodule = require("./dist/index")
const app = express();
const port = 3000;
const dirSize = async dir =>{
const files = await readdir(dir,{withFileTypes:true})
const paths = files.map( async file =>{
const path = join(dir, file.name)
if (file.isDirectory()) {
return await dirSize(path)
}
if (file.isFile()){
const {size } = await stat(path)
return size
}
return 0
})
return (await Promise.all(paths)).flat(Infinity).reduce((i,size) => i+ size , 0)
}
app.get("/v1" , async (req,res)=>{
console.time("dir")
let size = await dirSize("./assets/")
console.timeEnd('dir')
res.json(size)
})
app.get("/v2", async (req,res) =>{
console.time("dir")
let size = await rustmodule.size("./assets/")
console.timeEnd("dir")
res.json({size:Number(size)})
})
app.listen(port, () => {
console.log(`服务监听在${port}`)
})
启动服务, 在测试一下 curl -v http://127.0.0.1:3000/v2 会发现用rust写的库大约用了23ms提升了3倍左右
具体消耗时间取决于你的电脑性能
github地址 github.com/LuXinZ/rust…