精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Rust賦能前端:為WebAssembly 瘦身

開發(fā) 前端
SIMD(單指令多數(shù)據(jù))指令是一類特殊指令,能夠通過同時(shí)對(duì)多個(gè)數(shù)據(jù)元素執(zhí)行相同操作來利用數(shù)據(jù)并行性。這類指令廣泛應(yīng)用于計(jì)算密集型應(yīng)用中,比如音頻/視頻編解碼器、圖像處理器等,能夠加速性能。大多數(shù)現(xiàn)代體系結(jié)構(gòu)都支持某種形式的 SIMD 指令。

1. 準(zhǔn)備工作

前端項(xiàng)目

由于我們今天的主要任務(wù)是做WebAssembly的優(yōu)化處理,前端項(xiàng)目不是我們重點(diǎn)

針對(duì)于我來說,我直接就用之前的OCR前端項(xiàng)目了。當(dāng)然,你如果不想翻看之前的文章,你也可以使用f_cli_f[1]來構(gòu)建的前端Vite+React+TS項(xiàng)目。

然后在src/pages構(gòu)建一個(gè)文件上傳的頁面,在src目錄下構(gòu)建一個(gè)wasm目錄來存放在前端項(xiàng)目中要用到的各種wasm。

Rust項(xiàng)目

我們是用之前的OCR的Rust項(xiàng)目。當(dāng)然,你也可以拿你自己的項(xiàng)目來進(jìn)行驗(yàn)證。因?yàn)椋覀兇似恼碌膬?nèi)容,都不涉及具體的業(yè)務(wù)邏輯。

2. 前置知識(shí)點(diǎn)

之所以將后面可能涉及到的知識(shí)點(diǎn)和概念提前寫出來,是想讓行文更加明了。也是為了照顧不同階段的同學(xué)。如果你對(duì)這些概念都熟悉,那么可以直接跳過該節(jié)內(nèi)容。如果你還是Rust新手,那么這節(jié)內(nèi)容也算是一種知識(shí)的鞏固。

2.1 Rust Channel

Rust 被發(fā)布到三個(gè)不同的channel:

  1. stable(穩(wěn)定版):穩(wěn)定版本每 6 周發(fā)布一次
  2. beta(測試版):測試版是即將成為下一個(gè)穩(wěn)定版的版本
  3. nightly(夜間版):夜間版則是每天晚上構(gòu)建的最新版本

我們在安裝Rust后,它會(huì)安裝一個(gè)名為rustup的工具,這個(gè)工具能讓我們管理多個(gè)不同版本的 Rust。

默認(rèn)情況下,rustup會(huì)安裝stable版本到我們本機(jī)環(huán)境。

我們可以在rust 版本信息[2]中查看每個(gè)版本的各種信息。

圖片圖片

2.2 安裝nightly版本

Nightly 版本,可以幫助我們嘗試 Rust 的最新特性,我們后面在編譯的時(shí)候,需要用到該版本

我們可以通過下面命令來安裝nightly.

rustup toolchain install nightly

系統(tǒng)將下載所需組件,包括 rustc、rust-std、cargo 等,最后安裝它們。

然后我們可以通過rustup toolchain list來查看我們本機(jī)安裝的Rust版本。

下面是我本機(jī)的各個(gè)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

細(xì)心的同學(xué),可以看到在stable-x86_64-apple-darwin后面有default/override的字樣。

2.3 切換工具鏈

  1. 使用 rustup default 切換工具鏈
  2. 使用 rustup override 在特定項(xiàng)目中使用不同的工具鏈。

我們可以使用 rustup default 命令來切換到指定的工具鏈。

例如,要切換到 stable-x86_64-apple-darwin:

rustup default stable-x86_64-apple-darwin

或者如果切換到 nightly 版本:

rustup default nightly-x86_64-apple-darwin

我們可以使用以下命令,檢查 rustc 當(dāng)前使用的版本:

rustc -V

然后它就會(huì)返回當(dāng)前使用的版本信息。例如我本機(jī)的返回信息為rustc 1.81.0 (eeb90cda1 2024-09-04)

臨時(shí)使用不同工具鏈

如果我們只想在某個(gè)項(xiàng)目使用不同的工具鏈,不改變?nèi)值哪J(rèn)設(shè)置,可以使用:

rustup override set <toolchain>

例如:

rustup override set nightly-x86_64-apple-darwin

這個(gè)命令只會(huì)在當(dāng)前目錄下使用指定的工具鏈,不會(huì)影響其他項(xiàng)目或全局的默認(rèn)設(shè)置。

切換為特定版本的 Rust

我們也可以切換到已安裝的特定版本,比如 1.75.0:

rustup default 1.75.0-x86_64-apple-darwin

2.4 SIMD

在v8官網(wǎng)中有這么一篇文章 - Fast, parallel applications with WebAssembly SIMD[3]里面就介紹了很多關(guān)于SIMD的內(nèi)容,我們來將與我們相關(guān)的內(nèi)容做一下總結(jié)。

SIMD(單指令多數(shù)據(jù))指令是一類特殊指令,能夠通過同時(shí)對(duì)多個(gè)數(shù)據(jù)元素執(zhí)行相同操作來利用數(shù)據(jù)并行性。這類指令廣泛應(yīng)用于計(jì)算密集型應(yīng)用中,比如音頻/視頻編解碼器、圖像處理器等,能夠加速性能。大多數(shù)現(xiàn)代體系結(jié)構(gòu)都支持某種形式的 SIMD 指令。

我們可以從caniuse[4]中看到它的兼容性情況。

圖片圖片

將Rust編譯為WebAssembly SIMD

在Fast, parallel applications with WebAssembly SIMD文章中,它介紹了如何將c/c++的代碼編譯為SIMD以供前端環(huán)境使用。當(dāng)然,也有將Rust編譯為SIMD的方式。其實(shí)我們比較關(guān)心這部分。

此舉有助于將 Rust 代碼高效地編譯為 WebAssembly并利用底層硬件的并行性

當(dāng)我們將 Rust 代碼編譯為目標(biāo) WebAssembly SIMD 時(shí),需要啟用simd128 LLVM 特性[5]。

我們可以直接控制 rustc 的標(biāo)志或通過環(huán)境變量 RUSTFLAGS,可以傳遞 -C target-feature=+simd128:

rustc … -C target-feature=+simd128 -o out.wasm

或者使用 Cargo:

RUSTFLAGS="-C target-feature=+simd128" cargo build

當(dāng)啟用了 simd128 特性時(shí),LLVM 的自動(dòng)矢量化器會(huì)默認(rèn)在優(yōu)化代碼時(shí)啟用。

2.5 binaryen

Binaryen[6] 是一個(gè)為 WebAssembly 設(shè)計(jì)的編譯器和工具鏈基礎(chǔ)庫,由 C++ 編寫。它旨在讓編譯為 WebAssembly 變得簡單、快速且高效

Binaryen為我們提供了很多優(yōu)化工具,而今天我們選擇其中的一個(gè)也就是-wasm-opt。

安裝wasm-opt

wasm-opt 是 Binaryen 工具的一部分,可以通過多種方式安裝,下面列出了幾種常用的安裝方法:

  • 使用 npm 安裝:安裝完成后,wasm-opt 會(huì)成為全局命令,直接在終端中使用
npm install -g binaryen
  • 通過 Homebrew 安裝(適用于 macOS 和 Linux)
brew install binaryen
  • 通過預(yù)編譯二進(jìn)制文件安裝:前往 Binaryen的GitHub releases 頁面[7],下載與你的操作系統(tǒng)相匹配的壓縮包。

驗(yàn)證安裝

安裝完成后,我們可以通過以下命令檢查 wasm-opt 是否安裝成功:

wasm-opt --version
// wasm-opt version 119 (version_119)

如果返回版本號(hào),說明安裝成功。

3. 常規(guī)編譯

我們之前在Rust 編譯為 WebAssembly 在前端項(xiàng)目中使用就介紹過,如何將一個(gè)Rust項(xiàng)目編譯為WebAssembly。

當(dāng)時(shí)我們使用常規(guī)的編譯方式。

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的文件下生成相關(guān)的文件資源。

  • xxx.wasm
  • xxx.js
  • xxx.d.ts

然后,我們就可以將yyy的相關(guān)文件引入到前端項(xiàng)目中,通過配置Webpack/Vite的Wasm相關(guān)內(nèi)容,就可以通過import引入對(duì)應(yīng)的實(shí)例或者方法了。

release的默認(rèn)profiles配置

在Cargo Book[8]中對(duì)release的默認(rèn)profiles配置有相關(guān)介紹。

當(dāng)我們在使用cargo build --release對(duì)項(xiàng)目進(jìn)行打包處理時(shí)候,它內(nèi)部默認(rèn)是根據(jù)下面的配置優(yōu)化相關(guān)項(xiàng)目的。

[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

針對(duì)上面各個(gè)屬性的解釋,大家可以翻看release相關(guān)解釋[9]去了解更多,這里就不在贅述了。

效果展示

下面的所有的效果展示,和自己的本機(jī)環(huán)境息息相關(guān),也就是如果你在編譯/執(zhí)行項(xiàng)目時(shí),電腦資源被占用的很多或者電腦過熱。這個(gè)時(shí)間也是有波動(dòng)的。最終的時(shí)間對(duì)比,按自己的情況而定。

資源大小

首先,我們先看編譯后的文件大小

編譯的文件大小為1.4M編譯的文件大小為1.4M

編譯時(shí)間

編譯時(shí)間為40秒編譯時(shí)間為40秒

運(yùn)行時(shí)間

我們將上面編譯好的文件引入到之前我們的OCR的前端項(xiàng)目。然后,運(yùn)行相關(guān)代碼。

圖片圖片

在執(zhí)行相關(guān)的操作后,整體的運(yùn)行時(shí)間為4秒

4. 優(yōu)化編譯詳解

寫在最前面,下面的一些配置,有最大力度的優(yōu)化方案,但是可能根據(jù)項(xiàng)目性質(zhì)的不同,你使用了,卻沒達(dá)到想要的效果。這就是一個(gè)取舍問題,也是一個(gè)實(shí)踐出真知的問題。要想將自己的項(xiàng)目配置成最好,下面的配置方案可能適用你,也可能不使用。如果不適用,你可以根據(jù)下面的配置方向,找出符合你的最佳方案。

我們來針對(duì)上面的打包做一次優(yōu)化處理。我們先把相關(guān)的優(yōu)化方案列舉出來,然后最后給一個(gè)最終的解決方案。

4.1 刪除符號(hào)或調(diào)試信息

這部分,我們可以通過設(shè)置release-strip的信息來優(yōu)化編譯結(jié)果。

[profile.release]
strip = true

在 Rust 項(xiàng)目中,strip它決定了 rustc是否從生成的二進(jìn)制文件中刪除符號(hào)或調(diào)試信息。這個(gè)選項(xiàng)主要用于減小生成文件的大小,特別是在發(fā)布(release)模式下打包時(shí)。

strip 的選項(xiàng)

  • "none": 不剝離任何信息(默認(rèn)設(shè)置)
  • "debuginfo": 剝離調(diào)試信息,但保留符號(hào)。
  • "symbols": 剝離符號(hào)信息,保留調(diào)試信息。

除了字符串值外,還可以使用布爾值進(jìn)行設(shè)置:

  • strip = true 等同于 strip = "symbols"。
  • strip = false 等同于 strip = "none",完全禁用剝離

場景說明

在 Linux 和 macOS 系統(tǒng)上,編譯生成的 .elf 文件中默認(rèn)會(huì)包含符號(hào)信息。這些符號(hào)信息通常不需要在執(zhí)行二進(jìn)制文件時(shí)使用,因此可以選擇剝離,以減小文件大小。尤其是在發(fā)布模式下,剝離符號(hào)信息是常見的做法,用來生成更小、更優(yōu)化的可執(zhí)行文件。

4.2 設(shè)置opt-level

Rust 的 opt-level 設(shè)置控制 rustc 的 -C opt-level 標(biāo)志,它用于決定編譯時(shí)的優(yōu)化級(jí)別。

優(yōu)化級(jí)別越高,生成的代碼在運(yùn)行時(shí)可能越快,但同時(shí)也會(huì)增加編譯時(shí)間,并且更高的優(yōu)化級(jí)別可能會(huì)對(duì)代碼進(jìn)行重排和改動(dòng),這可能會(huì)使調(diào)試更加困難。

可用的優(yōu)化級(jí)別

  • 0: 無優(yōu)化,適合快速編譯,常用于開發(fā)階段。
  • 1: 基礎(chǔ)優(yōu)化,平衡編譯速度和性能,適合某些性能需求不高的場景。
  • 2: 中度優(yōu)化,進(jìn)行一些優(yōu)化,提供較好的性能,通常用于測試環(huán)境。
  • 3: 完全優(yōu)化,進(jìn)行所有可能的優(yōu)化,適合需要最高性能的發(fā)布代碼,但編譯時(shí)間會(huì)增加。
  • "s": 優(yōu)化二進(jìn)制文件大小,通過減少代碼體積來優(yōu)化。
  • "z": 進(jìn)一步優(yōu)化二進(jìn)制大小,并關(guān)閉循環(huán)向量化,使得編譯產(chǎn)物更小。

這里我們選擇大力出奇跡直接使用最高級(jí)別的優(yōu)化。

[profile.release]
opt-level = "s"

其實(shí),每個(gè)項(xiàng)目的優(yōu)化力度是不同的,這個(gè)需要根據(jù)自己項(xiàng)目去決定

4.3 Link Time Optimization (LTO)

Link Time Optimization (LTO) 是一種優(yōu)化技術(shù),它將編譯單元在鏈接階段進(jìn)行優(yōu)化。通常情況下,Cargo 會(huì)將每個(gè)編譯單元獨(dú)立編譯和優(yōu)化,而 LTO 允許在整個(gè)程序的鏈接階段對(duì)其進(jìn)行優(yōu)化。這可以去除不需要的代碼(例如死代碼),并且在許多情況下會(huì)減小二進(jìn)制文件的大小。這個(gè)和我們前端的TreeSharke是一個(gè)道理。

lto 設(shè)置的選項(xiàng)

  • false: 執(zhí)行“局部精簡 LTO”,即在本地 crate 的代碼生成單元上執(zhí)行精簡 LTO。如果 codegen-units 是 1 或者 opt-level 為 0,則不會(huì)進(jìn)行 LTO。
  • true 或 "fat": 執(zhí)行“胖 LTO”,嘗試對(duì)整個(gè)依賴圖中的所有 crate 進(jìn)行跨 crate 優(yōu)化。
  • "thin": 執(zhí)行“精簡 LTO”,類似于“胖 LTO”,但消耗的時(shí)間大大減少,同時(shí)仍能獲得類似的性能提升。
  • "off": 禁用 LTO。

這里我們也是下猛藥。直接使用最大力度的優(yōu)化方案。

LTO 的配置方法

[profile.release]
lto = true

4.4 設(shè)置并行代碼生成單元

在 Rust 中,代碼生成單元(codegen-units) 是編譯器將 crate 拆分為多個(gè)部分并行處理的機(jī)制。通過增加代碼生成單元,編譯器可以并行處理多個(gè)部分,從而加快編譯速度。然而,更多的代碼生成單元會(huì)限制某些全局優(yōu)化的能力,從而可能導(dǎo)致較大的二進(jìn)制文件或運(yùn)行速度稍慢的代碼。

減少代碼生成單元數(shù),尤其是在發(fā)布模式下,將有助于 Rust 編譯器執(zhí)行更深入的全局優(yōu)化,生成更高效和更小的二進(jìn)制文件。在性能需求高或者文件大小敏感的場景下,將 codegen-units 設(shè)置為 1 是一種常見的優(yōu)化手段。

并行代碼生成單元的設(shè)置

Rust 默認(rèn)在發(fā)布構(gòu)建中將 crate 分成 16 個(gè)并行代碼生成單元。這種設(shè)置有助于加快編譯速度,特別是在多核 CPU 上,因?yàn)槎鄠€(gè)單元可以同時(shí)生成代碼。然而,這會(huì)限制編譯器進(jìn)行某些全局優(yōu)化,例如跨模塊優(yōu)化,影響代碼運(yùn)行時(shí)的性能或二進(jìn)制文件的大小。

權(quán)衡

  • 更多并行單元:編譯速度更快,但可能會(huì)損失全局優(yōu)化的機(jī)會(huì)。
  • 更少并行單元(如 1):編譯速度較慢,但生成的代碼經(jīng)過更多全局優(yōu)化,可能運(yùn)行速度更快,并且二進(jìn)制文件更小。

我們的選擇

我們選擇將codegen-units設(shè)置為1,犧牲編譯速度,減少文件大小。

[profile.release]
codegen-units = 1


4.5 修改panic!()行為

當(dāng) Rust 代碼執(zhí)行 panic!() 時(shí),默認(rèn)的行為是 展開棧(unwinding the stack),從而生成有用的回溯信息(backtrace),以幫助我們定位問題。然而,棧展開過程需要額外的代碼,這增加了二進(jìn)制文件的大小。

為了減少二進(jìn)制文件的大小,Rust 提供了另一種策略,即在程序出現(xiàn) panic!() 時(shí),立即 終止進(jìn)程(abort),而不是展開棧。通過啟用這種行為,可以完全去掉棧展開代碼,顯著減少程序的二進(jìn)制大小。

啟用 Abort on Panic

在 Cargo.toml 中通過在發(fā)布配置下設(shè)置 panic = "abort" 來啟用此功能:

[profile.release]
panic = "abort"

使用 "abort" 策略可以有效減少二進(jìn)制文件的大小,特別適合生產(chǎn)環(huán)境和資源受限的場景,但會(huì)犧牲部分調(diào)試能力和安全性,所以這就要求我們在前端環(huán)境做一些容錯(cuò)機(jī)制。

4.6 移除位置信息

在 Rust 中,默認(rèn)情況下,panic!() 和 #[track_caller] 特性會(huì)生成文件、行號(hào)和列號(hào)的位置信息,用于在代碼運(yùn)行出錯(cuò)時(shí)提供更有用的回溯信息(traceback)。這些信息對(duì)調(diào)試非常有幫助,但也會(huì)增加二進(jìn)制文件的大小。

為了進(jìn)一步減小生成的二進(jìn)制文件的大小,Rust 提供了一個(gè)實(shí)驗(yàn)性的功能,可以移除這些位置信息。這通過使用 rustc 的不穩(wěn)定選項(xiàng) -Zlocation-detail 來實(shí)現(xiàn)。

有效的 location-detail 選項(xiàng):

  • none:移除所有文件、行號(hào)和列號(hào)信息。適合在不需要回溯信息的環(huán)境中使用。
  • file:僅保留文件信息。
  • file,line:保留文件和行號(hào)信息。
  • file,line,column(默認(rèn)值):保留完整的文件、行號(hào)和列號(hào)信息,用于調(diào)試。

移除位置信息

通過設(shè)置 RUSTFLAGS 環(huán)境變量并將其值設(shè)為 -Zlocation-detail=none,我們可以在構(gòu)建二進(jìn)制時(shí)移除這些位置信息,從而減少文件大小。這種優(yōu)化特別適用于生產(chǎn)環(huán)境,或者對(duì)二進(jìn)制文件大小有較高要求的項(xiàng)目。

示例命令如下:

$ RUSTFLAGS="-Zlocation-detail=none" cargo +nightly build --release

從上面可以看到,有一段cargo +nightly。這說明啥,這需要我們切換到nightly版本。

4.7 移除 fmt::Debug

在 Rust 中,#[derive(Debug)] 和 {:?} 格式化符號(hào)用于調(diào)試輸出,幫助我們打印結(jié)構(gòu)體和枚舉的內(nèi)部信息。然而,調(diào)試功能會(huì)在生成的二進(jìn)制文件中包含大量類型信息和格式化函數(shù),這可能會(huì)增加文件大小。

fmt-debug 選項(xiàng)說明:

  • **full**(默認(rèn)):#[derive(Debug)] 遞歸打印類型及其字段的詳細(xì)信息。
  • **shallow**:僅打印類型名稱或枚舉的變體名稱,不打印詳細(xì)的類型字段信息。此行為不穩(wěn)定,未來可能會(huì)有變化。
  • **none**:完全不打印任何信息,{:?} 格式化符號(hào)也不起作用。此選項(xiàng)可以顯著減少二進(jìn)制文件大小,并移除沒有被符號(hào)剝離移除的類型名稱,但可能導(dǎo)致 panic! 和 assert! 消息不完整。

移除 fmt::Debug:

Rust 提供了一個(gè)實(shí)驗(yàn)性選項(xiàng) -Zfmt-debug,允許將 #[derive(Debug)] 和 {:?} 格式化操作變成空操作(no-op),即不輸出任何調(diào)試信息。通過這種方式,派生的 Debug 實(shí)現(xiàn)和相關(guān)的字符串將被移除,從而減小二進(jìn)制文件的大小。

可以使用如下命令啟用該功能:

$ RUSTFLAGS="-Zfmt-debug=none" cargo +nightly build --release

和之前的location-detail一樣,開啟該項(xiàng)目功能,我們也需要使用Rust的nightly版本。

4.8 進(jìn)一步優(yōu)化 panic

panic_immediate_abort,旨在徹底移除 panic!() 相關(guān)的字符串格式化邏輯。這是 panic = "abort" 選項(xiàng)的進(jìn)一步優(yōu)化,即便已指定了 panic = "abort",Rust 仍然會(huì)默認(rèn)將一些與 panic!() 相關(guān)的字符串和格式化代碼包含在最終的二進(jìn)制文件中。這會(huì)導(dǎo)致二進(jìn)制文件中存在不必要的占用空間,尤其是在極致優(yōu)化二進(jìn)制大小的場景下。

如何使用

配置方式如下:

$ cargo +nightly build \
   -Z build-std=std,panic_abort \
   -Z build-std-features=panic_immediate_abort
  • **使用 build-std 重新構(gòu)建 libstd**:按照 build-std 的流程,重新編譯標(biāo)準(zhǔn)庫,同時(shí)啟用 panic_abort 行為。
  • 進(jìn)一步縮小二進(jìn)制大小:啟用 panic_immediate_abort 特性后,所有與 panic!() 相關(guān)的字符串信息和格式化邏輯都將被移除。

4.9 開啟simd128

之前我們就說過,我們可以對(duì)Rust開啟simd128。

RUSTFLAGS="-C target-feature=+simd128" cargo build

這里就不在過多解釋了。

4.10 優(yōu)化wasm-bindgen

之前的優(yōu)化都是針對(duì)Rust部分,下面我們來看看,針對(duì)wasm-bindgen的優(yōu)化角度。

之前我們不是,使用wasm-bindgen為 Rust 編寫的 WebAssembly 模塊生成 JavaScript 綁定。它可以幫助 Rust 和 JavaScript 之間進(jìn)行高效的數(shù)據(jù)交互。

wasm-bindgen target/wasm32-unknown-unknown/release/audioAndVideo.wasm --out-dir js/dist/ --target web

我們還可以在后面添加一下配置,來優(yōu)化生成的代碼。

--reference-types

  • 此選項(xiàng)啟用了 WebAssembly 的引用類型,這允許 WebAssembly 代碼可以直接引用 JavaScript 對(duì)象(如 DOM 元素),無需對(duì)這些對(duì)象進(jìn)行包裝或轉(zhuǎn)換,從而提高了內(nèi)存管理和交互的效率。
  • 引用類型擴(kuò)展了 WebAssembly 中的基本值類型(如 i32, i64, f32, f64),引入了可以引用 JavaScript 對(duì)象(如函數(shù)、外部引用)的能力。

--reference-types 通過允許 WebAssembly 直接引用 JavaScript 對(duì)象,提高了效率,減少了不必要的轉(zhuǎn)換。

--weak-refs

  • 此選項(xiàng)啟用了 WebAssembly 中的弱引用。弱引用允許我們引用對(duì)象而不會(huì)阻止它們被垃圾回收。在 JavaScript 中,這一特性被用于防止內(nèi)存泄漏,可以持有對(duì)象的弱引用,當(dāng)沒有強(qiáng)引用時(shí),垃圾回收器可以回收這些對(duì)象。
  • 對(duì)于 Rust 和 WebAssembly,弱引用有助于在跨 JS 和 WebAssembly 邊界的對(duì)象跟蹤中進(jìn)行更有效的內(nèi)存管理,避免不必要的對(duì)象占用內(nèi)存。

--weak-refs 通過啟用弱引用,改善了內(nèi)存管理,防止內(nèi)存泄漏,確保不必要的對(duì)象能被及時(shí)回收。

4.11 使用wasm-opt

由于,我們在前面已經(jīng)下載了wasm-opt了。所以,這里我們就直接上代碼了。

我們在Rust項(xiàng)目中構(gòu)建一個(gè)tools/optimize-wasm.sh文件。

內(nèi)容如下:

#!/bin/sh

set -eu

BIN_PATH="${1:-}"
WASMOPT_BIN=$(which wasm-opt || true)

if [ -z "$BIN_PATH" ]; then
  echo "Usage: $(basename "$0") <WASM binary>"
  exit 1
fi

if [ -z "$WASMOPT_BIN" ]; then
  echo '由于未找到 `wasm-opt` 二進(jìn)制文件,因此跳過編譯后優(yōu)化。'
  exit
fi

if [ -n "${SKIP_WASM_OPT:-}" ]; then
  echo  "由于設(shè)置了 SKIP_WASM_OPT,所以跳過了編譯后優(yōu)化"
  exit
fi

wasm-opt --enable-simd --enable-reference-types -O2 "$BIN_PATH" -o "$BIN_PATH".optimized
mv "$BIN_PATH.optimized" "$BIN_PATH"

上面代碼,最關(guān)鍵的就是

wasm-opt --enable-simd --enable-reference-types -O2 "$BIN_PATH" -o "$BIN_PATH".optimized
mv "$BIN_PATH.optimized" "$BIN_PATH"
  • 使用以下選項(xiàng)運(yùn)行 wasm-opt 對(duì)提供的 WASM 二進(jìn)制文件進(jìn)行優(yōu)化:

--enable-simd: 啟用 SIMD 支持,以便更快地進(jìn)行并行數(shù)據(jù)處理。

--enable-reference-types: 啟用 WASM 模塊中的引用類型。

-O2: 應(yīng)用中等級(jí)別的優(yōu)化 (O2),在性能和二進(jìn)制大小之間進(jìn)行平衡。

優(yōu)化結(jié)果寫入臨時(shí)文件 "$BIN_PATH.optimized"。

  • 最后,通過移動(dòng) (mv) 優(yōu)化后的文件替換原始文件。

5. 最終方案

配置Cargo.toml

[profile.release]
strip = true  
opt-level = 3
lto = true
codegen-units = 1
panic = "abort"

構(gòu)建shell 文件

注意下文中的xxx需要替換成你項(xiàng)目的名稱

build.sh

我們在項(xiàng)目根目錄構(gòu)建一個(gè)build.sh文件,內(nèi)容如下

#!/bin/bash

# 執(zhí)行 optimize-rust.sh
echo "執(zhí)行 optimize-rust.sh..."
./tools/optimize-rust.sh

# 檢查是否成功執(zhí)行
if [ $? -ne 0 ]; then
    echo "optimize-rust.sh 構(gòu)建失敗."
    exit 1
fi

# 執(zhí)行 optimize-wasm.sh
echo "執(zhí)行 optimize-wasm.sh..."
./tools/optimize-wasm.sh js/dist/xxx_bg.wasm

# 檢查是否成功執(zhí)行
if [ $? -ne 0 ]; then
    echo "optimize-wasm.sh 構(gòu)建失敗."
    exit 1
fi

echo "Rust 已構(gòu)建成功,到指定目錄查看相關(guān)信息."

我們構(gòu)建一個(gè)tools文件,然后新建兩個(gè)文件

  • optimize-rust.sh
  • optimize-wasm.sh

optimize-rust.sh

#!/bin/bash

# 獲取項(xiàng)目名稱
PACKAGE_NAME="xxx"

# 編譯 Rust 代碼
RUSTFLAGS="-Zlocation-detail=none -Zfmt-debug=none -C target-feature=+simd128" cargo +nightly build \
    -Z build-std=std,panic_abort \
    -Z build-std-features=panic_immediate_abort \
    --release --target wasm32-unknown-unknown --package "$PACKAGE_NAME"

# 生成 wasm 綁定
wasm-bindgen target/wasm32-unknown-unknown/release/"$PACKAGE_NAME".wasm --out-dir js/dist/ --target web

optimize-wasm.sh

#!/bin/sh

set -eu

BIN_PATH="${1:-}"
WASMOPT_BIN=$(which wasm-opt || true)

if [ -z "$BIN_PATH" ]; then
  echo "Usage: $(basename "$0") <WASM binary>"
  exit 1
fi

if [ -z "$WASMOPT_BIN" ]; then
  echo '由于未找到 `wasm-opt` 二進(jìn)制文件,因此跳過編譯后優(yōu)化。'
  exit
fi

if [ -n "${SKIP_WASM_OPT:-}" ]; then
  echo  "由于設(shè)置了 SKIP_WASM_OPT,所以跳過了編譯后優(yōu)化"
  exit
fi

wasm-opt --enable-simd --enable-reference-types -O2 "$BIN_PATH" -o "$BIN_PATH".optimized
mv "$BIN_PATH.optimized" "$BIN_PATH"

然后,我們就可以在Rust項(xiàng)目根目錄執(zhí)行./build.sh來執(zhí)行編譯任務(wù)了。

運(yùn)行結(jié)果

文件大小

編譯的文件大小為900KB

可以看到,我們將之前1.4MB的資源縮小到了900KB。

如果我們還想減少二進(jìn)制文件的大小,我們還可以繼續(xù)更改上面的配置信息。如果單純的追求資源大小的話,我們可以將其縮小到300kb,但是,其運(yùn)行時(shí)間會(huì)比沒瘦身之前還長

魚和熊掌不能兼得,我們只能根據(jù)實(shí)際情況而定。也就是實(shí)踐出真知

運(yùn)行時(shí)間

圖片圖片

可以看到,雖然文件大小變小了,但是我們運(yùn)行性能卻沒有打折扣。那就充分說明,我們此次的瘦身是成功的。

Reference

[1]f_cli_f: https://www.npmjs.com/package/f_cli_f

[2]rust 版本信息: https://releases.rs/

[3]Fast, parallel applications with WebAssembly SIMD: https://v8.dev/features/simd

[4]caniuse: https://caniuse.com/?search=simd

[5]LLVM 特性: https://llvm.org/

[6]Binaryen: https://github.com/WebAssembly/binaryen

[7]Binaryen的GitHub releases 頁面: https://github.com/WebAssembly/binaryen/releases

[8]Cargo Book: https://doc.rust-lang.org/cargo

[9]release相關(guān)解釋: https://doc.rust-lang.org/cargo/reference/profiles.html

責(zé)任編輯:武曉燕 來源: 前端柒八九
相關(guān)推薦

2024-11-01 13:31:28

RustViteRsbuild

2023-10-27 10:16:17

前端項(xiàng)目Rust

2019-11-01 10:00:14

前端業(yè)務(wù)代碼

2023-10-10 09:08:50

2022-06-22 10:04:29

JavaScriptRust語言

2021-03-29 14:53:01

大數(shù)據(jù)人工智能司法

2022-08-26 14:35:42

云計(jì)算數(shù)字經(jīng)濟(jì)安全

2024-05-23 08:12:45

Rust前端開發(fā)JavaScrip

2019-09-03 21:56:38

智能制造AWS

2017-07-27 20:43:50

賦能商業(yè)智能

2020-06-15 12:14:06

遠(yuǎn)程

2012-05-16 13:31:07

信息通信技術(shù)世界電信日

2021-04-16 23:39:57

機(jī)器人智慧醫(yī)療大數(shù)據(jù)

2021-03-29 11:02:46

大數(shù)據(jù)司法大數(shù)據(jù)應(yīng)用

2020-10-14 10:30:07

前端Node代碼

2021-05-14 22:24:28

移動(dòng)云辦公

2020-03-05 11:15:32

IBM混合云

2018-05-24 17:24:35

UCloudUMStor存儲(chǔ)

2018-03-23 12:08:34

企業(yè)上云

2023-06-06 07:32:41

辦公軟件PPTAI
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

精品国产一级| 深爱五月激情五月| 日韩一区电影| 91精品国产欧美日韩| 日本高清视频免费在线观看| 国产刺激高潮av| 亚洲尤物影院| 色妞欧美日韩在线| 国内精品免费视频| 日韩经典一区| 亚洲二区在线观看| 性欧美videosex高清少妇| www.99视频| 久久久人人人| 欧美激情成人在线视频| 熟女俱乐部一区二区| 久久视频免费| 欧美最猛性xxxxx直播| 欧美在线观看黄| а天堂8中文最新版在线官网| 国产精品资源站在线| 欧洲s码亚洲m码精品一区| 永久av免费网站| 嫩草影视亚洲| 精品国产电影一区二区| 久久久久xxxx| 自拍偷自拍亚洲精品被多人伦好爽| 一区二区三区四区在线播放| 日韩av高清| 五月婷婷六月丁香| 国产成人啪午夜精品网站男同| 国产极品jizzhd欧美| 国产精品日日夜夜| 欧美 日韩 国产精品免费观看| 久久精品国产亚洲a| 国产日韩欧美高清| 精品国产日本| 亚洲国产日韩在线观看| 极品少妇xxxx精品少妇偷拍| 国产不卡在线观看| 国产精品黄色大片| 亚洲人www| www.国产一区| 国产探花在线视频| 欧美少妇性xxxx| 亚洲精品一区av在线播放| 熟女人妻一区二区三区免费看| 国产成人免费精品| 欧洲生活片亚洲生活在线观看| 无码精品a∨在线观看中文| 国产盗摄精品一区二区酒店| 亚洲免费av高清| 国产精品三区四区| 午夜精品在线播放| 成人午夜视频在线| 国产精品日韩一区二区 | 国产理论电影在线观看| wwwwxxxxx欧美| 免费试看一区| 成人性生交大片免费看午夜| 国产视频一区二区三区在线观看 | 国产精品x453.com| 中文字幕在线看视频国产欧美| www.av天天| 国产又粗又猛又黄又爽| 成人h在线观看| 欧美三级视频在线观看| 三级av免费观看| 在线免费观看亚洲| 欧美一级黄色大片| 久久av一区二区三| 伦理一区二区| 亚洲人成电影网站色…| 91社区视频在线观看| 青青草91久久久久久久久| 最近2019年中文视频免费在线观看| 波多野结衣家庭教师在线观看 | 日韩激情视频在线| 真人bbbbbbbbb毛片| 精品一区欧美| 最新日韩中文字幕| 免费一级肉体全黄毛片| 日韩午夜在线| 国产精品国模在线| 午夜精品在线播放| 久久综合狠狠综合| 亚洲国产另类久久久精品极度| 蜜桃视频在线观看www社区| 一区二区三区四区中文字幕| 国产精品333| 国产日本久久| 精品精品国产高清a毛片牛牛| 给我看免费高清在线观看| 欧美色就是色| 欧美激情精品久久久久久黑人 | 久久超碰亚洲| 右手影院亚洲欧美| 国产高清一区二区| 性色av一区二区三区红粉影视| 国产suv精品一区二区33| 国产在线一区观看| 欧美日韩在线一二三| 黄色片网站在线| 亚洲第一精品在线| 欧美一级特黄aaa| 日韩精品福利一区二区三区| www.欧美精品| 国产精品免费精品一区| 狠狠色综合播放一区二区| 久久久久久九九九九| 免费大片在线观看www| 欧美日韩国产中文字幕| 久久久久久免费看| 国产在线一区不卡| 亚洲色图日韩av| 久久久全国免费视频| 日日欢夜夜爽一区| 国产一级精品aaaaa看| 免费网站看v片在线a| 色94色欧美sute亚洲线路一久| 特黄特色免费视频| 99久久99热这里只有精品| 欧美在线亚洲在线| 亚洲欧美另类视频| 亚洲柠檬福利资源导航| 嫩草影院国产精品| 蜜桃一区二区| 26uuu国产精品视频| 国产黄a三级三级三级| 色哟哟精品丝袜一区二区| 亚洲欧美激情插| 一区二区三区入口| 在线成人动漫av| 午夜精品久久久久久久久久久久| 国产美女三级无套内谢| 国产精品久久久久久久久久久免费看 | 制服.丝袜.亚洲.中文.综合懂| 日韩一区二区中文| 国产精品老牛影院在线观看| 黄色av小说在线观看| 一区二区三区自拍| 97人人模人人爽人人澡| 婷婷精品进入| 91精品啪aⅴ在线观看国产| 992tv免费直播在线观看| 在线看一区二区| 人妻少妇无码精品视频区| 亚洲欧美不卡| 日本不卡免费新一二三区| 免费福利视频一区二区三区| 精品一区电影国产| 无码人妻久久一区二区三区不卡| 91麻豆国产福利精品| 国产主播在线看| 九九久久精品| 国产精品九九久久久久久久| 福利视频在线导航| 欧美日韩在线亚洲一区蜜芽| 亚洲色图27p| 国内久久婷婷综合| 欧美中文字幕在线观看视频| 国产乱人伦精品一区| 91国内精品久久| 黄色在线免费观看大全| 欧美午夜电影网| 欧美肥妇bbwbbw| 国产精品69毛片高清亚洲| 屁屁影院ccyy国产第一页| 久久99国产精品久久99大师 | 欧美xoxoxo| 久久蜜桃av一区二区天堂| 免费黄色特级片| 欧美中文一区二区| 91视频免费在线| 视频在线这里都是精品| 亚洲电影在线看| chinese国产精品| 国产精品久久久久aaaa樱花| 成人高清在线观看视频| 999亚洲国产精| 色综合久久av| 视频一区日韩精品| 国产91精品久| 毛片在线播放a| 亚洲国产91色在线| 国产一区二区视频免费| 亚洲人成小说网站色在线| 水蜜桃av无码| 麻豆极品一区二区三区| 9色porny| 四虎成人av| 好吊色欧美一区二区三区| 成人黄页网站视频| 久久久久久综合网天天| 国产一级二级三级在线观看| 日韩一区二区高清| 精品免费囯产一区二区三区| 中文字幕中文在线不卡住| 国产伦精品一区二区免费| 蜜臀av一区二区| 亚洲不卡中文字幕无码| 99精品网站| 欧美国产综合视频| 亚洲经典视频| 国产精品亚洲自拍| 欧美gv在线| 欧美精品在线观看91| 欧洲亚洲精品视频| 精品奇米国产一区二区三区| 中文在线字幕av| 黑人狂躁日本妞一区二区三区| 小泽玛利亚一区二区免费| 久久精品一区四区| 日韩成人av影院| 精久久久久久久久久久| 国产成人亚洲精品无码h在线| 女生裸体视频一区二区三区| 色之综合天天综合色天天棕色| 国产精品流白浆在线观看| 成人精品网站在线观看| 亚洲www啪成人一区二区| 97色在线视频观看| 超碰在线资源| 欧美大片va欧美在线播放| 丝袜美腿美女被狂躁在线观看| 亚洲欧美国产精品久久久久久久| 黄色一级大片在线免费看国产一| 69堂国产成人免费视频| 最近中文字幕av| 91国偷自产一区二区三区成为亚洲经典| 中文字幕第28页| 一区二区久久久久| 老妇女50岁三级| 亚洲精品午夜久久久| 日韩在线视频免费看| 国产精品嫩草99a| 99久久久无码国产精品衣服| 久久婷婷综合激情| 波多野结衣办公室33分钟| 99久久夜色精品国产网站| av不卡中文字幕| 粉嫩久久99精品久久久久久夜| 成人性生交视频免费观看| 激情图区综合网| 日本77777| 国产一区二区三区蝌蚪| 国产成人强伦免费视频网站| 国产最新精品精品你懂的| 做a视频在线观看| 国产九色精品成人porny| 69久久精品无码一区二区| 国产在线视频一区二区三区| 亚洲黄色片免费看| 国产美女精品人人做人人爽| 日韩欧美中文在线视频| 国产成人综合视频| 久久人妻少妇嫩草av蜜桃| 成人免费看视频| 超碰97人人干| 国产精品久久综合| 日韩欧美国产成人精品免费| 亚洲猫色日本管| 久久久精品视频免费| 大桥未久av一区二区三区| 无码一区二区三区| 欧美日本视频在线| 国产成人免费看一级大黄| 精品欧美一区二区三区精品久久| 黄色www视频| 亚洲欧美中文另类| 欧美三级黄网| 欧美激情a在线| 超碰aⅴ人人做人人爽欧美| 国产精品h在线观看| 亚洲福利影视| 国产嫩草一区二区三区在线观看| 丝袜美腿综合| 亚洲资源在线网| 国产在线不卡| 老头吃奶性行交视频| 国产精品综合在线视频| 99re久久精品国产| 国产精品久线观看视频| 国产无码精品一区二区| 色欧美乱欧美15图片| 国产视频在线观看视频| 亚洲精品久久在线| 免费黄网在线观看| 欧美亚洲另类激情另类| 91视频亚洲| 欧美动漫一区二区| 午夜精品毛片| 动漫av网站免费观看| 久久国产三级精品| 香港三级日本三级| 亚洲久本草在线中文字幕| 久草手机在线视频| 欧美一二三区在线| 国产女人在线观看| 久久久久久18| 欧洲亚洲精品| 久久国产精品一区二区三区| 成人一级黄色大片| 另类小说一区二区三区| 国产人妻黑人一区二区三区| 国产精品乱人伦| 97免费在线观看视频| 制服丝袜中文字幕一区| 久久电影中文字幕| 久久人人爽人人爽人人片av高请 | 伊人免费在线| 欧美一二三视频| 试看120秒一区二区三区| 日韩中文不卡| 亚洲一区欧美激情| 永久免费未满蜜桃| 亚洲美女少妇撒尿| 在线免费观看日韩视频| 亚洲免费视频在线观看| 国产偷倩在线播放| 91亚洲国产精品| 成人在线一区| 久久久久久久久久久免费视频| 成人午夜视频免费看| 欧美日韩在线国产| 欧美日免费三级在线| 东凛在线观看| 欧美福利视频在线| 婷婷激情成人| 一级做a爰片久久| 欧美aaa在线| 欧美熟妇激情一区二区三区| 欧美日韩国产中字| 亚州视频一区二区三区| 97高清免费视频| 国内视频在线精品| 国产高清www| 国产91在线看| 久久久久黄色片| 精品黑人一区二区三区久久| 日韩伦理电影网站| 91在线精品观看| 欧美日韩国产欧| 少妇熟女视频一区二区三区 | 99久久久免费精品国产一区二区| 欧美日韩免费做爰视频| 日韩视频一区二区在线观看| 国产高清一区二区三区视频| 精品国产91久久久久久久妲己| 日韩av片免费观看| 久久久亚洲欧洲日产国码αv| 欧美一级视频免费观看| 亚洲韩国欧洲国产日产av | 午夜欧美2019年伦理| 欧美 日韩 国产 在线| 97人洗澡人人免费公开视频碰碰碰| 国产香蕉精品| 116极品美女午夜一级| 国产色产综合产在线视频| 亚洲手机在线观看| 久久久www成人免费精品| 精品国产乱码久久久久久樱花| gogogo免费高清日本写真| 国产麻豆一精品一av一免费 | 亚洲xxxx在线| 狠狠色丁香久久综合频道| 这里只有精品在线观看视频| 精品久久久久久中文字幕大豆网| 欧美在线观看在线观看| 国产精品久久91| 欧美日一区二区在线观看| 大乳护士喂奶hd| 在线观看亚洲一区| 欧美一区二区三区| 国产精品区一区二区三在线播放| 久久精品麻豆| 国内毛片毛片毛片毛片毛片| 日韩视频国产视频| 最近在线中文字幕| 中文字幕中文字幕一区三区| 成人97人人超碰人人99| 91在线视频免费播放| 精品国产依人香蕉在线精品| 成人知道污网站| 天天影视综合色| 一区二区三区美女视频| 久久国产精品高清一区二区三区| 亚洲va欧美va在线观看| 亚洲欧美bt| 欧美黄色一级网站| 亚洲人成在线播放| 国产一区 二区| 黄色高清无遮挡| 亚洲自拍偷拍麻豆| 草碰在线视频| 九九九久久久| 国产一区二区影院| 亚洲无码精品一区二区三区| 精品中文字幕在线2019| 精品久久久亚洲|