Deno应用集成WebAssembly(二)性能测试

时间:11/17/2024 10:07:11   作者:ChenReal    阅读:33

前几天,尝试了在Deno环境下JavaScript与集成WebAssembly的集成,我也立马将整个过程记录到博客里。

没多久,有朋友私信我说:“你只是验证方案的可行性,并没有证明这么做的必要性”。的确如此,其实,我故意卖关子,今天再写一篇把使用WebAssembly的“必要性”给点出来。(因为我需要花点时间学习Rust)

所谓的“必要性”,说白了就是性能的对比。看看使用了WebAssembly这样复杂性的方案,能不能获得应用程序性能的等比例提升,性价比几何。

啃了两天Rust之后,我已经准备好了!坐稳,开车~~

用例说明

我的测试用例是这样的:

  • 用字母和数字组成的长度为64的随机字符串,生成图片二维码
  • 将图片二维码用base64的编码输出
  • 以上过程循环1000次,记录试程序执行时长

测试代码

下面有请三组选手上场:

1、Deno(TypeScript)

import { qrcode } from "https://deno.land/x/qrcode/mod.ts";

// 生成一个随机的64位字符串
const generateRandomtring = (len:number=64): string =>{
    const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    var randomString = "";
    for (let i = 0; i < len; i++) {
        const n = Math.floor(Math.random() * charset.length);
        randomString += charset[n];
    }
    return randomString;
}

const generateQRCode = async () => {
    for (let i = 0; i < 1000; i++) {            
        const input = generateRandomtring();
        const base64Image = await qrcode(input,{size:160});
    }
}

const startTime = Date.now();
generateQRCode();
const endTime = Date.now();

console.log(`Deno Time taken: ${endTime - startTime} ms`);

2、Node.js(JavaScript)

Node.js作为Deno的姐妹,也前来助阵。生成二维码也是用的第三方的库:

{
    "dependencies": {
      "qrcode": "^1.5.4"
    }
}
const QRCode = require('qrcode');

const generateRandomtring = (len) =>{
    const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    var randomString = "";
    for (let i = 0; i < len; i++) {               
        const n = Math.floor(Math.random() * charset.length);
        randomString += charset[n];
    }
    return randomString;
}

const generateQRCode = async () => {
    for (let i = 0; i < 1000; i++) {            
        const input = generateRandomtring(64);      
        var base64Image = await QRCode.toDataURL(input);
    }
}

const startTime = Date.now();
generateQRCode();
const endTime = Date.now();
console.log(`Node.js Time taken: ${endTime - startTime} ms`);

3、WebAssembly(Rust)

  • Rust引用的第三方库
[dependencies]
wasm-bindgen = "=0.2.92"
qrcode = "0.14.1"
rand = "0.8.4"
base64 = "0.21.0"
getrandom = { version = "0.2", features = ["js"] }
  • 生成二维的Rust代码
use wasm_bindgen::prelude::*;
use qrcode::QrCode;
use base64::prelude::*;
use rand::{thread_rng, Rng};

fn generate_random_string(length: usize) -> String {
    let charset: &[u8] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    let mut rng = thread_rng();
    let mut result = String::with_capacity(length);
    for _ in 0..length {
        let random_index: usize = rng.gen_range(0..charset.len());
        result.push(charset[random_index] as char);
    }
    return result
}
#[wasm_bindgen]
pub fn gen_qrcode() -> String{
    let random_string = generate_random_string(64);
    println!("{}", random_string);
    // 生成二维码
    let code = QrCode::new(&random_string).unwrap();
    let image= code.render::<qrcode::render::unicode::Dense1x2>().build();
    let img_bytes = image.as_bytes();
    // 将二维码字符串转换为Base64编码
    let base64_encoded = BASE64_STANDARD.encode(img_bytes); 
    return base64_encoded;
}
  • Deno调用gen_qrcode
import { instantiate } from "./lib/lib_qrcode.generated.js";
const { gen_qrcode } = await instantiate();

const startTime = Date.now();
for (let i = 0; i < 1000; i++) {
    gen_qr_code()
}
const endTime = Date.now();

console.log(`WASM Time taken: ${endTime - startTime}ms`);

测试结果与分析

以上三组代码各自运行3次,取平均值。结果如下:

Deno(TypeScript) Node.js(JavaScript) WebAssembly(Rust)
6.1s 4.3s 1.4s
  • 不出意外,WebAssembly以好几个身位的绝对优势遥遥领先!证明了它是一套值得我们拥有的高性能的应用开发方案。
  • Node.js居然稍稍领先比Deno,这个有点始料不及。个人分析,有可能受第三方qrcode的库的拖累,导致Deno掉了链子。如果抛开这个因素,估计Deno和Node.js应当是在伯仲之间的。

结论

我们用代码实例去对比,证明了Rust+WebAssembly强悍的性能。相信之前有所怀疑的小伙伴们,现在也跟我一样的笃定,正在摩拳擦掌,准备开始学习Rust了吧!

 

评论
0/200