国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

給 Web 前端工程師看的用 Rust 開發(fā) wasm 組件實戰(zhàn)

這篇具有很好參考價值的文章主要介紹了給 Web 前端工程師看的用 Rust 開發(fā) wasm 組件實戰(zhàn)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

什么是wasm組件?

wasm 全稱 WebAssembly,是通過虛擬機的方式,可以在服務(wù)端、客戶端如瀏覽器等環(huán)境執(zhí)行的二進制程序。他有速度快、效率高、可移植的特點。

對我們 Web 前端工程最大的好處就是可以在瀏覽器端使用二進制程序處理一些計算量大的處理,使用他比 javascript 快的特點優(yōu)化性能。

目前瀏覽器對wasm的兼容性如下:

在移動端除了 android 4.4 和 ios 10 下不支持外,其他版本都能提供支持。還需要注意的是 wasm 有可能占用大量內(nèi)存,使用第三方包含 wasm 調(diào)用的組件需要注意內(nèi)存占用防止閃退。

為什么用Rust?

wasm模塊 可以用多種語言來編譯,包括 C/C++/C#、Rust、JAVA、Go。在這里使用 Rust 是因為他有嚴格的內(nèi)存管理機制,從語法上盡量避免內(nèi)存溢出,讓工程師寫出更安全的程序。

而且還有配套的工具 wasm-pack,讓使用 Rust 編寫的代碼,編譯包裝成 npm 包,讓使用這段程序的其他代碼可以像使用其他公共庫一樣調(diào)用,不需要額外學(xué)習(xí)成本。

工具安裝

  1. 安裝 rustup,他是 Rust 安裝器和版本管理工具。對于 web 前端來說相當(dāng)于 nvm 這樣的工具。
    按照 rust 官網(wǎng)的方法安裝:https://www.rust-lang.org/zh-CN/tools/install
    同時也會安裝 cargo,他是 Rust 的構(gòu)建工具和包管理器。對于 web 前端來說相當(dāng)于 npm 這樣的工具。

  2. 安裝 wasm-pack,他是上文提到的把 rust 程序編譯包裝成 wasm 組件的工具。
    同樣按照 wasm-pack 官網(wǎng)的方法安裝:https://rustwasm.github.io/wasm-pack/installer/

  3. 使用 wasm 模板
    使用 wasm-pack 提供的模板可以快速生成 rust 的 wasm 項目。

cargo generate --git https://github.com/rustwasm/wasm-pack-template


輸入希望的項目目錄名稱,將新建目錄并在其中生成項目。

在目錄下我們可以看到幾個文件,其中一個是 Cargo.toml ,這個是 rust 項目的描述文件,對于 web 前端來說相當(dāng)于 package.json 文件。

項目目錄下還有一個 src 目錄,里面有 lib.rs 和 utils.rs 兩個文件,其中 lib.rs 這個文件就是我們主要的邏輯入口,他引用了 wasm-bindgen 庫來輸出暴露給外部調(diào)用的接口,在函數(shù)之前加上#[wasm_bindgen]可以讓外部調(diào)用這個方法。

編譯項目

本來 rust 的項目編譯用的是 cargo build 的命令,但是我們這里是希望編譯 wasm 組件,所以用的是 wasm-pack build 命令。

執(zhí)行后會在項目目錄下的 pkg 目錄下生成編譯后的產(chǎn)品,是一個 npm 包的結(jié)構(gòu)。需要調(diào)用這個組件的邏輯只需要像其他公共包一樣 import 就可以使用了。

實戰(zhàn)

以上的就是 wasm-pack 官方的教程,還有其他組件測試、發(fā)布等的流程先不在這里介紹了。以下用一個實際開發(fā)中的模塊來說一下開發(fā) wasm 組件過程中遇到的問題和解決方法。

背景

需要使用的 wasm 組件是一個優(yōu)化3D模型的方法,傳入一個模型的頂點信息和距離閾值,比較每個頂點位置之間的距離,如果沒達到閾值距離就合并這兩個頂點,以達到減少頂點的優(yōu)化目的。

原邏輯是使用 javascript 編寫的,在模型頂點數(shù)量比較多的時候執(zhí)行的時間比較長。這種大量計算的情況就很適合使用 wasm 來處理。

數(shù)據(jù)傳遞

頂點信息是存儲在一個 Float32Array 的數(shù)組中的,而 wasm 設(shè)計上除了 int 和 float 類型(對應(yīng) javascript 就是 number 類型)可以直接傳遞外,其他的類型都通過地址來傳遞。這對我們的程序來說是好消息,因為頂點信息的數(shù)據(jù)非常多,如果以值傳遞,就需要做數(shù)據(jù)復(fù)制,這個過程消耗的時間可能比我們換成 wasm 處理減
少的時間還要多。得益這個特點,我們的入?yún)⒖梢灾苯觽魅搿?/p>

/*---  rust ----*/

// rust 獲取 javasctipt 數(shù)據(jù)
pub fn add_attribute(&mut self, attribute: &Float32Array, item_size: u32) {
    self.attributes.push(BufferAttribute {
        array: attribute.to_vec(),
        item_size,
    });
}


/*---  javascript ----*/

// javascript 傳遞數(shù)據(jù)到 rust
for (const name of attributeNames) {
  const attr = attrArrays[name]
  bg.add_attribute(attr.array, attr.itemSize)
}


而計算后的結(jié)果,wasm 也提供了返回數(shù)組的指針和數(shù)組長度的方法,javascript 可以讀取 wasm 的內(nèi)存空間,根據(jù)這兩個值構(gòu)造新的頂點信息Float32Array。

/*---  rust ----*/

// 返回指定數(shù)據(jù)的內(nèi)存指針位置
pub fn get_attribute_ptr(&self, index: usize) -> *const f32 {
  self.attributes[index].array.as_ptr()
}

// 返回指定數(shù)據(jù)的長度
pub fn get_attribute_length(&self, index: usize) -> usize {
  self.attributes[index].array.len()
}


/*---  javascript ----*/

// javascript 或取 rust 內(nèi)存空間中的指定部分,構(gòu)建Float32Array
const ptr = bg.get_attribute_ptr(i)
const length = bg.get_attribute_length(i)

const buffer = new attr.array.constructor(wasm.getMemory().buffer, ptr, length)


數(shù)據(jù)類型

合并頂點計算的邏輯中,有一段是這樣的:每個頂點的位置、UV等信息,經(jīng)過給定的精度計算后,生成一個特征值,之后比較每個頂點的特征值,如果是相同的話就表示這兩個頂點可以合并。

原 javascript 版本的代碼是逐個信息按順序,加上分隔號,拼成一個字符串。

rust 版本的代碼如果也按同樣的方法處理,因為頂點的信息量是不定的,有可能只有位置信息,也有可能有UV、法線、顏色等信息,所以生成的特征值字符串長度也不確定。

rust 對於可變長度的字符串使用 String 類型,每次對字符串使用push_str方法增加內(nèi)容。得到的結(jié)果 wasm 版本的執(zhí)行速度跟 javascript 版本相差不大,甚至在某些情況下耗時還更多,經(jīng)過逐個過程作排查,發(fā)現(xiàn)是在生成特征值和在表中查詢特征值這個過程中花費的時間比較多。

根據(jù)程序的意圖,特征值并不一定要是字符串,只需要在不同輸入值的時候能夠輸出相關(guān)的值就可以,這跟生成 hash 值的需求是一樣的,于是考慮將特征值生成替換成 hash 值計算。

因為在存儲特征值的表使用了std::collections::hash_map類型,于是 hash 值也使用了其下的std::collections::hash_map::DefaultHasher類來計算

use std::collections::hash_map::DefaultHasher;

...

let mut hasher = DefaultHasher::new();

for j in 0..self.attributes.len() {
  ...

  let value = (attr.array[i * attr.item_size as usize + index as usize]
    * self.shift_multiplier)
    .trunc() as i32;
    
  hasher.write_i32(value);
    
  ...
}

let hash = hasher.finish();


需要注意的是對寫入不同類型的內(nèi)容,需要調(diào)用不同的方法,頂點信息中的值是正負值都用,經(jīng)過精度計算后取整得到的值類型是i32,所以用write_i32來寫入內(nèi)容。

生成的 hash 值為u64,作為hash_mapkey記錄對應(yīng)頂點的序號。

替換特征值的類型之后,wasm 版本的耗時達到了 javascript 版本的 1/2,基本符合 wasm 設(shè)計的性能范圍。

適配打包工具

wasm-pack 工具打包出來的 npm 包,可以直接在webpack下加載并調(diào)用運行。

我們原本的項目使用 vite 構(gòu)建,vite 對import wasm 組件策略和 webpack 的不一樣,vite 加載會返回一個加載方法,調(diào)用加載方法會返回一個 Promise,resolve 后才會返回跟 webpack 加載一樣的 wasm 組件。

我們要對 wasm-pack 生成的產(chǎn)物作一些修改,假設(shè)我們的 wasm 組件命名為 merge_vertice_wasm,生成的主 js 文件應(yīng)該會命名為merge_vertice_wasm.js,內(nèi)容如下:

import * as wasm from './merge_vertice_wasm_bg.wasm'
import { __wbg_set_wasm } as wasm_bg from './merge_vertice_wasm_bg.js'
__wbg_set_wasm(wasm);
export * from './merge_vertice_wasm_bg.js'


為兼容 vite 的加載策略,修改成下面的內(nèi)容

import * as wasm from './merge_vertice_wasm_bg.wasm'
import * as wasm_bg from './merge_vertice_wasm_bg.js'

let memory
if (wasm.default) {
  wasm.default({
    './merge_vertice_wasm_bg.js': wasm_bg,
  }).then(_wasm => {
    memory = _wasm.memory
    wasm_bg.__wbg_set_wasm(_wasm)
  })
} else {
  memory = _wasm.memory
  wasm_bg.__wbg_set_wasm(wasm)
}
export * from './merge_vertice_wasm_bg.js'

export function getMemory() {
  return memory
}


就可以在 webpack 和 vite 下都可以順利加載并運行了。

其中增加了getMemory的方法供外部獲取 wasm 組件的內(nèi)存空間。

wasm調(diào)用javascript方法

當(dāng)我們在調(diào)試和測試性能表現(xiàn)時,需要打印日志,由于我們的 wasm 跑在瀏覽器環(huán)境中,我們需要調(diào)用 javascript 的方法,比如console.logconsole.time

wasm-bindgen 庫提供了 web-sys 的組件,讓 rust 可以調(diào)用這些方法。

首先需要在cargo.toml中添加 web-sys 的依賴,并聲明需要用到的特性:

[dependencies]
wasm-bindgen = "0.2.84"

[dependencies.web-sys]
version = "0.3.64"
features = ["console"]


這樣在下次編譯的時候,cargo 就會自動處理這些依賴,將會下載并構(gòu)建。

然后在我們的 rust 文件中,加入對 web-sys 的引用:

extern crate web_sys;


就可以調(diào)用 javascript 的 console 下的方法了:

// 調(diào)用console.log
web_sys::console::log_1(&JsValue::from(logContent));

// 調(diào)用console.time(label)
web_sys::console::time_with_label(label);

// 調(diào)用console.timeEnd(label)
web_sys::console::time_end_with_label(label);


原 javascript 版本優(yōu)化模型耗時:

wasm 版本優(yōu)化模型耗時:

總結(jié)

以上為根據(jù)官網(wǎng)文檔把模型合并頂點優(yōu)化方法遷移為 wasm 版本的開發(fā)經(jīng)歷,從安裝工具到發(fā)布、調(diào)試的整個過程。

中間因為對 rust 數(shù)據(jù)類型的不熟悉和對不同前端構(gòu)建工具對 wasm 組件處理的不同不夠清晰,在開發(fā)過程中遇到的問題和解決方法。

rust 版本的代碼邏輯基本上是從 javascript 版本翻譯過來的,其中應(yīng)該還有在 rust 環(huán)境下的優(yōu)化手段,將在之后的學(xué)習(xí)中繼續(xù)迭代。

以上的完整代碼在http://xingyun.jd.com/codingRoot/LemonTea-lib/merge-vertice-wasm/倉庫,歡迎提優(yōu)化修改建議。

引用

rust 官方文檔:https://doc.rust-lang.org/book/

rust wasm 官方介紹文檔:https://rustwasm.github.io/docs/book/

wasm-pack 官方文檔:https://rustwasm.github.io/docs/wasm-pack/

作者:京東零售?胡俊文

來源:京東云開發(fā)者社區(qū) 轉(zhuǎn)載請注明來源文章來源地址http://www.zghlxwxcb.cn/news/detail-748258.html

到了這里,關(guān)于給 Web 前端工程師看的用 Rust 開發(fā) wasm 組件實戰(zhàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • uniapp打包微信小程序詳細步驟【前端開發(fā)】,web前端開發(fā)工程師

    uniapp打包微信小程序詳細步驟【前端開發(fā)】,web前端開發(fā)工程師

    II.打包發(fā)布 1?? 獲取微信小程序id: 首先,登錄微信公眾平臺,查看自己 微信小程序的id號并復(fù)制 : 2?? 填寫自己的小程序id: 打開uniapp自己的工程文件,選擇 manifest.json文件-微信小程序配置 ,黏貼自己的小程序id: 3?? 發(fā)布: 選中 發(fā)行-小程序-微信 之后出現(xiàn)下面的

    2024年04月27日
    瀏覽(24)
  • 初級web前端開發(fā)工程師的崗位職責(zé)描述(合集)

    初級web前端開發(fā)工程師的崗位職責(zé)描述(合集)

    ? 初級web前端開發(fā)工程師的崗位職責(zé)描述1 職責(zé): 1. 根據(jù)功能需求設(shè)計編寫頁面原型; 2. 前后端聯(lián)調(diào)保證功能流暢; 3. 提高頁面易用性、美觀提出合理建議。 4、與后臺工程師配合開發(fā)聯(lián)調(diào)并交付產(chǎn)品; 5、持續(xù)優(yōu)化前端頁面體驗和訪問速度,保證頁面精美高效。 任職要求 1、

    2024年02月14日
    瀏覽(27)
  • 程序員在職場中如何讓自己的技能快速提高,WEB前端開發(fā)工程師如何讓自己快速成為團隊的核心開發(fā)人員?

    今天聊一聊 就是我們在工作中就實際的 工資里面 寫代碼的過程中怎么提高自己的 一些技能 以及我們怎么樣快速成為 就是一個團隊的核心開發(fā)人 包括我以前 其實我也是一個小迷弟 后來就是慢慢慢慢 包括經(jīng)歷一些項目什么東西 其實現(xiàn)在已經(jīng)慢慢成為核心開發(fā)人員 就是分享

    2023年04月16日
    瀏覽(26)
  • 前端開發(fā)工程師

    ? ? 前端開發(fā)工程師,又叫web前端開發(fā)工和師,在國外早就有此職業(yè),我國在2000年后開始興起互聯(lián)網(wǎng),也就是在此時段開始,我國 慢慢的就有了前端開發(fā)這個職業(yè),慢發(fā)展進程持續(xù)到2013年2014年以后,前端開發(fā)工程師這個職業(yè)最終被重視,于是市場上便逐漸大量出現(xiàn)各類IT職

    2024年02月01日
    瀏覽(24)
  • 成為一名高級前端開發(fā)工程師

    前后端面試題庫 (面試必備) 推薦:★★★★★ 地址:前端面試題庫??web前端面試題庫 VS java后端面試題庫大全 隨著互聯(lián)網(wǎng)技術(shù)的不斷發(fā)展,前端開發(fā)已經(jīng)成為了一項非常重要的職業(yè)。如果您希望成為一名高級前端開發(fā)工程師,那么以下幾點建議可能會對您有所幫助。 1

    2024年02月12日
    瀏覽(25)
  • 淺談ChatGPT取代前端開發(fā)工程師

    淺談ChatGPT取代前端開發(fā)工程師

    1.ChatGPT 是什么? ChatGPT 是一種基于深度學(xué)習(xí)的自然語言處理技術(shù),它可以生成高質(zhì)量的自然語言文本。該技術(shù)是由 OpenAI 團隊 開發(fā),旨在使計算機能夠像人類一樣理解和產(chǎn)生自然語言。ChatGPT 使用了深度神經(jīng)網(wǎng)絡(luò)和自然語言處理技術(shù),通 過對大量語言數(shù)據(jù)的學(xué)習(xí)和建模,實現(xiàn)

    2023年04月08日
    瀏覽(17)
  • 50道web前端工程師面試題及答案解析,你學(xué)會了嗎

    50道web前端工程師面試題及答案解析,你學(xué)會了嗎

    簡介:本文包含了50個實用的前端面試題及答案解析,涵蓋了HTML、CSS、JavaScript、DOM、Ajax、MVC、模塊化、ES6、SPA、Webpack、Babel、Virtual DOM、響應(yīng)式設(shè)計、移動優(yōu)先設(shè)計、響應(yīng)式圖片、CSS 預(yù)處理器、后處理器、模塊化、布局、盒模型、浮動、定位、動畫、選擇器、HTML5、WebGL、

    2024年02月02日
    瀏覽(23)
  • HTML5前端開發(fā)工程師的崗位職責(zé)說明(合集)

    HTML5前端開發(fā)工程師的崗位職責(zé)說明(合集)

    ? HTML5前端開發(fā)工程師的崗位職責(zé)說明1 職責(zé) 1、根據(jù)產(chǎn)品設(shè)計文檔和視覺文件,利用HTML5相關(guān)技術(shù)開發(fā)移動平臺的web前端頁面; 2、基于HTML5.0標準進行頁面制作,編寫可復(fù)用的用戶界面組件; 3、持續(xù)的優(yōu)化前端體驗和頁面響應(yīng)速度,并保證兼容性和執(zhí)行效率; 4、配合后臺工程師

    2024年02月15日
    瀏覽(21)
  • 程序員必須掌握哪些算法?——前端開發(fā)工程師需要掌握的算法

    程序員必須掌握哪些算法?——前端開發(fā)工程師需要掌握的算法

    一個程序員一生中可能會邂逅各種各樣的算法,但總有那么幾種,是作為一個程序員一定會遇見且大概率需要掌握的算法。作為一名前端開發(fā)工程師,今天就通過這個話題和文章來聊聊前端開發(fā)工程師需要掌握的算法有哪些呢。 算法(Algorithm) 是指解題方案的準確而完整的

    2024年02月15日
    瀏覽(96)
  • mongodb安裝教程(圖解+鏈接,輕松拿到了阿里前端高級開發(fā)工程師的offer

    mongodb安裝教程(圖解+鏈接,輕松拿到了阿里前端高級開發(fā)工程師的offer

    4.測試是否安裝成功 進入C:Program FilesMongoDBServer3.4bin文件夾下,點擊mongod.exe,如果閃一下退出,說明安裝正常 5.安裝服務(wù) 用管理員權(quán)限打開cmd命令行,輸入如下命令安裝mongodb服務(wù) sc create MongoDB binPath= “C:Program FilesMongoDBServer3.4binmongod.exe --service --config=D:mongodbmongo.co

    2024年04月09日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包