一開始也糾結過要用Go還是Rust或者Swift的,后來發現Go目前還不支持編譯到WebAssembly,Swift按理說應該可以支持的,因為都是用LLVM做的編譯器,不過沒有找到好的資料,好像說要自己編譯LLVM去支持https://stackoverflow.com/questions/46572144/compile-swift-to-webassembly 。另外對Rust的一些特性很是喜歡,聽說Rust很復雜,比較像Scala和Haskell,而偏偏我對Scala還算熟悉,也學過一下Haskell,所以決定嘗試一下Rust。
https://github.com/ChristianMurphy/compile-to-web 這里可以查看目前能編譯到WebAssembly的語言。
PS, 話說asm.js和Rust都是Mozilla搞的呢。
安裝Rust的管理工具rustup
rustup用于安裝管理Rust的相關工具,包括編譯器rustc、包管理工具cargo等,支持安裝不同版本比如stable, beta, nightly等以及在不同版本之間切換,類似于nvm。
curl https://sh.rustup.rs -sSf | sh
安裝Emscripten Rust編譯器
用rustup安裝最新體驗版(Nightly Version):
rustup toolchain add nightly rustup target add wasm32-unknown-emscripten --toolchain nightly
安裝cmake
根據平臺自行選擇:
brew install cmake # MacOS, brew sudo port install cmake # MacOS, MacPorts sudo apt-get install cmake # Debian Linux
安裝 Emscripten
參考前一篇,或者直接執行下面命令:
wget https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz tar -xvf emsdk-portable.tar.gz cd emsdk-portable ./emsdk update ./emsdk install sdk-incoming-64bit
這一步花的時間比較久,據說要2個多小時,我是執行完命令就出去跟朋友吃飯了,所以具體時間不知道。
添加下列路徑到PATH中:
~/emsdk-portable ~/emsdk-portable/clang/fastcomp/build_incoming_64/bin ~/emsdk-portable/emscripten/incoming
終端執行emcc -v檢查是否安裝成功。
用Webpack運行Rust
新建一個Rust/Javascript混合項目:
cargo new webasm --bin --vcs none cd webasm npm init rustup override set nightly
安裝Webpack, webpack-dev-server, rust-wasm-loader,
npm i -D webpack webpack-dev-server rust-wasm-loader
增加package.json腳本:
{ "name": "webasm", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "compile": "webpack --progress", "serve": "http-server", "start": "webpack-dev-server --content-base ./build" }, "author": "magicly", "license": "ISC", "devDependencies": { "http-server": "^0.10.0", "rust-wasm-loader": "^0.1.2", "webpack": "^3.6.0", "webpack-dev-server": "^2.8.2" } }
在build目錄下新建文件index.html:
<!DOCTYE html> <html> <head> <title>Hello WebAssembly</title> </head> <body> < div id="container"></div> <script src="/bundle.js"></script> </body> </html>
配置webpack.config.js:
module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: dirname + '/build', }, module: { rules: [ { test: /\.rs$/, use: { loader: 'rust-wasm-loader', options: { <span>// The path to the webpack output relative to the project root</span> path: '', release: true <span>// 沒有的話性能巨差,差不多只有1/10</span> } } } ] }, <span>// The .wasm 'glue' code generated by Emscripten requires these node builtins,</span> <span>// but won't actually use them in a web environment. We tell Webpack to not resolve those</span> <span>// require statements since we know we won't need them.</span> externals: { 'fs': true, 'path': true, } }
新建src/main.rs文件,添加我們要從js中調用的函數:
fn main() { println!("Hello, world!"); } <span>// Functions that you wish to access from Javascript</span> <span>// must be marked as no_mangle</span> #[no_mangle] pub fn add(a: i32, b: i32) -> i32 { return a + b }
新建src/index.js,寫代碼加載WebAssembly模塊:
const wasm = require('./main.rs') wasm.initialize({ noExitRuntime: true }).then(module => { <span>// Create a Javascript wrapper around our Rust function</span> const add = module.cwrap('add', 'number', ['number', 'number']) console.log('Calling rust functions from javascript!') console.log(add(1, 2)) })
然后執行npm start,訪問http://localhost:8080/就可以看到調用rust代碼的效果了。并且還支持熱更新哦,直接修改rust代碼,保存,頁面就能看到最新效果。
測試了一下前一篇里的代碼,直接運行rust優化過的代碼只需要300多ms,這個基本跟C代碼一樣,但是用wasm運行,居然要2.7s左右,不知道是哪里沒有配置好,還是說現在Rust編譯成wasm沒有優化好。Rust支持WebAssembly應該還不是特別成熟,可以關注https://github.com/rust-lang/rust/issues/38804 跟進。
另外Rust有一個包https://crates.io/crates/webplatform, 可以用來操作DOM,不過我目前用不到(感覺沒啥用)
以上文章就是我對于WEB的高性能計算的理解,希望能幫助到有需要的朋友,之前也有倆篇文章《asm.js & webassembly-WEB的高性能計算》,《asm.js & webassembly-WEB的高性能計算》,有需要的朋友可以去看一下。
推薦閱讀:
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com