WebAssemblyデモ

1.なに?


WebAssembly or wasm is a new portable, size- and load-time-efficient format suitable for compilation to the web.

Webへのコンパイルに適した、ポータブルで小型で高速読み込み(バイナリ)形式

主な目標は、Web環境で高性能アプリケーションをサポートすることです。ただし、この設計はWeb機能に依存せず、Web機能の機能も提供せず、他の環境でも使用できます。

簡単に理解できるのは、この形式をサポートする任意の環境でネイティブに近い実行パフォーマンスを実現できるコンパイルターゲット形式を定義することです。これは、ネイティブモジュールの拡張を許可することと同じです。パフォーマンスが重要なシナリオでは、他のより適切な言語(C ++など)を使用して実装し、事前にWebAssemblyにコンパイルすると、ネイティブに匹敵するパフォーマンスエクスペリエンスを得ることができます。

設計目標は2つの側面に分けられます。

高速、安全、ポータブルなセマンティクス

高速:ネイティブコードに近いパフォーマンスで実行し、最新のすべてのハードウェアに共通の機能を利用します

セキュリティ:データの破損やセキュリティ違反を防ぐために、コードはメモリセーフなサンドボックス環境で検証および実行されます

明確に定義されている:非公式および公式に簡単に推測できる方法で、法的手続きとその動作を完全かつ正確に定義する

ハードウェアに依存しない:すべての最新のアーキテクチャ、デスクトップまたはモバイルデバイス、および組み込みシステムでコンパイルします

言語に依存しない:特定の言語、プログラミングモデル、またはオブジェクトモデルへの偏りはありません

プラットフォームに依存しない:ブラウザに組み込んだり、スタンドアロンVMとして実行したり、他の環境に統合したりできます

オープン:プログラムは、シンプルで普遍的な方法で環境と対話できます

効率的でポータブルな表現

小さくて絶妙:バイナリ形式は通常のテキストまたはネイティブコード形式よりも小さく、すばやく送信できます

モジュール性:プログラムは小さな部分に分割でき、送信、キャッシュ、および個別に使用できます。

効率的:シングルパス(トラバーサル)ですばやくデコード、検証、コンパイルできます。これは、リアルタイム(JIT)または事前(AOT)コンパイルと同等です。

ストリーミング:すべてのデータが利用可能になる前に、できるだけ早くデコード、検証、およびコンパイルを開始できます

並列:デコード、検証、およびコンパイルを複数の独立した並列タスクに分割できます

移植性:最新のハードウェアで広くサポートされていないアーキテクチャについての仮定はありません

主要なブラウザ(Chrome、Edge、Firefox、およびWebKit)は、共同で標準化プロセスを推進しています。


WebAssembly is currently being designed as an open standard by a W3C Community Group that includes representatives from all major browsers.

PSこれは、ブラウザメーカー(4社が協力して作業を行うために協力しているので楽しみです)が主導しています。ちなみに、オープンスタンダード(Web環境だけでなく)は、V8でJSランタイムパフォーマンスをさらに向上させたいという願望から来ています。 JITの導入後は、JS言語の機能(解釈されたタイプや弱いタイプなど)の制限により、パフォーマンスをさらに向上させることはできません。Web機能はますます強力になり、クライアントJSはますます重くなり、JS実行パフォーマンスをさらに改善する必要性は依然として存在するため、WebAssemblyの収益があります。

2. WasmとwasWebAssembly
がバイナリ形式を定義していることはわかっています。この形式はwasmです。例:


0061 736d 0100 0000 0187 8080 8000 0160
027f 7f01 7f03 8280 8080 0001 0004 8480
8080 0001 7000 0005 8380 8080 0001 0001
0681 8080 8000 0007 9080 8080 0002 066d
656d 6f72 7902 0003 6763 6400 000a ab80
8080 0001 a580 8080 0001 017f 0240 2000
450d 0003 4020 0120 0022 026f 2100 2002
2101 2000 0d00 0b20 020f 0b20 010b 

この16進数の文字列に対応するCコードは次のとおりです。


// 辗转相除法求最大公约数
int gcd(int m, int n) {
    if (m == 0) return n;
    return gcd(n % m, m);
}

wasmの読みやすさは0です。この問題を軽減するために、wastと呼ばれる読みやすさの向上したテキスト形式が定義されています。


(module
 (table 0 anyfunc)
 (memory $0 1)
 (export "memory" (memory $0))
 (export "gcd" (func $gcd))
 (func $gcd (; 0 ;) (param $0 i32) (param $1 i32) (result i32)
  (local $2 i32)
  (block $label$0
   (br_if $label$0
    (i32.eqz
     (get_local $0)
    )
   )
   (loop $label$1
    (set_local $0
     (i32.rem_s
      (get_local $1)
      (tee_local $2
       (get_local $0)
      )
     )
    )
    (set_local $1
     (get_local $2)
    )
    (br_if $label$1
     (get_local $0)
    )
   )
   (return
    (get_local $2)
   )
  )
  (get_local $1)
 )
)

括弧は少しLispスタイルですが、少なくとも次のように読みやすくなっています。

// 导出了两个东西,分别叫`memory`和`gcd`
(export "memory" (memory $0))
(export "gcd" (func $gcd))
// 函数签名,接受2个int32类型参数,返回int32类型值
(func $gcd (; 0 ;) (param $0 i32) (param $1 i32) (result i32)
// 函数体...就不猜了

PSwastとwasmは相互に変換できます。詳細については、WABT:WebAssembly BinaryToolkitを参照してください。

さらに、ブラウザの[ソース]パネルに別のテキストコマンドが表示されます。


func (param i32 i32) (result i32)
(local i32)
  block
    get_local 0
    i32.eqz
    br_if 0
    loop
      get_local 1
      get_local 0
      tee_local 2
      i32.rem_s
      set_local 0
      get_local 2
      set_local 1
      get_local 0
      br_if 0
    end
    get_local 2
    return
  end
  get_local 1
end

無駄によく似ていますが、名前があるかどうかわかりませんか、それとも無駄に属していますか?これは、wasmに基づいてブラウザによって変換されます

3.トライアルプレイ環境の
環境要件:

C / C ++コンパイル環境Emscripten

WebAssemblyをサポートするブラウザ(最新のChromeはデフォルトでサポートしています)

オンライン環境は
害を及ぼしますか?デモ環境:WebAssembly Explorer

コンパイルとダウンロードは無駄になる可能性があり、使いやすいです

デフォルトはC ++環境であることに注意してください。Cを使用する場合は、左側でC99またはC89を選択します。そうしないと、C ++ 11の無駄など、関数名が破損します。


(module
 (table 0 anyfunc)
 (memory $0 1)
 (export "memory" (memory $0))
 (export "_Z3gcdii" (func $_Z3gcdii))
 (func $_Z3gcdii (; 0 ;) (param $0 i32) (param $1 i32) (result i32)
  (local $2 i32)
  (block $label$0
   (br_if $label$0
    (i32.eqz
     (get_local $0)
    )
   )
   (loop $label$1
    (set_local $0
     (i32.rem_s
      (get_local $1)
      (tee_local $2
       (get_local $0)
      )
     )
    )
    (set_local $1
     (get_local $2)
    )
    (br_if $label$1
     (get_local $0)
    )
   )
   (return
    (get_local $2)
   )
  )
  (get_local $1)
 )
)

関数名は_Z3gcdiiにまとめられています。名前のようなものが問題を引き起こしていると推測されます。私はC ++に慣れていないので、素直にCを使用します。

PS C / C ++に加えて、Rustなどの他の言語もWebAssemblyを再生できます

ローカル環境
用のプラットフォームSDKをダウンロードする

インストール手順に従います

他に何もない場合は、ここにインストールできます。emcc-vを試すことができます。


INFO:root:(Emscripten: Running sanity checks)
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 1.37.22
clang version 4.0.0  (emscripten 1.37.22 : 1.37.22)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: D:\emsdk-portable-64bit\clang\e1.37.22_64bit
INFO:root:(Emscripten: Running sanity checks)

Windows環境では、DLLが見つからない(MSVCP140.dll)エラーが発生する場合があります。必要なC ++環境を手動でインストールできます。詳細については、MSVCP140.dllが見つかりません・問題#5605・kripken / emscriptenを参照してください。

次に、試してみることができます(前のCコードをファイルgcd.cとして保存します)。

emcc ./c/gcd.c -Os -s WASM=1 -s SIDE_MODULE=1 -s BINARYEN_ASYNC_COMPILATION=0 -o ./output/gcd.wasm

PSその他の使用法については、Emscriptenチュートリアルを参照してください。

gcd.wasmの内容は次のとおりです。


0061 736d 0100 0000 000c 0664 796c 696e
6b80 80c0 0200 010a 0260 027f 7f01 7f60
0000 0241 0403 656e 760a 6d65 6d6f 7279
4261 7365 037f 0003 656e 7606 6d65 6d6f
7279 0200 8002 0365 6e76 0574 6162 6c65
0170 0000 0365 6e76 0974 6162 6c65 4261
7365 037f 0003 0403 0001 0106 0b02 7f01
4100 0b7f 0141 000b 072b 0312 5f5f 706f
7374 5f69 6e73 7461 6e74 6961 7465 0002
0b72 756e 506f 7374 5365 7473 0001 045f
6763 6400 0009 0100 0a40 0327 0101 7f20
0004 4003 4020 0120 006f 2202 0440 2000
2101 2002 2100 0c01 0b0b 0520 0121 000b
2000 0b03 0001 0b12 0023 0024 0223 0241
8080 c002 6a24 0310 010b 

デフォルトでは、メソッド名の前に下線(_)が付けられることに注意してください。この例では、エクスポートされるメソッド名は_gcdです。詳細については、「コードとの対話」を参照してください。


The keys passed into mergeInto generate functions that are prefixed by _. In other words myfunc: function() {}, becomes function _myfunc() {}, as all C methods in emscripten have a _ prefix. Keys starting with $ have the $ stripped and no underscore added.

JSで使用されるモジュールインターフェイスには下線を引く必要があります(削除できる構成アイテムがあるかどうかはわかりません)

4.試してみてください


WebAssembly.compile(new Uint8Array(`
    0061 736d 0100 0000 0187 8080 8000 0160
    027f 7f01 7f03 8280 8080 0001 0004 8480
    8080 0001 7000 0005 8380 8080 0001 0001
    0681 8080 8000 0007 9080 8080 0002 066d
    656d 6f72 7902 0003 6763 6400 000a ab80
    8080 0001 a580 8080 0001 017f 0240 2000
    450d 0003 4020 0120 0022 026f 2100 2002
    2101 2000 0d00 0b20 020f 0b20 010b 
    `.match(/\S{2}/g).map(s => parseInt(s, 16))
)).then(module => {
    const instance = new WebAssembly.Instance(module);
    console.log(instance.exports);
    const { gcd } = instance.exports;
    console.log('gcd(328, 648)', gcd(328, 648));
});

16進文字列は、元のwasmの例と一致するオンラインデモからのものです。これらをChromeのコンソールに貼り付けて実行するだけです。すべてが正常な場合は、次のエラーが発生します。


VM40:1 Uncaught (in promise) CompileError: WasmCompile: Wasm code generation disallowed in this context

これは、デフォルトのCSP(コンテンツセキュリティポリシー)の制限を簡単に解決できるためです。インコグニートモードをオンにするだけです(Ctrl / CMD + Shift + N)

出力を取得します:


{memory: Memory, gcd: ƒ}
gcd(328, 648) 8

最初の行は、メモリオブジェクトとgcdメソッドを含む、WebAssemblyをロードして取得したモジュールのエクスポートコンテンツであり、2行目の出力は、高性能モジュールを呼び出して計算された最大の一般的な除数です。

WebAssembly.compileおよびその他の関連APIは、以下を参照できます。

JavaScript API-WebAssembly:仕様の定義

WebAssembly-JavaScript | MDN:例が含まれています

さらに、ローカルでコンパイルされたバージョンでは、imports envが必要です(関数名の前には下線_が付いています)。


WebAssembly.compile(new Uint8Array(`
    0061 736d 0100 0000 000c 0664 796c 696e
    6b80 80c0 0200 010a 0260 027f 7f01 7f60
    0000 0241 0403 656e 760a 6d65 6d6f 7279
    4261 7365 037f 0003 656e 7606 6d65 6d6f
    7279 0200 8002 0365 6e76 0574 6162 6c65
    0170 0000 0365 6e76 0974 6162 6c65 4261
    7365 037f 0003 0403 0001 0106 0b02 7f01
    4100 0b7f 0141 000b 072b 0312 5f5f 706f
    7374 5f69 6e73 7461 6e74 6961 7465 0002
    0b72 756e 506f 7374 5365 7473 0001 045f
    6763 6400 0009 0100 0a40 0327 0101 7f20
    0004 4003 4020 0120 006f 2202 0440 2000
    2101 2002 2100 0c01 0b0b 0520 0121 000b
    2000 0b03 0001 0b12 0023 0024 0223 0241
    8080 c002 6a24 0310 010b 
    `.match(/\S{2}/g).map(s => parseInt(s, 16))
)).then(module => {
    let imports = {
        env: {
            memoryBase: 0,
            memory: new WebAssembly.Memory({ initial: 256 }),
            tableBase: 0,
            table: new WebAssembly.Table({ initial: 0, element: 'anyfunc' })
        }
    };
    const instance = new WebAssembly.Instance(module, imports);
    console.log(instance.exports);
    // 注意下划线前缀
    const { _gcd } = instance.exports;
    console.log('gcd(328, 648)', _gcd(328, 648));
});

同様の出力を得ることができます:


{__post_instantiate: ƒ, runPostSets: ƒ, _gcd: ƒ}
gcd(328, 648) 8

Emscriptenがデフォルトでいくつかの無関係なものを追加しているはずです。これは、機能的には簡略化されたバージョンと同等です。

V.
長所、短所、およびアプリケーションシナリオ
コードサイズが小さい

約300k(圧縮)のJavaScriptロジックがWebAssemblyで書き直され、ボリュームは約90kです。

ただし、WebAssemblyを使用するには、インフラストラクチャとして50k〜100kのJavaScriptクラスライブラリを導入する必要があります。

セキュリティがわずかに改善されました

ソースコードに対応するWebAssemblyテキスト命令はまだ隠されていませんが、逆のコストは高くなります

パフォーマンスの向上

理論的には、WebAssemblyは解釈プロセスをスキップするため、ネイティブの実行パフォーマンスに近く、ファイルサイズには送信の点でも利点があります。

もちろん、ビジネスコードの量が多く、極端なパフォーマンスが必要なシナリオでは、ベンチマークなどの繰り返し実行シナリオでは、JITはAOTよりもそれほど遅くないことが前提です。


現在容量が制限されているデメリット

いくつかの基本的なデータタイプのみがサポートされています(i32 / i64 / f32 / f64 / i8 / i16)

DOMやその他のWebAPIに直接アクセスすることはできません

GCを制御できません

アプリケーションシナリオ
WebAssemblyは、ブラウザ用の標準の実行可能なバイナリ形式を定義しているため、より多くの開発者が統合されたコンパイルメカニズムを介して参加し、繁栄するWebエコシステムを構築できます。ビジョンは良好ですが、実際的な問題がいくつかあります。

まず、WebAssemblyの本来の目的は、「Web環境で高性能アプリケーションをサポートする」ことです。パフォーマンスのボトルネックを打破するために考えられるアプリケーションシナリオは次のとおりです。

ビデオデコード

画像処理

3D / WebVR / ARの視覚化

レンダリングエンジン

物理エンジン

圧縮/暗号化アルゴリズム

…計算量の多いシーンなど

もちろん、将来的には、「拡張機能」などを使用する代わりに、一部のサポートがブラウザに組み込まれる可能性もあります。しかし、WebAssemblyの本当の意味は、高性能の「ネイティブ」モジュールの自己拡張を可能にする機能を提供することです。結局のところ、ブラウザーがそれを提供するのを待って、互換性が受け入れられるまで待つのに長い時間がかかる場合があります。この機能を使用すると、市場に出回っている主流のブラウザが特定のネイティブ機能をサポートするのを待つ必要はありません。自分でそれを行うことができ、互換性の違いはありません。逆に、人気のあるコミュニティモジュールのバッチが出現し、ブラウザのネイティブサポートとして徐々に採用され、生態学的にWeb環境に還元される可能性があります。

参照
WebAssembly

実際のWebAssembly:コードの書き方:優れたガイド

ブラウザの最新のWebAssemblyバイトコードテクノロジーについてコメントするにはどうすればよいですか?

WebAssembly:JavaScriptの慢性的な問題を解決するための特効薬?

WebAssembly、Webの新時代

WebAssemblyをポリフィルすることはできますか?

wasm-arrays:WebAssemblyアレイパッケージングライブラリ

おすすめ

転載: blog.51cto.com/15080030/2592698