首頁  >  文章  >  web前端  >  Rust -> asm.js & webassembly-WEB的高效能運算

Rust -> asm.js & webassembly-WEB的高效能運算

php中世界最好的语言
php中世界最好的语言原創
2017-11-18 15:18:502907瀏覽

我們之前說過,對於javascript來言,前端的世界千變萬化。前幾篇文章給大家說過用Emscripten來編譯C語言然後用到asm.js和WebAssembly,這種方法是可以始前端程式碼的執行速度提升很大,但是由於在實際的項目裡C語言缺乏很多高階特性,很多功能沒辦法實現,不利於開發大型的項目,而C++又太過於複雜,所以最後我選擇了用Rust。

一開始也糾結過要用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: &#39;./src/index.js&#39;,
  output: {
    filename: &#39;bundle.js&#39;,
    path: dirname + &#39;/build&#39;,
  },
  module: {
    rules: [
      {
        test: /\.rs$/,
        use: {
          loader: &#39;rust-wasm-loader&#39;,
          options: {
            <span>// The path to the webpack output relative to the project root</span>
            path: &#39;&#39;,
            release: true <span>// 没有的话性能巨差,差不多只有1/10</span>
          }
        }
      }
    ]
  },
  <span>// The .wasm &#39;glue&#39; code generated by Emscripten requires these node builtins,</span>
  <span>// but won&#39;t actually use them in a web environment. We tell Webpack to not resolve those</span>
  <span>// require statements since we know we won&#39;t need them.</span>
  externals: {
    &#39;fs&#39;: true,
    &#39;path&#39;: 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(&#39;./main.rs&#39;)
 
wasm.initialize({ noExitRuntime: true }).then(module => {
  <span>// Create a Javascript wrapper around our Rust function</span>
  const add = module.cwrap(&#39;add&#39;, &#39;number&#39;, [&#39;number&#39;, &#39;number&#39;])
  
  console.log(&#39;Calling rust functions from javascript!&#39;)
  console.log(add(1, 2))
})

然後執行npm start,訪問http: //localhost:8080/就可以看到呼叫rust程式碼的效果了。並且也支援熱更新哦,直接修改rust程式碼,儲存,頁面就能看到最新效果。

Rust -> asm.js & webassembly-WEB的高效能運算

測試了一下前一篇裡的程式碼,直接執行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的高效能運算》,有需要的朋友可以去看一下。

推薦閱讀:

WebWorkers-前端的高效能運算


#

asm.js & webassembly-WEB的高效能運算


#JavaScript提交表單校驗三種方法分享

以上是Rust -> asm.js & webassembly-WEB的高效能運算的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn