Rust赋能前端:为WebAssembly 瘦身
前端小魔女 2024-10-14 15:33:01 阅读 75
❝
凡事你一旦接纳了,就不存在了;你看不惯它,它就一直折磨你
大家好,我是柒八九。一个专注于前端开发技术/<code>Rust及AI
应用知识分享的Coder
❝
此篇文章所涉及到的技术有
WebAssembly
Rust
SIMD
LLVM
binaryen
因为,行文字数所限,有些概念可能会一带而过亦或者提供对应的学习资料。请大家酌情观看。
前言
❝
提前祝大家国庆节快乐哈!🎇🎇
我们最近不是写了3篇Rust赋能前端的文章吗。
Rust 赋能前端:PDF 分页/关键词标注/转图片/抽取文本/抽取图片/翻转...:在里面介绍如何在前端环境中(
React/Vue
)中使用
Mupdf
,用于执行各种
PDF
的操作。
Rust 赋能前端: 视频抽帧:在里面介绍如何在前端环境中(
React/Vue
)中对视频资源进行抽帧处理。
Rust 赋能前端:图片OCR识别,以后可以抛弃tesseract了:介绍了在前端环境中(
React/Vue
)如何使用
Rust
对图片做
Ocr
处理。
之前和大家剧透过,本来最近的一篇文章是讲利用AI模型进行音视频文件的语音信息抽离。
但是呢,看到有些粉丝在后台私信我。说想让讲讲如何对WebAssebmly进行打包优化。可能看到我们在Rust 赋能前端:图片OCR识别,以后可以抛弃tesseract了
中提过一嘴,然后感觉没尽兴。
你都开口了,我358团不能不帮这个忙。所以,今天我们就来聊聊这个话题。
再啰嗦几句
其实,如果大家做过前端项目的打包优化(Webpack/Vite
)的话,对这块就不会很陌生。
对于打包优化
来讲,可能有很多优化方向。但是,无论如何处理,其实最核心的一点就是减少资源大小。
所以,今天就来从这个角度来讲讲如何为我们的WebAssembly做瘦身处理。
对了,如果大家想了解如何针对Webpack
做打包优化,可以翻看我们之前的文章前端工程化之Webpack优化
好了,天不早了,干点正事哇。
我们能所学到的知识点
❝
准备工作
前置知识点
常规编译
优化编译详解
最终方案
1. 准备工作
前端项目
❝
由于我们今天的主要任务是做<code>WebAssembly的优化处理,前端项目不是我们重点
针对于我来说,我直接就用之前的OCR
前端项目了。当然,你如果不想翻看之前的文章,你也可以使用f_cli_f[1]来构建的前端Vite+React+TS
项目。
然后在src/pages
构建一个文件上传的页面,在src
目录下构建一个wasm
目录来存放在前端项目中要用到的各种wasm
。
Rust项目
我们是用之前的OCR
的Rust
项目。当然,你也可以拿你自己的项目来进行验证。因为,我们此篇文章的内容,都不涉及具体的业务逻辑。
2. 前置知识点
❝
之所以将后面可能涉及到的知识点和概念提前写出来,是想让行文更加明了。也是为了照顾不同阶段的同学。如果你对这些概念都熟悉,那么可以直接跳过该节内容。如果你还是
Rust
新手,那么这节内容也算是一种知识的巩固。
2.1 Rust Channel
Rust
被发布到三个不同的channel
:
stable
(稳定版):稳定版本每 6 周发布一次
beta
(测试版):测试版是即将成为下一个稳定版的版本
nightly
(夜间版):夜间版则是每天晚上构建的最新版本
我们在安装Rust
后,它会安装一个名为rustup
的工具,这个工具能让我们管理多个不同版本的 Rust
。
❝
默认情况下,
rustup
会安装stable
版本到我们本机环境
我们可以在rust 版本信息[2]中查看每个版本的各种信息。
2.2 安装nightly版本
❝
<code>Nightly 版本,可以帮助我们尝试
Rust
的最新特性,我们后面在编译的时候,需要用到该版本
我们可以通过下面命令来安装nightly
.
rustup toolchain install nightly
系统将下载所需组件,包括 rustc
、rust-std
、cargo
等,最后安装它们。
然后我们可以通过rustup toolchain list
来查看我们本机安装的Rust
版本。
下面是我本机的各个Rust
信息。
stable-x86_64-apple-darwin (default) (override)
stable-x86_64-unknown-linux-gnu
nightly-x86_64-apple-darwin
1.75.0-x86_64-apple-darwin
细心的同学,可以看到在stable-x86_64-apple-darwin
后面有default
/override
的字样。
2.3 切换工具链
❝
使用
rustup default
切换工具链
使用
rustup override
在特定项目中使用不同的工具链。
我们可以使用 rustup default
命令来切换到指定的工具链。
例如,要切换到 stable-x86_64-apple-darwin
:
rustup default stable-x86_64-apple-darwin
或者如果切换到 nightly
版本:
rustup default nightly-x86_64-apple-darwin
我们可以使用以下命令,检查 rustc
当前使用的版本:
rustc -V
然后它就会返回当前使用的版本信息。例如我本机的返回信息为rustc 1.81.0 (eeb90cda1 2024-09-04)
临时使用不同工具链
如果我们只想在某个项目使用不同的工具链,不改变全局的默认设置,可以使用:
rustup override set <toolchain>
例如:
rustup override set nightly-x86_64-apple-darwin
这个命令只会在当前目录下使用指定的工具链,不会影响其他项目或全局的默认设置。
切换为特定版本的 Rust
我们也可以切换到已安装的特定版本,比如 1.75.0
:
rustup default 1.75.0-x86_64-apple-darwin
2.4 SIMD
在v8
官网中有这么一篇文章 - Fast, parallel applications with WebAssembly SIMD[3]里面就介绍了很多关于SIMD
的内容,我们来将与我们相关的内容做一下总结。
❝
SIMD
(单指令多数据)指令是一类特殊指令,能够通过同时对多个数据元素执行相同操作来利用数据并行性。这类指令广泛应用于计算密集型应用中,比如音频/视频编解码器、图像处理器等,能够加速性能。大多数现代体系结构都支持某种形式的 SIMD 指令。
我们可以从caniuse[4]中看到它的兼容性情况。
将Rust编译为WebAssembly SIMD
在<code>Fast, parallel applications with WebAssembly SIMD文章中,它介绍了如何将c/c++
的代码编译为SIMD
以供前端环境使用。当然,也有将Rust
编译为SIMD
的方式。其实我们比较关心这部分。
❝
此举有助于将
Rust
代码高效地编译为WebAssembly
并利用底层硬件的并行性
当我们将 Rust
代码编译为目标 WebAssembly SIMD
时,需要启用simd128
LLVM 特性[5]。
我们可以直接控制 rustc
的标志或通过环境变量 RUSTFLAGS
,可以传递 -C target-feature=+simd128
:
rustc … -C target-feature=+simd128 -o out.wasm
或者使用 Cargo
:
RUSTFLAGS="-C target-feature=+simd128" cargo buildcode>
当启用了 simd128
特性时,LLVM
的自动矢量化器会默认在优化代码时启用。
2.5 binaryen
❝
Binaryen[6] 是一个为
WebAssembly
设计的编译器和工具链基础库,由C++
编写。它旨在让编译为WebAssembly
变得简单、快速且高效
Binaryen
为我们提供了很多优化工具,而今天我们选择其中的一个也就是-wasm-opt
。
安装wasm-opt
wasm-opt
是 Binaryen
工具的一部分,可以通过多种方式安装,下面列出了几种常用的安装方法:
使用
npm
安装:安装完成后,
wasm-opt
会成为全局命令,直接在终端中使用
npm install -g binaryen
通过
Homebrew
安装(适用于
macOS
和
Linux
)
brew install binaryen
通过预编译二进制文件安装:前往
Binaryen的GitHub releases 页面
[7],下载与你的操作系统相匹配的压缩包。
验证安装
安装完成后,我们可以通过以下命令检查 wasm-opt
是否安装成功:
wasm-opt --version
// wasm-opt version 119 (version_119)
如果返回版本号,说明安装成功。
3. 常规编译
我们之前在Rust 编译为 WebAssembly 在前端项目中使用就介绍过,如何将一个Rust
项目编译为WebAssembly
。
当时我们使用常规的编译方式。
cargo build --release --target wasm32-unknown-unknown --package xxx
wasm-bindgen target/wasm32-unknown-unknown/release/xxx.wasm --out-dir yyy --target web
上面我们是通过cargo
和wasm-bindgen
编译Rust
文件为WebAssembly
,然后在yyy
的文件下生成相关的文件资源。
xxx.wasm
xxx.js
xxx.d.ts
然后,我们就可以将yyy
的相关文件引入到前端项目中,通过配置Webpack/Vite
的Wasm
相关内容,就可以通过import
引入对应的实例或者方法了。
release的默认profiles配置
在Cargo Book[8]中对release
的默认profiles
配置有相关介绍。
当我们在使用cargo build --release
对项目进行打包处理时候,它内部默认是根据下面的配置优化相关项目的。
[profile.release]
opt-level = 3
debug = false
split-debuginfo = '...' # Platform-specific.
strip = "none"
debug-assertions = false
overflow-checks = false
lto = false
panic = 'unwind'
incremental = false
codegen-units = 16
rpath = false
针对上面各个属性的解释,大家可以翻看release相关解释[9]去了解更多,这里就不在赘述了。
效果展示
❝
下面的所有的效果展示,和自己的本机环境息息相关,也就是如果你在编译/执行项目时,电脑资源被占用的很多或者电脑过热。这个时间也是有波动的。 最终的时间对比,按自己的情况而定。
资源大小
首先,我们先看编译后的文件大小
本文由 mdnice 多平台发布
上一篇: 芋道源码yudao-cloud 二开日记(添加接口权限和页面固定路由)
下一篇: 【JavaWeb】利用IDEA2024+tomcat10配置web6.0版本搭建JavaWeb开发项目
本文标签
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。