精品欧美一区二区三区在线观看 _久久久久国色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)

亚洲AV无码精品国产| 欧美激情一区二区视频| 草莓视频成人appios| 国产精品乱人伦| 成人免费91在线看| 欧美啪啪小视频| 天天插综合网| 亚洲精品国产精品国自产在线| 国产一区亚洲二区三区| 大片免费在线观看| 久久久午夜精品理论片中文字幕| 国产剧情日韩欧美| 极品魔鬼身材女神啪啪精品| 欧美精品中文| 7777精品伊人久久久大香线蕉完整版 | 久色乳综合思思在线视频| 色综合久久五月| 小说区图片区亚洲| 色婷婷综合久久久久中文| 在线视频一二三区| 丁香婷婷在线| 99精品国产视频| 亚洲影视九九影院在线观看| 中文人妻av久久人妻18| 亚洲韩日在线| 久久九九全国免费精品观看| 91精品人妻一区二区| 91综合久久爱com| 欧美高清视频www夜色资源网| 草草久久久无码国产专区| h网站久久久| 国产精品丝袜一区| 欧洲一区二区在线观看| 丰满岳乱妇国产精品一区| 老司机午夜精品| 国产精品第2页| 久草视频在线观| 在线精品一区二区| 九色成人免费视频| 黄色片在线观看网站| 视频在线不卡免费观看| 在线观看免费高清视频97| 人妻熟女aⅴ一区二区三区汇编| 精品美女一区| 欧美无砖砖区免费| 在线视频日韩一区| 影视一区二区三区| 91久久精品一区二区三| 日韩欧美精品在线观看视频| 国产污视频在线播放| 亚洲一区视频在线| www.欧美黄色| 波多野结衣乳巨码无在线观看| 亚洲欧美日韩综合aⅴ视频| 亚洲欧美日韩不卡一区二区三区| 精品乱码一区二区三四区视频 | 精品久久久久久中文字幕动漫| 国产富婆一级全黄大片| 国产精品资源站在线| 亚洲精品日韩激情在线电影| av中文字幕免费在线观看| 韩国v欧美v日本v亚洲v| 亚洲综合大片69999| 国产高清免费av| 国产不卡视频在线播放| 国产精品手机在线| 天堂影院在线| 国产视频一区二区在线| 亚洲人成人77777线观看| 午夜老司机在线观看| 国产精品成人网| 欧美交换配乱吟粗大25p| 免费污视频在线观看| 精品国产乱码久久久久久虫虫漫画| 日本欧美视频在线观看| 麻豆免费在线| 欧美性猛交一区二区三区精品| 黄色永久免费网站| 成人av在线播放| 亚洲精品在线电影| 欧美做受喷浆在线观看| 精品久久精品| 久久天天躁狠狠躁夜夜躁| 免费毛片在线播放免费| 夜夜夜久久久| 国产免费一区视频观看免费| va婷婷在线免费观看| 91一区在线观看| 亚洲精品一卡二卡三卡四卡| 99在线播放| 亚洲成人午夜电影| 午夜免费高清视频| 日韩欧美中文在线观看| 精品视频在线导航| 三级黄色免费观看| 99热这里只有精品8| 国产精品自拍偷拍视频| 韩国av在线免费观看| 久久久国产午夜精品 | av片在线观看免费| 欧美天堂在线观看| 韩国一区二区在线播放| 五月综合久久| 欧美黄色小视频| 中国黄色一级视频| www.亚洲在线| 男女h黄动漫啪啪无遮挡软件| 多野结衣av一区| 91精品国产一区二区三区香蕉 | 沈樵精品国产成av片| 欧美xxxx做受欧美.88| 日本熟女毛茸茸| 成人午夜视频网站| 日本免费在线视频观看| 韩国精品主播一区二区在线观看| 日韩欧美三级在线| 欧美色图17p| 久久综合图片| 国产亚洲自拍偷拍| jizzjizz亚洲| 在线播放欧美女士性生活| 37p粉嫩大胆色噜噜噜| 欧美日一区二区在线观看| 国产精品直播网红| gogogo高清在线观看免费完整版| 天天综合天天做天天综合| 97超碰免费在线观看| 日韩久久综合| 国产精品久久久精品| 神马电影在线观看| 欧美日韩国产精品专区 | 亚洲香蕉视频| 国内成人精品一区| 囯产精品久久久久久| 亚洲欧美视频一区| 北条麻妃亚洲一区| 91精品一区国产高清在线gif | 天天干天天色天天| 亚洲综合激情小说| 亚洲区 欧美区| 欧美在线免费一级片| 成人欧美在线观看| 国产网友自拍视频导航网站在线观看| 精品视频色一区| 精品伦精品一区二区三区视频密桃| 丝袜a∨在线一区二区三区不卡| 久久久久久国产精品免费免费| а√天堂中文资源在线bt| 精品国产百合女同互慰| 精品一区二区三区人妻| 国产91精品免费| 欧美乱大交xxxxx潮喷l头像| 精品三级在线观看视频| 91极品视频在线| 欧美日韩激情视频一区二区三区| 欧美日韩中文字幕日韩欧美| 亚洲AV无码国产精品| 欧美中文字幕| 亚洲图片都市激情| 国产精品美女久久久久人| 欧美剧在线观看| 成人免费视频国产| 福利精品视频在线| 日本成人免费视频| 精品一区二区三区在线播放视频 | 午夜亚洲精品| 欧洲在线视频一区| 国外成人福利视频| 九九久久综合网站| 五月婷婷伊人网| 欧洲精品一区二区| 波多野结衣爱爱视频| 99re成人在线| 鲁一鲁一鲁一鲁一av| 欧美三级免费| 日本欧美色综合网站免费| 日韩三区四区| 欧美激情一级精品国产| 三级视频在线播放| 欧美美女一区二区三区| 日本污视频在线观看| 国产色91在线| 日韩高清一二三区| 久久资源在线| 久久久无码中文字幕久...| 精品三级av| 91精品国产综合久久男男| 伦理在线一区| 在线成人中文字幕| 国产77777| 欧美日韩一区二区不卡| 国产精品 欧美激情| 91麻豆蜜桃一区二区三区| 五月婷婷激情久久| 亚洲激情国产| 9999在线观看| 国产乱码精品一区二区亚洲 | 一区二区三区资源| 免费人成又黄又爽又色| 国产成人精品免费视频网站| 亚洲免费av一区二区三区| 欧美精品97| 亚洲成人一区二区三区| 另类ts人妖一区二区三区| 国产一区在线播放| 都市激情亚洲一区| 欧美激情一级二级| www免费视频观看在线| 亚洲人a成www在线影院| 成人无码一区二区三区| 欧美美女bb生活片| 国产又粗又猛又黄视频| 精品动漫一区二区| 日本中文在线视频| 国产精品视频麻豆| 熟女俱乐部一区二区| 成人免费高清在线| theporn国产精品| 日本伊人精品一区二区三区观看方式| 欧美 丝袜 自拍 制服 另类| 亚洲精品小说| 中文字幕乱码一区二区三区| 久久av超碰| 久久天天狠狠| 欧美黑人巨大videos精品| 2014亚洲精品| 99视频这里有精品| 国产中文字幕亚洲| 国产欧美自拍| 国产精品久久在线观看| 欧美日韩美女| 国产999在线观看| 免费日韩电影| 日本人成精品视频在线| 秋霞伦理一区| 97精品国产97久久久久久免费| 青春草免费在线视频| 久久伊人91精品综合网站| 丝袜美腿美女被狂躁在线观看| 亚洲网站视频福利| 国模吧精品人体gogo| 亚洲男人的天堂在线播放| 天堂av网在线| 亚洲欧美日韩成人| 国产日本在线| 自拍偷拍亚洲区| 视频三区在线| 另类图片亚洲另类| 日本资源在线| 高清在线视频日韩欧美| 国产传媒在线观看| 日韩av快播网址| 亚洲天堂1区| 国产欧美日韩免费看aⅴ视频| 涩涩涩久久久成人精品| 成人免费黄色网| 欧美黄视频在线观看| 国产精品视频免费一区| 小嫩嫩12欧美| 视频一区在线免费观看| 99久久www免费| 久久av高潮av| 一区二区毛片| 91日韩视频在线观看| 国产一区二区精品久久91| 亚洲一区和二区| 久久先锋影音av| 中文国语毛片高清视频| 洋洋av久久久久久久一区| 日韩精品手机在线| 欧美午夜一区二区三区免费大片| 91在线你懂的| 亚洲第一视频在线观看| 国内av一区二区三区| 久久久国产精品视频| caoporn视频在线| 国产精品极品美女在线观看免费 | 国产成人精品免费看| 无码人妻aⅴ一区二区三区| 国产午夜精品久久| 久久久久久久久久网站| 欧美三级欧美成人高清www| 真实新婚偷拍xxxxx| 亚洲精品在线电影| 日韩理伦片在线| 久久久久久亚洲精品中文字幕| 台湾佬中文娱乐久久久| 99久久99久久精品国产片| 五月激激激综合网色播| 亚洲自拍偷拍一区二区三区| 99av国产精品欲麻豆| 香蕉视频禁止18| 成人国产视频在线观看| 林心如三级全黄裸体| 亚洲成人激情综合网| 在线观看xxxx| 日韩毛片在线观看| 深夜国产在线播放| 国产精品久久久av| 日韩在线黄色| 青青草免费在线视频观看| 久久一综合视频| 黄色激情在线观看| 日韩久久一区二区| 五月婷婷激情五月| 亚洲成人中文字幕| yellow91字幕网在线| 国产高清在线不卡| 欧美影院天天5g天天爽| 麻豆一区二区三区在线观看| 日韩国产一区二| 久久人人爽人人人人片| 亚洲欧美日韩国产手机在线| 亚洲第一区av| 亚洲精品视频久久| av成人影院在线| 99视频网站| 911精品美国片911久久久| 中文字幕国内自拍| 久久综合精品国产一区二区三区| 麻豆亚洲av熟女国产一区二| 777欧美精品| 黄色片网站在线| 91精品久久久久久久久久久久久久 | 在线看成人av电影| 日韩精彩视频在线观看| av直播在线观看| 精品久久香蕉国产线看观看gif| 99视频在线观看免费| 久久久www成人免费精品| 国产乱子精品一区二区在线观看| 日韩国产在线一区| 日韩电影网1区2区| 2019男人天堂| 欧美中文字幕一区二区三区| 国产最新视频在线观看| 国产成人在线一区| 国产剧情一区| 亚洲精品视频导航| 国产精品家庭影院| 国产精品久久久久毛片| 久久精品久久久久久| 外国成人毛片| 精品国产一区二区三区在线| 国产高清无密码一区二区三区| 亚洲天堂黄色片| 日韩一区二区免费在线电影| a级网站在线播放| 99re视频| 影音先锋亚洲精品| 日本黄色片在线播放| 色综合咪咪久久| 成人三级黄色免费网站| 成人黄色av网站| 欧美成人午夜| 艳妇乳肉亭妇荡乳av| 欧美日韩中文字幕在线| h网站视频在线观看| 亚洲aaaaaa| 伊人久久婷婷| 欧美激情aaa| 欧美日本在线播放| 羞羞视频在线观看免费| 久久人人九九| 久久国产夜色精品鲁鲁99| 欧美性猛交xxxxx少妇| 精品国产不卡一区二区三区| 久九九久频精品短视频| 亚洲国产精品综合| 国产福利一区在线| 欧美日韩综合一区二区三区| 中文字幕久久久av一区| 1313精品午夜理伦电影| 37pao成人国产永久免费视频| 中文字幕欧美区| 不卡av中文字幕| 日韩av高清不卡| 欧美日韩亚洲三区| 在线观看日本中文字幕| 91精品国产欧美日韩| 美女视频在线免费| 制服丝袜综合日韩欧美| 成人黄色a**站在线观看| 在线观看日本视频| 裸体女人亚洲精品一区| 网友自拍一区| 99精品视频免费版的特色功能| 精品欧美一区二区三区| 国产在线观看av| 欧洲成人一区二区| 国产69精品久久99不卡| 最近中文字幕在线观看视频| 欧美风情在线观看| 欧美日韩在线网站| 亚洲精品成人无码毛片| 欧美在线播放高清精品| av蜜臀在线| av磁力番号网| 久久尤物电影视频在线观看| 一区二区www|