AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

寶貝,帶上WebAssembly,換個姿勢來優化你的前端應用

來源: 責編: 時間:2024-06-07 17:19:25 288觀看
導讀前言說起,「前端性能優化」,大家可能第一時間就會從網絡/資源加載/壓縮資源等角度考慮。正如下面所展示的一樣。圖片圖片圖片上面所列的措施,是我們常規優化方案。針對上面的內容我們有機會來講講該如何做。而今天呢,我們

前言

說起,「前端性能優化」,大家可能第一時間就會從網絡/資源加載/壓縮資源等角度考慮。azi28資訊網——每日最新資訊28at.com

正如下面所展示的一樣。azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

上面所列的措施,是我們常規優化方案。針對上面的內容我們有機會來講講該如何做。azi28資訊網——每日最新資訊28at.com

而今天呢,我們和大家嘮嘮利用WebAssembly來優化前端渲染鏈路或者針對關鍵節點進行調優處理。azi28資訊網——每日最新資訊28at.com

我們能所學到的知識點

  1. WebAssembly是個啥?
  2. 項目初始化&配置
  3. Rust項目初始化
  4. 處理耗時任務
  5. 圖像處理
  6. 優化音視頻
  7. 優化游戲體驗

1. WebAssembly是個啥?

WebAssembly是一種「二進制指令格式」,旨在在瀏覽器中高效執行。azi28資訊網——每日最新資訊28at.com

  • 它「作為JavaScript的補充」,允許我們用Rust、C++和C等語言編寫性能關鍵代碼,并在瀏覽器中運行。
  • 通過將代碼編譯成Wasm,它變得「平臺無關」,并且可以以接近本地的速度運行。
  • Rust是一種以安全性和性能著稱的系統編程語言,由于其強大的保證和與Wasm的無縫集成,已經在WebAssembly生態系統中獲得了廣泛的關注。WebAssembly為網絡開發開辟了新的可能性,在一些復雜任務如游戲引擎、圖像處理等方面有著顯著的性能提升。

WebAssembly 的優勢

WebAssembly的一個最具說服力的特點是其在「計算密集型任務」中的性能提升。例如,在對龐大數據集進行復雜的統計計算時,WebAssembly 可能比常規的 JavaScript 快得多。這是因為 WebAssembly 的高度優化設計使得代碼執行速度遠遠超過 JavaScript。azi28資訊網——每日最新資訊28at.com

WebAssembly 的另一個優點是其「可移植性」??缙脚_應用程序的開發變得非常簡單,因為可以從多種語言生成 WebAssembly 代碼,并在任何平臺上執行。azi28資訊網——每日最新資訊28at.com

最后,「安全性」也是 WebAssembly 架構中的一個重要考慮因素。由于 WebAssembly 提供了沙箱執行環境,代碼無法訪問敏感數據或運行惡意代碼。azi28資訊網——每日最新資訊28at.com

下面是了解和學習WebAssembly的RoadMap。azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

2. 項目初始化&配置

進入正題之前,我們還是和之前一樣,使用我們自己的腳手架-f_cli_f[1]構建一個以Vite為打包工具的前端項目。azi28資訊網——每日最新資訊28at.com

在本地合適的目錄下執行如下代碼:azi28資訊網——每日最新資訊28at.com

npx f_cli_f create wasm_preformance

然后,我們在pages中新建如下的目錄結構:azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

其中wasm存放的是我們已經構建好的wasm的資源。azi28資訊網——每日最新資訊28at.com

配置Web Worker

由于我們在項目中會用到Web Worker,所以我們還需要對其做一定的配置。azi28資訊網——每日最新資訊28at.com

而今天,我們再介紹另外一種更加優雅的方式 - Comlink[2]。azi28資訊網——每日最新資訊28at.com

Comlink是一個由Google Chrome Labs開發的輕量級庫,它旨在簡化Web Worker與主線程之間的通信,讓我們能夠充分利用多線程處理的威力,提升前端應用性能。azi28資訊網——每日最新資訊28at.com

由于,我們是用Vite搭建的前端項目,所以我們還需要在項目中借助vite-plugin-comlink[3]。azi28資訊網——每日最新資訊28at.com

我們可以通過如下代碼安裝對應的依賴。azi28資訊網——每日最新資訊28at.com

yarn add -D vite-plugin-comlinkyarn add comlink

然后,將對應的庫配置到vite.config.js中。azi28資訊網——每日最新資訊28at.com

import { comlink } from "vite-plugin-comlink";export default {  plugins: [comlink()],  worker: {    plugins: () => [comlink()],  },};

這里有一點需要額外注意,comlink要放置在plugins第一個位置。azi28資訊網——每日最新資訊28at.com

針對TypeScript項目,我們還需要在vite-env.d.ts中新增/// <reference types="vite-plugin-comlink/client" />。azi28資訊網——每日最新資訊28at.com

然后我們就可以用優雅的方式來使用WebWorker了。azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

可以看到,使用了comlink后,我們在使用多線程能力時,不需要寫那么多模板代碼,而是通過Promise來接收從子線程返回的數據。azi28資訊網——每日最新資訊28at.com

配置WebAssembly

如果看過我們之前的文章(Rust 賦能前端 -- 寫一個 File 轉 Img 的功能)就對這塊不會陌生。azi28資訊網——每日最新資訊28at.com

在Vite項目中使用WebAssembly我們需要配置vite-plugin-wasm[4]和vite-plugin-top-level-await[5]azi28資訊網——每日最新資訊28at.com

然后,也是需要在vite.config.js的plugin和worker中進行相關處理。這里就不展開說明了。之前的文章有過解釋。azi28資訊網——每日最新資訊28at.com

3. Rust項目初始化

在講項目頁面結構時說過,我們在組件目錄中特意有一個wasm目錄用于存放編譯好的wasm信息。azi28資訊網——每日最新資訊28at.com

我們選擇wasm代碼和前端項目分離的方式,也就是我們會重新啟動一個Rust項目。azi28資訊網——每日最新資訊28at.com

通過如下代碼在合適的文件目錄下執行。azi28資訊網——每日最新資訊28at.com

cargo new --lib rust_comformation2web

然后,因為我們想要把Rust編譯成wasm并且還需要操作對應的dom等。所以,我們需要按照對應的crate。azi28資訊網——每日最新資訊28at.com

安裝依賴

所以,我們來更新對應的Cargo.toml。azi28資訊網——每日最新資訊28at.com

[package]name = "rust_comformation2web"version = "0.1.0"edition = "2021"[lib]crate-type = ["cdylib"][dependencies]wasm-bindgen = "0.2.92"console_error_panic_hook = "0.1.7"js-sys = "0.3.69"[dependencies.web-sys]version = "0.3.69"features = [    'Document',    'TextMetrics',    'CanvasRenderingContext2d',    'HtmlCanvasElement',    'Window']

然后,我們就可以在src/lib.rs寫我們對應的代碼了。azi28資訊網——每日最新資訊28at.com

如果對自己的代碼質量不是很放心,并且又不想寫Test模塊了,我們將Rust所在的文件目錄,構建成一個Node項目(通過npm init),并配合對應的打包軟件(Webpack)來直接驗證wasm的效果。azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

對應的webpack.config.js的配置如下:azi28資訊網——每日最新資訊28at.com

const path = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');const webpack = require('webpack');const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");module.exports = {    entry: './index.js',    output: {        path: path.resolve(__dirname, 'dist'),        filename: 'index.js',    },    plugins: [         new HtmlWebpackPlugin({            template: 'index.html'        }),        new WasmPackPlugin({            crateDirectory: path.resolve(__dirname, ".")        }),        // 讓這個示例在不包含`TextEncoder`或`TextDecoder`的Edge瀏覽器中正常工作。        new webpack.ProvidePlugin({          TextDecoder: ['text-encoding', 'TextDecoder'],          TextEncoder: ['text-encoding', 'TextEncoder']        })    ],    mode: 'development',    experiments: {        asyncWebAssembly: true   }};

然后,我們在package.json新增兩個命令azi28資訊網——每日最新資訊28at.com

"scripts": {    "build": "webpack",    "serve": "webpack serve"  },

我們就可以通過yarn serve查看效果亦或者yarn build執行對應的rust打包。azi28資訊網——每日最新資訊28at.com

能夠實現這一切的功勞都是-@wasm-tool/wasm-pack-plugin[6]所賜予的。azi28資訊網——每日最新資訊28at.com

編譯處理

但是呢,我們對Rust編譯處理不使用之前的yarn build,而是使用cargo自己的構建工具 - wasm-pack[7]。azi28資訊網——每日最新資訊28at.com

wasm-pack build --target web --release

如果一切都正常的話,對應的wasm就會被打包到pkg文件夾下面了。azi28資訊網——每日最新資訊28at.com

然后,我們就可以將所有文件復制到Vite項目中的wasm/xx目錄下。azi28資訊網——每日最新資訊28at.com

最后,我們就可以在React組件中通過。azi28資訊網——每日最新資訊28at.com

import init, { fib } from './wasm/xx';

引入對應的wasm函數了。azi28資訊網——每日最新資訊28at.com

前面鋪墊了那么多,其實為了更好的講下面的內容,我們先把一些和邏輯代碼不相關的配置內容提前介紹了,這樣我們就可以將更過的注意力放在代碼實現上了。azi28資訊網——每日最新資訊28at.com

4. 處理耗時任務

先說結果

圖片圖片azi28資訊網——每日最新資訊28at.com

當執行一個處理耗時任務時,WebAssembly/JS WebWorker/JS主線程三者的執行時間是由低到高排列的。azi28資訊網——每日最新資訊28at.com

WebAssembly < JS WebWorker<JS主線程。azi28資訊網——每日最新資訊28at.com

針對上面的我們有幾點需要注意:azi28資訊網——每日最新資訊28at.com

  1. JS WebWorker針對JS主線程優化率不是很高,(有時候worker執行時間甚至比JS主線程長)。
  2. WebAssembly通過至極的內存優化,還可以將優化率提高到50%以上。

聽我解釋

我們都知道JS是單進程的,所以我們在處理一些處理耗時任務就會很吃力。當然,我們也可以借助Web Worker來開啟新的子線程來緩解主線程的計算壓力。但是,在一些計算量特別大的功能面前,一切的計算都是收效甚微的。azi28資訊網——每日最新資訊28at.com

其實,將一些處理耗時任務放置到Web Worker中只是不想讓耗時任務過多的占用主線程資源,從而讓頁面沒有卡頓的感覺。這就是大家所熟悉的瀏覽器在 1 秒鐘內完成 60 次圖像的繪制,用戶才會感覺頁面順暢。azi28資訊網——每日最新資訊28at.com

為了在前端環境模擬處理耗時任務,我們采用在前端環境中執行一個fibonacci的計算過程。azi28資訊網——每日最新資訊28at.com

在WasmPerformance的index.tsx中有如下的頁面操作。azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

也就是說,我們在JS主線程/JS WebWorker/WebAssembly中分別執行一個耗時的fibonacci。azi28資訊網——每日最新資訊28at.com

我們在tool.ts中構建了一個最簡單的fibonacci函數。azi28資訊網——每日最新資訊28at.com

function fibJS(n: number): number {  if (n < 2) {    return n;  }  return fibJS(n - 1) + fibJS(n - 2);}

對應的頁面代碼如下:azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

從上面我們看到幾個關鍵的點:azi28資訊網——每日最新資訊28at.com

我們用state來維護計算的結果和時間。azi28資訊網——每日最新資訊28at.com

const [calculateInfo, setCalculateInfo] = useState<CalculateInfo>({    js: { result: 0, executionTime: 0 },    wasm: { result: 0, executionTime: 0 },    webworker: { result: 0, executionTime: 0 },  });

然后,我們在handleCalculate中執行不同的操作邏輯。azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

其中measureExecutionTime是我們在tool定義的用于檢測指定函數被執行時的所用時間的函數。azi28資訊網——每日最新資訊28at.com

function measureExecutionTime<T extends (...args: any[]) => any>(  fn: T): (...args: Parameters<T>) => { result: ReturnType<T>; executionTime: number } {  return function (...args: Parameters<T>): { result: ReturnType<T>; executionTime: number } {    const start = performance.now();    const result = fn.apply(this, args);    const end = performance.now();    const executionTime = end - start;    return { result, executionTime };  };}

還有,我們在handleCalculate在接收到type為3時,是觸發了一個wasm版本的fibonacci函數。azi28資訊網——每日最新資訊28at.com

由于,對應的Rust代碼如下:azi28資訊網——每日最新資訊28at.com

use wasm_bindgen::prelude::*;#[wasm_bindgen]pub fn fib(n: usize) -> usize {    match n {        0 => 0,        1 => 1,        _ => fib(n - 1) + fib(n - 2),    }}

而上面的Rust代碼會通過wasm-pack build --target web --release進行打包處理,并且打包后的相關內容被復制到了前端項目中wasm/calculate。azi28資訊網——每日最新資訊28at.com

然后在組件中通過import init, { fib } from './wasm/calculate';方式來導入。azi28資訊網——每日最新資訊28at.com

5. 圖像處理

先說結果

圖片圖片azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

我們寫了兩個示例:azi28資訊網——每日最新資訊28at.com

  1. 將指定文本信息繪制到圖片上
  2. 將特定圖形繪制到圖片上

無論是哪種情況,我們可以得出一個比較明顯的情況。azi28資訊網——每日最新資訊28at.com

在圖像處理的部分功能點上,WebAssembly的性能遠高于JS。azi28資訊網——每日最新資訊28at.com

因為,我們這里沒做WebAssembly的內存優化,當處理數據「超級大」時,由于數據傳輸的問題,反而WebAssembly的執行時間會比JS長。但是呢,這塊不在我們的討論范圍內。后期有機會寫相關的文章。azi28資訊網——每日最新資訊28at.com

下面,我們就按照上面的示例來分別講講它們的代碼實現。有些代碼的邏輯其實很簡單,我們已經有對應的注釋,所以也不會用多余的篇幅解釋。azi28資訊網——每日最新資訊28at.com

繪制文本到圖片上

對應的頁面結構如下:azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

我們還是用了一個state來維護狀態信息。azi28資訊網——每日最新資訊28at.com

const [drawInfo, setDrawInfo] = useState<DrawInfo>({    js: { url: '', executionTime: 0 },    wasm: { url: '', executionTime: 0 },    js_circle: { url: '', executionTime: 0 },    wasm_circle: { url: '', executionTime: 0 },  });

然后在handleDraw中處理事件邏輯。azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

其中drawTextToCanvas是利用JS來繪制文本到Canvas,而drawTextToCanvasWasm是利用wasm處理相關邏輯。azi28資訊網——每日最新資訊28at.com

JS 版本的drawText

圖片圖片azi28資訊網——每日最新資訊28at.com

該函數定義在tool.ts中,然后就是接收一個String類型的數據,并將其渲染到Canvas中。azi28資訊網——每日最新資訊28at.com

Rust 版本的drawText

圖片圖片azi28資訊網——每日最新資訊28at.com

然后,別忘記在頭部引入對應的crate。azi28資訊網——每日最新資訊28at.com

use wasm_bindgen::prelude::*;use wasm_bindgen::JsCast;use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement};extern crate console_error_panic_hook;use std::panic;

其實這塊的邏輯,和之前我們講的Rust 賦能前端 -- 寫一個 File 轉 Img 的功能的核心功能是類似的。azi28資訊網——每日最新資訊28at.com

該函數通過wasm-pack編譯到pkg中,然后我們復制對應的文件到React項目的wasm/draw中。azi28資訊網——每日最新資訊28at.com

然后我們通過如下代碼:azi28資訊網——每日最新資訊28at.com

import init4Draw, {  draw_text_to_canvas as drawTextToCanvasWasm,  draw_circle_to_canvas as drawCircleToCanvasWasm,} from './wasm/draw';

進行函數的導入。azi28資訊網——每日最新資訊28at.com

繪制圖形到圖片上

對應的頁面結構和事件回調和之前是類似的,我們就省略了這部分的解釋。azi28資訊網——每日最新資訊28at.com

JS 版本的drawCircle

該部分也是定義在tool.ts中:azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

Rust 版本的drawCircle

圖片azi28資訊網——每日最新資訊28at.com

此函數的處理過程和drawText是一樣的。azi28資訊網——每日最新資訊28at.com

利用Photon操作圖形

針對圖片操作,不單單只有繪制文本/繪制圖案,其實我們還可以做類似(裁剪/新增水印/圖片翻轉等)。azi28資訊網——每日最新資訊28at.com

我們可以借助一些成熟的WebAssembly來做上述的操作。這里呢,給大家推薦一個庫Photon[9]。azi28資訊網——每日最新資訊28at.com

Photon 是一個高性能的圖像處理庫,用 Rust 編寫并可編譯為 WebAssembly,既可以在本地使用 Web 也可以在 Web 上使用。azi28資訊網——每日最新資訊28at.com

這是它能做相關功能:azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

6. 優化音視頻

寫到這里呢,我們就不在羅列相關代碼了。所以,我們給出一些針對音視頻的優化的解決方案。azi28資訊網——每日最新資訊28at.com

在這里我們介紹一種wasm庫-ffmpeg.wasm[10]。azi28資訊網——每日最新資訊28at.com

ffmpeg.wasm 是 FFmpeg[11] 的針對 WebAssembly / JavaScript 端口,支持在瀏覽器中錄制、轉換和流式傳輸視頻和音頻。它利用 Emscripten 來轉譯 FFmpeg 源代碼和許多庫得到。azi28資訊網——每日最新資訊28at.com

具體的功能和庫如下:azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

7. 優化游戲體驗

得益于WebAssembly極致的內存管理,然后其二進制特性,WebAssembly 提供接近本地執行速度的性能,使得復雜的游戲邏輯和高幀率的圖形渲染可以在瀏覽器中高效運行。azi28資訊網——每日最新資訊28at.com

還得之前我們寫過Game = Rust + WebAssembly + 瀏覽器。azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

還有,如果我們想要更多的效果,我們可以選擇使用bevy[12] - 一款基于Rust的數據驅動的游戲引擎。azi28資訊網——每日最新資訊28at.com

然后我們還在itch.io[13]查看哪些游戲是用Rust寫的。azi28資訊網——每日最新資訊28at.com

圖片圖片azi28資訊網——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-92743-0.html寶貝,帶上WebAssembly,換個姿勢來優化你的前端應用

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 從入門到精通:Python OpenPyXL完整教程

下一篇: Oxlint 會取代 Eslint 嗎?

標簽:
  • 熱門焦點
Top