Design: WebAssembly.Instanceはすでにコンパイルされたモジュールを再コンパイルできますか?

作成日 2016年10月27日  ·  94コメント  ·  ソース: WebAssembly/design

私がこのコードを持っているとしましょう:

let descriptor = /* ... */;
let memories = Array.apply(null, {length: 1024}).map(() => new WebAssembly.Memory(descriptor));
let instance = fetch('foo.wasm')
  .then(response => response.arrayBuffer())
  .then(buffer => WebAssembly.compile(buffer))
  .then(module => new WebAssembly.Instance(module, { memory: memories[1023] }));

WebAssembly.Instanceはかなりの時間ブロックすることができますか? たとえば、 WebAssembly.Module再コンパイルできますか?

ほとんどの場合、私はノーと言いますが、すでにコンパイルされたコードが受け取るメモリを特に気に入らない場合はどうなりますか? たとえば、そのメモリは低速モードのメモリであり、コードは高速モードを想定してコンパイルされているためですか? memories[0]は高速モードのメモリだったかもしれませんが、 memories[1023]確かにそうではありません。

代わりに、このコードはどうですか?

let instances = [0,1,2,3,4,5,6,7].map(v => fetch(`foo${v}.wasm`)
  .then(response => response.arrayBuffer())
  .then(buffer => WebAssembly.compile(buffer))
  .then(module => new WebAssembly.Instance(module)));

WebAssembly.Instanceへのこれらの呼び出しは、再コンパイルを引き起こすことを許可されていますか?

上記が理にかなっていると仮定して、ここにいくつかの関連する質問があります:

  • コンパイルしてインスタンス化できるpromiseを返す非同期関数が必要ですか? すでに持っている同期APIと非同期APIのいずれかを削除する必要があると言っているのではなく、新しい非同期APIを提案しています。
  • コンパイルされたコードをWebAssembly.Moduleブラウザが公開するのはどのように高速であり、 WebAssembly.Memoryインスタンスはそのような高速コードに適していますか? 今のところ、答えは「試してみて、気付くかどうか確かめてください」のようです。
  • ユーザーは、スローコードを取得する前に許可されるWebAssembly.Memoryインスタンスの数をどのように知るのですか(たとえば、2番目の例で作成された暗黙のインスタンスを数えます)。
JS embedding

最も参考になるコメント

@kgryte私のコメントは、主に実行コンテキストとしてのブラウザに関係していることを明確にする必要がありました。 同期APIをまだ公開しているAPIサーフェスにたどり着きました。 ブラウザは、同期APIに渡されるモジュールにサイズ制限を課す場合があります(たとえば、Chromeはすでにそうしています)が、その制限は埋め込み者によって構成可能であり、ノードに適用する必要はありません。

全てのコメント94件

WebAssembly.Instanceが時々再コンパイルを引き起こすのは良いことです。このようにして、不変のグローバル変数を生成されたコードで定数畳み込みすることができます。 たとえば、Emscriptenは、静的データへのすべてのポインターをオフセットすることにより、再配置可能なコードを生成します。 モジュールがインスタンス化されると、オフセットは不変のグローバル変数として渡されます。 WebAssembly.Instanceが再コンパイルできる場合は、生成されたコードを特殊化できます。

仕様は「コンパイル」が何であるかを定義していませんし、それが作ることもありません
実装アプローチは大きく異なる可能性があるため、そうする意味があります
(通訳を含む)。 したがって、これについて規範的な発言をすることはできません
どちらにしても。 私たちができる最善のことは、次のようなメモを追加することです。
WebAssembly.Instanceは「高速」であることが期待されます。

3時24分に2016年10月27日、マイケル・Bebenita [email protected]
書きました:

WebAssembly.Instanceが時々再コンパイルを引き起こすのは良いことですが、
このようにして、不変のグローバル変数を生成されたもので定数畳み込むことができます
コード。 たとえば、Emscriptenは、すべてをオフセットすることによって再配置可能なコードを生成します
静的データへのポインタ。 オフセットは不変のグローバル変数として渡されます
モジュールがインスタンス化されたとき。 WebAssembly.Instanceが再コンパイルできる場合は、
生成されたコードを特殊化することができます。


このスレッドにサブスクライブしているため、これを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/WebAssembly/design/issues/838#issuecomment -256522163、
またはスレッドをミュートします
https://github.com/notifications/unsubscribe-auth/AEDOO9sJPgujK3k0f6P7laYV_zaJxES5ks5q3_1LgaJpZM4Kh1gM

これはせいぜい非規範的なメモであることに同意しました。

SMでは、現在、インスタンス化が再コンパイルされないようにすることも意図しています。これにより、開発者のコ​​ンパイルコストモデルが予測可能になります(特に、開発者がWebAssembly.compileとIDBを使用して、コンパイルがヒットするタイミングを制御できるようになります)。 。 同期Instanceコンストラクター内からのインスタンス化時の再コンパイルは、確かにそのコストモデルを破り、大きな問題につながる可能性があります。

しかし、個別のコンパイルは、生成されたコードをアンビエントパラメーターに特化するために実行したいさまざまな最適化と基本的に対立していることを理解しています。 コンパイルとインスタンス化を1つの非同期操作に融合することは理にかなっており、過去に検討したことです。 もちろん、欠点は、これが明示的なキャッシュを禁止することです( Moduleはありません)。そのため、開発者は不快なトレードオフを行う必要があります。 いくつかのオプション:

  • implは、現在FFにあるasm.jsで行うように、暗黙的なコンテンツアドレスキャッシュ(キーにアンビエントパラメーターを含めることができます)を実行できます。 これは一種の苦痛であり、暗黙のキャッシュのすべての予測可能性/ヒューリスティックな問題があります。
  • 新しい方法を作成できます(たとえば、バイトコードとインスタンス化パラメータを渡してPromise<Instance>を取得する新しいWebAssembly.Cache API。

後者は私に興味をそそられ、IDBを使用するよりもはるかに優れた開発者エクスペリエンスを提供し、おそらくキャッシュをさらに最適化する機会を提供する可能性があります(キャッシュは目的に特化しているため)が、それは確かに大きな機能であり、しばらく時間がかかりたいものです考慮する。

@ rossberg-chromium私は自分の目的をひどく説明したようです:私は仕様が何を言っているかについて口論したくありません。 私は、APIの下に隠れて、開発者にとって深刻な驚きのように見えることを指摘しようとしています。 開発者は、 .compileの結果が再コンパイルされることを期待しません。 それは私には設計上の欠陥のように思えます。

@lukewagnerは、暗黙的または明示的なキャッシュを使用しても、同じ問題が発生する可能性があります。同じアドレス空間/オリジンに作成できるWebAssembly.Memoryは、ブラウザーの制限です。 私はあなたが提案しているものが好きですが、それは問題に直交していると思います。 あなたの提案を誤解した場合はお知らせください。

たぶん.compileModule Memory与えることができ、 Instanceは他のコンパイル/インスタンス化に渡すことができる.memoryプロパティがあります?

再コンパイルの可能性を排除しようとはしていません。最初のコンパイル時(またはキャッシュ取得時)にMemoryで完全な情報を持つ一般的な慣用的なAPIの使用法が必要だと思います。コンパイルが境界チェックを発行するかどうか、必要に応じて。

@jfbastien特定のインスタンス化パラメーター(つまりMemory )が提供された暗黙的/明示的キャッシュでは、再コンパイルがどのように必要になるかわかりません。

@jfbastien特定のインスタンス化パラメーター(つまりMemory )が提供された暗黙的/明示的キャッシュでは、再コンパイルがどのように必要になるかわかりません。

あるかもしれません:

  1. 多くのMemory作成します。
  2. Memoryが多すぎるため、明示的な(遅い)境界チェックを使用してコードをコンパイルします。
  3. そのコードをキャッシュします。
  4. ページから出る。
  5. ページを再度読み込みます。
  6. Memory 1つだけ割り当てます。これにより、高速バージョンが取得されます。
  7. キャッシュから取得します。
  8. スローコードInstanceを受け取ります。

この時点で、再コンパイルは_必要ない_ことに同意しますが、必要のないときに低速境界チェックを行うのは少しばかげています。

私が言ったように:私はあなたが提案するこのCache APIが好きです、それはWebAssemblyをより使いやすくすると思います、しかし私は問題がまだそこにあると思います。 😢

それが、インスタンス化パラメーターとバイトコードを受け入れる拡張キャッシュを持つことについての私のポイントです。キャッシュしたものがインスタンス化パラメーターと一致しない場合、キャッシュは自由に再コンパイルできます。 したがって、手順は次のようになります。

  1. 多くのMemory作成します
  2. キャッシュからInstanceを要求し、それらの1つを渡します(遅い) Memory s
  3. スローコードはコンパイルされ、キャッシュされ、 Instanceとして返されます
  4. ページから出る
  5. ページを再度読み込む
  6. Memory 1つだけ割り当てます
  7. キャッシュからInstanceをリクエストし、高速のMemoryを渡します
  8. 高速コードはコンパイルされ、キャッシュされ、 Instanceとして返されます

ステップ8の後、今後のすべてのページの読み込みは、高速または低速のコードでキャッシュされます。

@lukewagnerまず第一に、決定論的なパフォーマンスを提供するWebAssemblyの目標に直面して飛ぶ緩和策を提案しています。 遅いと速いの違いは最後に約20%と見積もられていたので、決定論的なパフォーマンスを目指したスペックがAPIの癖のためにそれを床に落とした場合、それは本当に悪臭を放ちます。 プロファイル-再コンパイル-キャッシュの最適化の必要性を取り除くために、仕様はすでに他の場所で多くの問題を抱えているため、コンテンツアドレスキャッシュを備えたブラウザが正しい解決策であるとは思いません。 たとえば、コードがキャッシュされていない場合でもアプリが適切な動作を取得できるように、コンパイルを正確に約束します。 これが仕様化されている方法で、キャッシュやその他の緩和策を実装する必要がある場合、合理的に移植可能なコストモデルを人々に提供するという目標は達成できません。

私にとっての問題はこれだけです。競争上の理由で私たち全員が効果的に実行しなければならない最適化の1つ(4GB仮想メモリ境界チェック。これを4GBハックと呼びます)は、現在の仕様では犠牲にすることなく実行できません。これらのうちの1つ:

  • 常に4GBの仮想メモリをwasmメモリに割り当てると、それを回避できます。 これにより、小さなモジュールにWebAssemblyを使用することを思いとどまらせます。これらの多くを割り当てると、仮想メモリの割り当て制限、仮想メモリの断片化、またはその他の問題が発生するためです。 また、それらの多くを割り当てることを許可すると、ASLRのようなセキュリティ緩和策の効果が低下することも恐れています。 既存のAPIは、割り当てたメモリをコミットし、物理メモリで許可されているよりもはるかに多くを割り当てる前にOOMまたはクラッシュするため、この危険性を共有しないことに注意してください。
  • インスタンス化中に不一致が見つかったときに再コンパイルを許可すれば、それを回避できます(コンパイルされたコードは4GBのハックを必要としますが、メモリにはその仮想メモリ割り当てがありません)。 インスタンス化によってメモリが4GBの領域に移動された場合にも、それを回避することができますが、前のポイントを参照してください。 したがって、おそらくこれが発生するたびに、それが発生したブラウザのP1バグになります。

これは、この仕様により、ベンダーがwasmメモリが割り当てられたときに4GBの予約を許可するように収束するか、これを検出するためにキャッシュ/レイジーコンパイル/プロファイルの最適化を行うことを奨励すると思います。

最後に、私はこれを非規範的にすることについてのポイントを理解していません。 APIで、ブラウザがどのような種類のメモリを搭載するかを知らなくても何かをコンパイルしなければならない可能性を排除できるため、これは標準的な場合があります。 これを行うには多くの方法があると思います。 たとえば、インスタンス化するとpromiseが返され、個別のコンパイルステップが削除される可能性があります。 これにより、インスタンス化がしばらくかかる可能性のあるステップであることが明確になります。これは、これがコンパイルを実行するステップであることをクライアントに強く示唆します。 このようなAPIでは、コンパイラは、コンパイル対象のメモリに4GBのハッキングがあるかどうかを常に認識しています。

今気づいているのは悲しいことですが、これがもっと大きな問題だと思わないのは驚きです。 私が見落としているキャッシュ以外の緩和策はありますか?

やる気を起こさせるシナリオで

もしそうなら、キャッシングまたは非同期インスタンス化のこれらの代替手段はどのように感じますか?

  1. モジュールの作成者は、最小/最大メモリとして4GBを必要とします
  2. 高速メモリのみを受け入れるインスタンスを生成するコンパイルのバリアント(少なくとも非同期、場合によっては同期)。

「4GBハック」の問題と、それを使用するメモリとそれを予期するコードとの不一致について、コンパイルで2つのバージョンのコードを内部的に出力することは理にかなっていますか? (明らかに、これはより多くのメモリを使用しますが、これは悲しいことですが、コンパイル時間がそれほど悪くないことを願っています。ライターは両方を同時に生成できますか?)

@mtrofin 4GiBを使用するつもりがない場合、それを要求するのは意味がないと思います。 仮想割り当ては使用目的とは別なので、両方を分離する必要があると思います。

2について:それはまだ開発者にとってあまり役に立ちません:彼らがそのバリ​​アントを使用して失敗した場合、それではどうしますか?

@kripkenダブルコンパイルは良い考えではないと思います。

@kripkenこれは、この問題に対する他の解決策がなければ、私たちが行うことだと思います。

カジュアルなブラウジングの場合にWebAssemblyを優れたものにしたいと思います。クールなことについて教えてくれ、URLを送って、クリックして、数分間楽しんでください。 それがウェブをクールにするものです。 ただし、これは、多くのコンパイルがキャッシュされないコードであることを意味するため、コンパイル時間はユーザーのバッテリー寿命に大きな影響を及ぼします。 だから、ダブルコンパイルは私を悲しくさせます。

@mtrofin

モジュールの作成者は、最小/最大メモリとして4GBを必要とします

多くのデバイスには4GBの物理メモリがないため、これは実際には実用的ではありません。 また、それを特定するのは難しいです。

高速メモリのみを受け入れるインスタンスを生成するコンパイルのバリアント(少なくとも非同期、場合によっては同期)。

ダブルコンパイルは必要ないと思います。

@pizlonatorこれまで、

したがって、1つの観察結果は、4GBのハッキングによって許可される境界チェックの排除の大部分は、wasmメモリの最後に小さなガード領域を設けるだけで回避できるということです。 最初の実験では、基本的な分析(ループとは関係なく、同じベースポインターを使用したロード/ストアのチェックを削除するだけ)で、境界チェックの約半分をすでに削除できることが示されています。 そしておそらくこれは良くなるかもしれません。 したがって、4GBのハックは、より控えめで、必要性の少ない高速化になります。

私が以前に持っていたもう1つのアイデアは、境界チェックを使用してコードを悲観的にコンパイルし(ガードページに基づく除去を使用)、高速モードメモリでインスタンス化するときにそれらをnopすることでした。 組み合わせると、理想化された高速モードコードと比較してオーバーヘッドがかなり小さくなる可能性があります。

@lukewagner

これまで、さまざまなモードのcodegenを必要とする設計については検討していません。64ビットで常に4 GBの領域を割り当て、Linux、OSX、およびWindowsの何千ものメモリでこれが成功することを確認しました。 利用可能なアドレス空間がわずかに使い果たされるのを防ぐために、控えめな総数があります。これは、多数の小さなライブラリのユースケースをサポートするのに十分であると私は期待しています。 したがって、ここで対処している新しい制約は、iOSには4GBの割り当て数を減らす可能性のある仮想アドレス空間の制限があることだと思います。

これはiOS固有の問題ではありません。 問題は、そのような割り当てを多数許可すると、そのような割り当てごとにASLRの有効性が低下するため、セキュリティリスクが発生することです。 したがって、VMには、割り当てる4GBスペースの数に非常に低い制限を設定するオプションがあるはずですが、これは、フォールバックパスが高すぎない(つまり、再コンパイルが必要ない)ことを意味します。

割り当てる4GBメモリの数にはどのような制限がありますか? この制限に達したときはどうしますか?完全に諦めるか、インスタンス化時に再コンパイルしますか?

したがって、1つの観察結果は、4GBのハッキングによって許可される境界チェックの排除の大部分は、wasmメモリの最後に小さなガード領域を設けるだけで回避できるということです。 最初の実験では、基本的な分析(ループとは関係なく、同じベースポインターを使用したロード/ストアのチェックを削除するだけ)で、境界チェックの約半分をすでに削除できることが示されています。 そしておそらくこれは良くなるかもしれません。 したがって、4GBのハックは、より控えめで、必要性の少ない高速化になります。

分析によってより多くのチェックを排除できることに同意しますが、最高のパフォーマンスが必要な場合は4GBのハックが最適です。 誰もがピークパフォーマンスを望んでいます。セキュリティの問題、リソースの問題、予期しない再コンパイルを引き起こすことなく、ピークパフォーマンスを取得できるようにすると素晴らしいと思います。

私が以前に持っていたもう1つのアイデアは、境界チェックを使用してコードを悲観的にコンパイルし(ガードページに基づく除去を使用)、高速モードメモリでインスタンス化するときにそれらをnopすることでした。 組み合わせると、理想化された高速モードコードと比較してオーバーヘッドがかなり小さくなる可能性があります。

境界チェックのあるコードは、メモリサイズのレジスタを固定し、メモリベースのレジスタを固定するのが最善です。

4GBのハックを使用するコードは、メモリベースのレジスタを固定するだけで済みます。

したがって、これは優れたソリューションではありません。

仕様と実装を混乱させなければならないという煩わしさに加えて、コンパイルとインスタンス化を1つの約束されたアクションに組み合わせるデメリットは何ですか?

問題は、そのような割り当てを多数許可すると、セキュリティ上のリスクが発生することです。
割り当てにより、ASLRの有効性が低下します。

私はASLRの専門家ではありませんが、iiucは、控えめな限界がなかったとしても(つまり、カーネルがその数に達したためにmmap失敗するまで割り当てを続けることを許可した場合)アドレス範囲最大)、47ビットのアドレス可能なスペース全体のごく一部のみが消費されるため、コードの配置はこの47ビットのスペース全体で非常にランダムになります。 IIUC、ASLRコードの配置も完全にランダムではありません。 何かがどこにあるかを予測するのを難しくするのにちょうど十分です。

割り当てる4GBメモリの数にはどのような制限がありますか? 職業はなんですか
この制限に達したとき-完全に諦めますか、それともインスタンス化時に再コンパイルしますか?

まあ、それはasm.jsの日からなので、1000だけです。それからメモリ割り当てはただスローします。 これをぶつける必要があるかもしれませんが、同じプロセスを共有する多くの超モジュール化されたアプリ(それぞれに多くの個別のwasmモジュールがある)でも、これ以上必要になるとは想像できません。 Memoryは、アプリが自然に数千を作成したくないという点で、昔ながらのArrayBuffer Memoryとは異なると思います。

仕様と実装を混乱させなければならないという煩わしさに加えて、欠点は何ですか
コンパイルとインスタンス化を1つの約束されたアクションに組み合わせるのですか?

上で述べたように、 Promise<Instance> eval(bytecode, importObj) APIを追加することは問題ありませんが、一部のプラットフォームでパフォーマンスを向上させるか、コンパイルしたコードをキャッシュできるかを選択する必要があるため、開発者は困難な状況に置かれます。すべてのプラットフォーム。 キャッシュと統合するソリューションが必要なようです。それは、明示的なCache APIを使用して上記でブレインストーミングしたものです。

新しいアイデア: new Instance非同期バージョンを追加した場合、たとえばWebAssembly.instantiateとすると、 WebAssembly.compile同様に、誰もが非同期バージョンを使用することになっていると言いますか? パッチを適用するとインスタンス化に数ミリ秒かかる可能性があるため、これは私が_とにかく_検討してきたことです。 次に、仕様で、エンジンはcompileまたはinstantiateいずれかで高価な作業を実行できると言います(または、エンジンが遅延検証/コンパイルを実行する場合はどちらも実行できません!)。

それでも、 compile d ModuleがIDBに格納されている場合はどうすればよいかという疑問が残りますが、複数のcodegenモードが_とにかく_ある場合は難しい質問です。 1つのアイデアは、IDBに格納またはIDBから取得されるModuleは、IDBエントリへのハンドルを保持し、このエントリに新しいコンパイル済みコードを追加するというものです。 このようにして、IDBエントリは、そのモジュールの1つ以上のコンパイル済みバージョンを遅延蓄積し、インスタンス化中に必要なものを提供できるようになります。

IDBの部分はもう少し手間がかかりますが、パフォーマンス的には理想にかなり近いようです。 WDYT?

非同期instantiateを追加することは理にかなっていると思いますが、 Memoryパラメーターもcompile追加します。 別のメモリをinstantiate渡すと、再コンパイルできます。それ以外の場合は、コンパイル時にメモリをすでに「バインド」しています。

私はまだ完全な意見を持つのに十分なキャッシングについて考えていません。

@lukewagner

私はASLRの専門家ではありませんが、iiucは、控えめな限界がなかったとしても(つまり、カーネルがアドレス範囲の最大数に達したためにmmapが失敗するまで割り当てを続けることを許可した場合) 、47ビットのアドレス可能なスペース全体のごく一部のみが消費されるため、コードの配置はこの47ビットのスペース全体で非常にランダムになります。 IIUC、ASLRコードの配置も完全にランダムではありません。 何かがどこにあるかを予測するのを難しくするのにちょうど十分です。

ASLRは、コードとデータの両方に影響します。 重要なのは、攻撃者がデータ構造へのポインタを追跡せずにデータ構造に侵入することをより高価にすることです。 攻撃者がメモリを使い果たすことができれば、彼は間違いなくより多くのレバレッジを持っています。

まあ、それはasm.jsの日からなので、1000だけです。それからメモリ割り当てはただスローします。 これをぶつける必要があるかもしれませんが、同じプロセスを共有する多くの超モジュール化されたアプリ(それぞれに多くの個別のwasmモジュールがある)でも、これ以上必要になるとは想像できません。 メモリは、アプリが自然に数千を作成したくないという点で、従来のArrayBufferとは異なると思います。

1000は賢明な制限のようです。 警備員に聞いてみます。

上で述べたように、約束を追加するeval(bytecode、importObj)APIは問題ありませんが、一部のプラットフォームでパフォーマンスを向上させるか、すべてのプラットフォームでコンパイル済みコードをキャッシュできるかを選択する必要があるため、開発者は困難な状況に置かれます。 キャッシングと統合するソリューションが必要なようです。それは、明示的なキャッシュAPIを使用して上記でブレインストーミングしたものです。

右。 そのようなAPIを機能させる方法がいくつかあります。 安っぽいが実用的なAPIは、evalをオーバーロードすることです。

  1. instancePromise = eval(bytecode、importObj)
  2. instancePromise = eval(module、importObj)

次に、インスタンスにはゲッターがあります。

module = instance.module

モジュールが構造クローン可能である場合。

これについてどう思いますか?

新しいアイデア:新しいインスタンスの非同期バージョン、たとえばWebAssembly.instantiateを追加し、WebAssembly.compileと同様に、誰もが非同期バージョンを使用することになっているとしたらどうでしょうか。 パッチを適用するとインスタンス化に数ミリ秒かかる可能性があるため、これはとにかく検討してきました。 次に、仕様では、エンジンはコンパイルまたはインスタンス化のいずれかで高価な作業を実行できると言います(または、エンジンが遅延検証/コンパイルを実行する場合はどちらも実行できません!)。

それでも、コンパイルされたモジュールがIDBに格納されているときに何をすべきかという問題が残りますが、とにかく複数のcodegenモードがある場合、それは難しい問題です。 1つのアイデアは、IDBに格納またはIDBから取得されるモジュールが、IDBエントリへのハンドルを保持し、このエントリに新しいコンパイル済みコードを追加することです。 このようにして、IDBエントリは、そのモジュールの1つ以上のコンパイル済みバージョンを遅延蓄積し、インスタンス化中に必要なものを提供できるようになります。

IDBの部分はもう少し手間がかかりますが、パフォーマンス的には理想にかなり近いようです。 WDYT?

興味をそそる。 上記の私の考えに関連して:

プロ:あなたのものは、私たちが今言っていることと概念的に似ている、理解しやすい抽象化です。
短所:あなたの提案では、ユーザーが行うこととエンジンが行うことの間に、私の提案が許すほどの相乗効果はもたらされません。

あなたの提案がユーザーに私のものほど多くのコントロールを与えない3つの領域があります:

  1. 高価な作業は2つの場所のいずれかで発生する可能性があるため、ユーザーはどちらかが高価になるように計画する必要があります。 たまたま安い場合に合わせて調整されているため、そのうちの1つが高価な場合、動作が悪いWebコンテンツが存在する可能性があります。 私の提案には、費用のかかることが発生する場所が1つあり、実装間の均一性が高まります。
  2. コンパイルされたコードのすべてのバージョンがキャッシュされるための明確に保証されたパスはありません。 一方、APIを介してモジュールをスレッド化することを使用すると、VMは、ユーザーがキャッシュを管理できるようにしながら、毎回より多くのものでモジュールを構築できることを意味します。 したがって、最初に4GBを実行する場合はこれがキャッシュされますが、2回目に4GBを実行できない場合は、両方をキャッシュできる可能性があります(ユーザーがコンパイルのたびにinstance.moduleをキャッシュする場合)。
  3. ブラウザの異常なコーナーケースやその他の問題により、スキームで二重コンパイルが発生する場合があります。これは、コンパイルステップで1つのものをコンパイルしますが、インスタンス化ステップで別のものが必要であることに気付くためです。 私のバージョンでは、ダブルコンパイルは必要ありません。

だから、私は私の方が好きです。 そうは言っても、あなたの提案は進歩だと思うので、私には間違いなく良いと思います。

この問題は、断片化によって割り当てが高速になる頻度に依存します
メモリ(ところで、4GB +サポートされている最大オフセットまたは8GB)に障害が発生します。 の場合
おそらく1%未満ですが、それは完全に不合理ではないかもしれません
それはOOMの状況です。

ユーザーがウェブを閲覧し、多くのを使用しているシナリオでは
小さなWASMモジュールが次々と登場します。おそらく、すべてがライブではありません。
一度。 その場合、予約済みの4GBチャンクの小さなキャッシュは、
問題。

別の可能な戦略は、コードの1つのバージョンを生成することです。
境界チェックを行い、高速メモリが利用可能な場合は、境界を上書きするだけです
nopsでチェックします。 それは醜いですが、それは
再コンパイルし、2回のコンパイルよりも少ないスペース。

21:03の木、2016年10月27日には、pizlonator [email protected]
書きました:

@mtrofin https://github.com/mtrofin

モジュールの作成者は、最小/最大メモリとして4GBを必要とします

多くのデバイスには4GBの物理容量がないため、これは実際には実用的ではありません。
メモリー。 また、それを特定するのは難しいです。

コンパイルのバリアント(少なくとも非同期、おそらく同期も)は、
高速メモリのみを受け入れるインスタンス。

ダブルコンパイルは必要ないと思います。


このスレッドにサブスクライブしているため、これを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/WebAssembly/design/issues/838#issuecomment -256738329、
またはスレッドをミュートします
https://github.com/notifications/unsubscribe-auth/ALnq1F6CYUaq0unla0H6RYivUC8jfxIAks5q4PWIgaJpZM4Kh1gM

ASLRだけでなく、ページテーブル/アロケータなどの汚染でもあります。 私たちは皆、セキュリティ担当者やカーネル/システム担当者と話をする必要があります。 または、各エンジンが「高速」 Memoryに課す制限について開発者に事前に知らせ、APIで慣用的にして、間違って使用するのを防ぐこともできます。

nopやダブルコンパイルなど、使用できる松葉杖はすべてありますが、なぜ松葉杖さえあるのでしょうか。

@jfbastienPROT_NONEメモリがページテーブルエントリにかかるとは思わない。 ページテーブルが遅延入力されるマッピングを保持する別のデータ構造があると思います。

@pizlonator私はそのアイデアが好きで、チュートリアルやツールチェーンなどでデフォルトですべての人に使用することをお勧めします。 Module単に無視できれば、より簡潔で教えやすくなります。 これは、最も優れたAPIを非同期APIにすることで、同期APIの使用を思いとどまらせるという@ s3ththompsonの懸念にも対処できます。

ただし、 WebAssembly.compileModuleコンストラクターを削除するべきではないと思います。「コードサーバー」(IDB + postMessage介してクロスオリジンコードキャッシングを提供する)があるシナリオを想像しています。 new Module経由)が必要な同じコーナーケースでは、 new Instanceを維持する必要があります。

したがって、それに同意した場合、これは、あなたが言及した2つのWebAssembly.evalオーバーロードの純粋に付加的な提案になります。 はい?

私たちは持っているべきではないと思う:一つの微調整、しかしmoduleこれが必要になるので、ゲッターInstance周りにいくつかの内部データを保持するための有効期間(すなわちを、バイトコード。) Instance ; 現在、 Moduleは通常、インスタンス化の直後にGCできます。 これは、データプロパティ(ユーザーはおそらく削除することを忘れますが、削除できます)、または{instance, module}ペアを返すeval 3番目のバージョンのいずれかを示唆します...

典型的なモノリシックアプリの推奨ケースとして非同期ワンステップAPIを使用することは、推奨パターンとして理にかなっています。

@lukewagnerは、新しいモジュールと新しいインスタンスでカバーされるすべての同期(インラインコンパイル)のケースの両方がました。
また、同期インスタンス化を備えたバックグラウンドコンパイル(非同期)サーバーも便利なようです。

提案された2つの評価バリアントを追加することは、これを導入するための良い方法のようです。

ただし、この名前は、(セキュリティ)の人々の心の中でjs eval(ある意味では似ていますが、スコープキャプチャの点では似ていません)と混同されるため、好きではありません。
WebAssembly.instantiateはどうですか?

ああ、良い点ですが、evalには少しの担当者がいます。 +1からWebAssembly.instantiate

非同期インスタンス化をいつ使用するかについて、開発者へのガイドラインは何でしょうか?

@mtrofin特定の用途とは無関係にModuleコンパイルする必要がある特別なコード共有/ロードスキームがない限り、デフォルトでWebAssembly.instantiateを使用します。

@lukewagnerこれは合理的なようです。

ああ、良い点ですが、evalには少しの担当者がいます。 WebAssembly.instantiateに+1します。

同意しました。

したがって、それに同意した場合、これは、あなたが言及した2つのWebAssembly.evalオーバーロードの純粋に付加的な提案になります。 はい?

それはそれがどのように聞こえるかです。

モジュールゲッターを使用するべきではないと思います。これは、インスタンスがインスタンスの存続期間中、内部データ(つまり、バイトコード)を保持する必要があるためです。 現在、モジュールは通常、インスタンス化の直後にGCできます。 これは、データプロパティ(ユーザーはおそらく削除することを忘れますが、削除できます)、または{instance、module}ペアを返すevalの3番目のバージョンのいずれかを示唆します...

確かに、データプロパティの方が優れているように感じます。 または、WebAssembly.instantiateを使用すると、常にインスタンスとモジュールのペアが返されます。

これは正しいですか:fastmemoryモジュールのバリアントを取得することを目的としてWebAssembly.instantiateを取得するとします。 これでモジュールを取得し、構造クローンを作成します。 現在、このモジュールは、fastmemoryをサポートするMemory esでインスタンス化する必要があります。

@pizlonatorええ、私は頭の中でそれを複数の方法で自転車に乗せることができます。 未使用のModule誤って同伴する人が少なくなる可能性があるため、ペアをもう少し返品するのが好きだと思います。

@mtrofin再コンパイルは、1回のinstantiate呼び出しからinstantiate Module取り出し、新しいインポートでinstantiate取り出すときにも必要になる可能性があります。 このAPIの追加のポイントは、一般的なケースではなく、基本的に必要な場合(つまり、1つのモジュールが2種類のメモリにアクセスする場合)にのみ発生することだと思います。

このスレッドは長くなっており、収束しているように見えますが、さまざまなユーザーが作成することを期待するコードを100%確実に作成する必要があります。

  1. 単一モジュールの非同期インスタンス化。
  2. モジュールの非同期インスタンス化。他のモジュールとメモリを共有します。
  3. 単一モジュールの同期インスタンス化(同期マルチモジュールは有用ではないと思いますか?)。
  4. これらすべてのキャッシュ(キャッシュへの書き込み、およびメモリを使用した取得とインスタンス化の両方)。
  5. 単一の.wasmモジュールの更新、および他のモジュールのキャッシュされた負荷。

他に何か? @lukewagnerは、私が完全にはです

つまり、このモジュールを後で使用するには、非同期でインスタンス化する必要があります。そうしないと、驚くほど長い同期インスタンス化でUIスレッドがブロックされるリスクがあります。

@jfbastien開発者が作成することを期待するスニペットごとに、その特定のパスに進む動機となるもの、および開発者が決定を下すために利用できる必要のある情報を理解したいと思います。

@mtrofinそうですModule m与えられた場合、非同期であるWebAssembly.instantiate(m)を呼び出します。 new Instance(m)を呼び出すことができ、高額になる可能性がありますが、それはnew Module(m)と同じです。

@jfbastien 「非同期インスタンス化」と言うとき、「非同期コンパイルとインスタンス化」を意味すると仮定すると、ここに短いバージョンがあります。

  1. WebAssembly.instantiate(bytecode, imports)
  2. WebAssembly.instantiate(bytecode, imports) 、ここでimportsには共有メモリが含まれます
  3. new Instance(new Module(bytecode), imports)
  4. すべての場合で、 Moduleを取得できます。次に、 IDBObjectStore putを取得できます。 後で、 get a Module m戻って、 WebAssembly.instantiate(m, imports)電話します。
  5. ここでは、本当に特別なことは何もありません:あなたのWebAssembly.instantiateバイトコードから一つのモジュールとinstantiate残りの部分からModule IDBから引き出さ秒。

同期コンパイルを使用できると思われる場合は同期インスタンス化を使用し、非同期コンパイルを使用する必要があると思われる場合は非同期インスタンス化を使用することをお勧めしますか?

それとは別に、開発者がより複雑なシステムに直面することを懸念しています。私たちが計画している最適化を引き起こすより多くの選択肢があり、開発者がトレードオフを行うために利用できる正しい情報を持っているかどうかはわかりません。 開発者の観点から考えると、彼らが気にかけていて、表現しやすいと感じる懸念の小さなセットはありますか? ある時点で、開発者が「正確な障害点を犠牲にして最適化する」ことについて話しました(これは境界チェックを引き上げることでした)。 代替案は「最適化」フラグでしょうか?

@mtrofin開発者が作成する(またはツールチェーンによって生成した)ものの99%は、 WebAssembly.instantiateます。 同期APIは、特別な「WasmでJITを作成しています」にのみ使用し、コード共有システムを作成している場合はWebAssembly.compileを使用するため、「はじめに」チュートリアルではWebAssembly.instantiateのみをカバーすると思います。

@lukewagner上記の#3の新しいModule()にインポートを追加したことに気付きました。 それに加えて、それをWebAssembly.compileに追加することは良い考えであり、可能性を締めくくると思います。
そうすれば、コンパイル時にメモリについてヒントを得ることができます。
後で、特に同期的に、別のインポートで再度インスタンス化すると、問題が発生する可能性があります。

変更の概要(はっきりしているので):

  • WebAssembly.instantiate(bytes、imports)を追加すると、{instance:、module:}のpromiseが返されます
  • Add WebAssembly.instantiate(module、imports)は、{instance:、module:}のpromiseを返します
  • 新しいModule(bytes 、imports )に変更すると
  • WebAssembly.compile(bytes 、imports )に変更すると、インスタンスのpromiseが返されます

コンパイルからのインポートがインスタンス化に一致する場合、インスタンス化が高速になるという期待をどこかに述べてください。

WDYT?

おっと、インポートを引数としてInstanceに入れるつもりModuleまたはcompile必要だとは思いません。 [編集:もし持っていたら、 instantiateと呼ぶだけだから]

つまり、エンドツーエンドの非同期の場合、4GBのハックメモリにバインドすることはわかりますが、JITされたフィルタカーネルやバックグラウンドでコンパイルされたアイテムにはバインドしないことを意味します(throw-も作成しない限り)アウェイインスタンス)?

コンパイルとインスタンス化の非同期ペアにガイダンスを集中させることに+ 1-メッセージを単純にし、開発者から決定問題の複雑さを隠します。

ええ、私たちは皆、人々に次のことを指摘することに同意していると思います。
初めて:
WebAssembly.instantiate(bytes、imports)-> {module、instance}の約束(indexeddbへのキャッシュモジュール)
2回目:
WebAssembly.instantiate(module、imports)-> {module、instance}の約束

それが主なパターンであることに異議はありますか?

コンパイル/新しいモジュールのインポートに悩まされています。 それは役に立つヒントになるようです。
ただし、可能性として言及し、その引数(オプションの場合もあります)をPost-MVPに追加するのを延期することはできます。

考え?

@mtrofin (まあ、技術的には、 instantiateです。)

@lukewagner@mtrofinの意味だと思います)

@ lukewagner@ flagxor OKですが、非同期コンパイルAPIは保持していますよね?

このシナリオはどうですか:たくさんのプラグインを備えたPhotoShopのようなアプリケーションを入手します。 各プラグインはwasmモジュールです。 メインアプリを起動し、fastmemoryをトリガーする魔法のメモリサイズを割り当てることができます(このシナリオでは妥当と思われます-1つのアプリ、メモリが不足しています)。

いくつかのプラグインを並行してコンパイルしたいので、それを行うためにいくつかのワーカーを起動します。 これらのコンパイルを、実際に使用するメモリに渡すことはできません(正しいですか?)。 そのため、デフォルトに応じて、プラグインのslowmemoryコンパイルが行われ、プラグインがアプリに接続されると、fastmemoryの非同期再コンパイルのコストがかかります。

このシナリオを購入した場合、コンパイルAPIにメモリ記述子(明確にするために、実際のバッキングメモリなしで)を渡すことに価値があると感じます。

はい、コンパイルにMemoryを渡すことは可能であるはずです(推奨されています)。

@mtrofinそうですね、高度な用途にはcompileです。 プラグインの例は、コンパイルしたい、 Memoryがあるが、(まだ)インスタンス化したくないという有効なケースだと思います。

@pizlonatorところで、ASLR /セキュリティの懸念に対処するには「プロセスごとに1000を超える4GBマップをスローする」ハックで十分であると仮定して、先に尋ねるつもりでしたが、プラットフォームのために低速モード/高速モードの必要性はまだありますか仮想アドレス割り当ての制限? なかったとしても、これが上級ユーザーにとってもパフォーマンスの考慮事項でなかったとしたら、それは確かに素晴らしいことです。 (もちろん、 instantiate APIは、前述した他の理由で追加すると便利なようです。)

2の累乗にスピルエリアを加えたメモリサイズの恩恵を受ける可能性のあるアプリケーションもあります。アプリケーションはすでにポインタをマスクしてタグ付けを削除しているため、境界チェックを回避するために上位ビットをマスクできます。 これらのアプリケーションは、マスキングに使用されるグローバル定数を変更するか、wasmに解凍しながら適切な定数でベイクすることにより、コンパイル前に受け取ることができるメモリ割り当てサイズについて推論する必要があります。

一部のランタイムが利用したいゼロ時バッファーの最適化もあり、プロセスごとにそのようなバッファーは1つだけになります。

また、アプリケーションをコンパイルする前に必要なメモリと使用可能なメモリについて推論できれば、プラットフォームはよりユーザーフレンドリーになります。 たとえば、ブラウザまたはアプリが、アプリケーションを実行するためにいくつかのタブを閉じる必要があること、または機能を低下させずに実行する必要があることをユーザーに通知できるようにするため。

Webブラウザーには、ユーザー向けのオプションである専用アプリモードが必要な場合があります。このモードでは、限られたデバイスで実行され、1つのアプリケーションを適切に実行するために取得できるすべてのメモリとパフォーマンスが必要になります。 このためには、要件について早期に推論できる必要があります。

コンパイル前にメモリを割り当てる必要はなく、合理的な予約を行う必要があります。 限られたデバイスでは、コンパイルだけで大量のメモリを使用する可能性があるため、VMの割り当てが大きい場合でもショーストッパーになる可能性があります。

これらは新しい問題ではなく、何年もの間議論されてきました。 メモリリソース管理が必要であり、コード生成と調整する必要があります。

@lukewagner 1000モジュールに制限すると、許容誤差が十分に大きくないのではないかと心配するので、そう思います。

  • この天井を下げる必要のある攻撃が表面化するのではないかと心配しています。
  • スタックの他の場所での最適化により、使用可能な仮想アドレススペースの量が減少することを心配します。その場合、上限が十分に低いかどうかを再評価する必要があります。
  • 意図的に数千のモジュールを作成するプログラミングスタイルを防ぐことを心配します。 たとえば、ほとんどのJavaScriptCoreフレームワーククライアントがVMを作成し、少しの作業を行ってから、それを破棄することを私は知っています。 JSCがObjective-Cからのものと同じようにJSからWebAssemblyを使用する場合、64ビットシステムでWebAssemblyを機能させるには、1000個のメモリを割り当てると(それぞれが小さい場合でも)、GCは次のことを認識しなければなりません。これらの1000個のメモリに到達できないという理由で次の割り当てが成功する場合のGC。 たとえば、4GBハックメモリがすでに10個存在した後で、4GBハック以外のメモリを割り当てることができるということは、GCがヒューリスティックをあまり変更する必要がないことを意味します。 インスタンス化->実行->ダイループで1001番目のモジュールを割り当てるときにGCを実行する必要はありません。 これは、小さなメモリを使用するパターンにとってメリットになります。 1MB未満のものであれば、1000個持つのが理にかなっています。 64KBで便利なことをしている人が想像できます。
  • これが他のJavaScriptコンテキストにとってあまり役に立たないのではないかと心配しています。 JSC CAPIおよびObjective-CAPIクライアントがJSコードからWebAssemblyAPIにアクセスできるようにドアを開いたままにしておきたいと思います。 これらのクライアントは、割り当てる4GBメモリの数に小さな制限を設けることをおそらく好むでしょう。 そのようなコンテキストでそのクォータを構成可能にすることさえ魅力的です。

改善されたAPIにより、メモリ数に人為的な上限を設ける必要がなくなったり、再コンパイルしたりする必要がなくなったり、その他の望ましくないことがなくなるのが好きです。 公差が非常に大きくない限り、人工天井は好きではありません。ここではそうではないと思います。

@pizlonator十分に公平で、よりクリーンでシンプルなAPIなので、追加しても問題ないと思います。

なぜ私があなたが言及したそれらの項目に関心がないのかについては(現時点で):

  • 制限を引き上げる必要があるかもしれません。 簡単だ。
  • 妥当な制限が何であれ、64ビットアドレス空間全体のごく一部しか使用されないため、その攻撃ベクトルがここにあるかどうかはわかりません。 決定されたコンテンツには、それ自体をOOMする多くの方法があります
  • 予約サイズに見合ったGCヒューリスティックをバンプするため、 Memoryをかき回すと、GCがより積極的になります。 GCを増やすのは良いことではありませんが、これが一般的なパターンになるかどうかはわかりません。

しかし、私たちが将来何を見るかは誰にもわからないので、今すぐ柔軟性を組み込むと便利だと思います。

js APIで実装の詳細(特にアーキテクチャ/プラットフォーム固有の詳細)を過度に表示しようとするのは悪い考えだと思います。 実装には、高速メモリに対する独自の内部制限があれば十分だと思います。

非同期インスタンス化関数を持つことは合理的であるように思われますが、コンパイラのヒントを与えるためにそれを使用したい場合は、他のものを使用する必要があると思います。 たとえば、モジュールを拡張して、シングルトンの最適化、多くのインスタンスの最適化、ロード時間の最適化、予測可能なパフォーマンスの最適化などを要求するフラグセクションを作成できます。もちろん、エンジンが行うことは完全に実装に依存します。しかし、それは開発者に方向転換するためのノブを与え、競争はブラウザベンダーを正直に保ちます。

2:15で金、2016年10月28日には、JFバスティアン[email protected]
書きました:

はい、メモリをに渡すことは可能であるはずです(奨励されていても)
コンパイル。

私はそれをやめるべきだと思います
メモリーのインポート/エクスポート。 結局のところ、モジュールがインポートされない場合
またはメモリをエクスポートする場合、メモリはコンパイル時に予約できます。 私たちは私たちを知っています
洗練されたモジュールを効率的に処理できるようにしたい
アプリケーションはやりたいと思うでしょうが、モノリシックWASMアプリは
私たちが予想しているよりも一般的です。 たぶん私はここで少数派ですが
動的バインディングが少ないモジュールが少ないほうがいいです。

あなたがコメントしたのであなたはこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/WebAssembly/design/issues/838#issuecomment -256805006、
またはスレッドをミュートします
https://github.com/notifications/unsubscribe-auth/ALnq1KXrUWaegRZwEhznmT1YcyI33IN9ks5q4T6TgaJpZM4Kh1gM

私はあなたに完全に同意します。少なくともmvpの直後の数年間は、モノリシックアプリが主なユースケースになると思います。 何万ものモジュールがロードされたときに何が起こるかを心配することは、まだ存在していないwasmエコシステムについて多くのことを想定しています。

では、この問題を解決するために何をする必要がありますか? 1つは、 http://webassembly.org/getting-started/js-apiを更新することです。これは私が実行できます。 もう1つは、binaryenがデフォルトでこれを出力することです(良い@kripken?)。 @titzer CanaryはWebAssembly.instantiate実装していますか?

他に何か?

@lukewagner :何を求めているのかわからないので、この号の議論は非常に長いです。 ここで提案されている新しいpromiseベースのAPIの1つを使用するために使用する現在の同期WebAssembly.InstanceAPIからbinaryenを変更することを意味しますか? それは必要ですか?古い方法を削除していますか?

@kripkenそうですWebAssembly.instantiateを使用するように切り替えます。 古い方法を削除するわけではありませんが、新しい方法の方が効率的で、デフォルトで使用されるようになっています。

HTMLを生成するときにpromiseベースのAPIを使用することもできますが、多くのユーザーがJSを生成し、非同期ステップを自動的に追加するのは簡単ではありません。 しかし、これは人々のために文書化することができます。 しかし、これがすべてのブラウザに到達したときにのみ、すべてを実行する必要があると思います。

@kripken理解できません。現在のアプローチは、非同期APIをまったく使用しないことです。

はい。 非同期のものを追加するには、この問題を参照してください。

@kripkenノードには機能する約束があると思います。 シェルでさえ、promiseキューを明示的に排出する方法があります(したがって、すべての解決を同期的に実行します)。 SMではdrainJobQueue()で、V8では%RunMicroTasks()があると聞きました。 単に機能テストWebAssembly.instantiateを使用して、デフォルトで存在する場合にそれを使用できるようです。

確かに、しかし最初に、Promiseのサポートは最新のnode.jsにあるかもしれませんが、一般的に使用されているバージョンにはありません(たとえば、Linuxディストリビューションのデフォルトバージョン)。 そして第二に、より大きな問題は、HTMLを発行するとき、ページのロード方法を制御できることです(emccはユーザーのロードコードを発行します)が、JSを発行するとき、JSは直線的に実行されると想定され、ユーザーは依存しますその上で、例えば、彼らはそのJSの直後に別のスクリプトタグを持つことができます。 その場合、ユーザーは独自のロードコードを記述します。

これらの両方の結果として、前述のように、HTMLを発行するときにPromise APIを使用できます(その場合、シェルにいるわけではなく、読み込みを制御できます)が、JSを発行するときは使用できません。 そこではそれを文書化することしかできません。

NodeにはWebAssemblyをサポートしているが、Promiseはサポートしていないバージョンがありますか? ノードの人々はこれらのバージョンを気にしますか?

直線的なJSのことはわかりません。 常にPromiseを返す場合、それは正しく機能しませんか(コードのユーザーはPromiseを消費する必要があります)?

最初の質問に対する答えはわかりませんが、ポリフィルを使用すると、promiseがないノードバージョンでwasmを実行できる可能性があります。 ノードにはしばらくの間setTimeoutのバージョンがあったので、promiseをポリフィルすることも可能かもしれませんが、私は思いますが、それについてもよくわかりません。

直線的な問題について:emccは、ランタイムをセットアップし、コンパイルされたコードに接続するJSを発行します。 スクリプトタグ内の一部のJSは、コンパイルされたコードを呼び出す直後に、たとえばccallを使用する

WebAssemblyを使用しているがPromisesを使用していないIMOノードは、設計上の制約ではありません。 WebAssemblyへのポリフィルは、そのコンテキストではかなりばかげています。

あなたは今日のコードが何をしているのかを説明しています。 完全には理解していませんが、バックアップしたいと思います。WebページのコードでPromiseAPIを使用する必要があります。 Emscriptenはそのようなコードのプロデューサーです。 何がpromiseを使用するコードの発行をブロックしているのかわかりません。 「今日のやり方ではないので、それは重要な仕事ですが、私たちはそれに到達します」と言っても、私はまったく問題ありません。 しかし、私たちの議論から、それがあなたが言っていることであるかどうかはわかりません。

キャッシュに非同期APIを使用することについて指摘した問題

なぜノードでwasmへのポリフィルがばかげているのですか? 他の場合よりも少なくても、そのコンテキストではまだ役立つようです:)

繰り返しますが、EmscriptenはHTMLを出力するときにpromiseAPI使用します。 そして、それが推奨されるパスです。 したがって、あなたの質問に対する答えは「はい」です。 重要な作業ではありません。 それはその問題でスケッチされており、そうです、キャッシングに焦点を当てていますが、(古い)オフラインディスカッションからのメモを追加しました。その間、他の非同期最適化もたくさん行う必要があります。

それはあなたの懸念に対処していますか?

私が言っているのは、EmscriptenがJS(あまり推奨されないパス)を発行するとき、その出力に関する保証は、内部で非同期マジックを実行するコードと一致しないということです。 私たちは人々のコードを破ることになりますが、それはやりたくないことです。 私が言ったように、誰かがそれが準備ができていると仮定するそのJSの直後に同期的に実行されるJSを書くことができます。 そのため、その場合、promiseを使用することはできません。 これを想像してみてください:

「」

「」

doSomethingが存在するには、 Module.my_funcが必要です。 output.jsがpromiseを返したばかりの場合、それはまだ存在していません。 したがって、これは重大な変更になります。

それは今意味がありますか?

なぜノードでwasmへのポリフィルがばかげているのですか? 他の場合よりも少なくても、そのコンテキストではまだ役立つようです:)

wasmへのポリフィルはばかげていません。 wasmがなく、ポリフィルし、約束はないがポリフィルしないNodeインストールに対応するのは、ばかげています。 それは中途半端です。 彼らはお尻の残りの半分を取得する必要があります😁

繰り返しますが、EmscriptenはHTMLを出力するときにpromiseAPIを使用します。 そして、それが推奨されるパスです。 したがって、あなたの質問に対する答えは「はい」です。 重要な作業ではありません。 それはその問題でスケッチされており、そうです、キャッシングに焦点を当てていますが、(古い)オフラインディスカッションからのメモを追加しました。その間、他の非同期最適化もたくさん行う必要があります。

それはあなたの懸念に対処していますか?

OK]それは良いことだ! ほとんどのWebページがpromiseAPIを使用している限り、私は満足しています。

[をちょきちょきと切る]

それは今意味がありますか?

はい。 説明してくれてありがとう。

私のPOVからは、EmscriptenはもはやJSを発行するだけのビジネスではありません! あなたの例はあなたがたの古いコードには意味がありますが、新しいものは約束のIMOを想定する必要があります。

ところで、 instantiateを使用するようにwebassembly.org/demoを切り替えることを検討しましたが、同期結果が必要なコンテキストで現在の同期new Instanceが発生するのは少し注意が必要です。 したがって、Binaryenを更新してデフォルトでinstantiateを発行したら、AngryBotsデモを最初から再構築すると便利です。

ええ、でも最初から再構築するだけでは不十分かもしれないことに注意してください-Unityは独自の読み込みとHTMLコードを使用していると思います。 したがって、必要なことを実行できるように、前述のようにこの問題を文書化して伝達する必要があります(または、emccにhtmlを出力させることができますが、それが実現可能かどうかはわかりません)。

ええ、でも最初から再構築するだけでは不十分かもしれないことに注意してください-Unityは独自の読み込みとHTMLコードを使用していると思います。 したがって、必要なことを実行できるように、前述のようにこの問題を文書化して伝達する必要があります(または、emccにhtmlを出力させることができますが、それが実現可能かどうかはわかりません)。

WebAssembly.instantiate APIを使用しないことの潜在的な欠点を考えると、それを使用することを検討するように依頼する価値があると思います。

それらの欠点は文書化されていますか? メインのwasmWebサイトまたはemscriptenwasm wikiページのいずれかでこれに関する明確なガイダンスは、人々に指摘するのに便利なものです。

私はこの長い問題を自分でざっと読みましたが、欠点はまだはっきりしていませんので、それも読みたいと思います:)

@kripken現在のコードの課題は、binaryen / emscriptenが、エクスポートが同期的に必要になると同時に、必要なインポート( instantiateへの引数として必要)のみを提供することです。 インポートを「前もって」利用できるようにすることができれば、非同期XHRの末尾にWebAssembly.instantiateを追加するのは非常に簡単です(非同期compileした現在のデモで行ったように) 見たところ、現在のAngryBots wasmビルドは最適ではなく、とにかく更新する必要があります。

ああ、wasm XHRが始まる前にインポートを利用できるようにすることが、ここで重要であることを理解していませんでした。 その場合、それは非常に難しいことです。 だから私が前に言ったことのほとんどは間違っています。

インポートするには、すべてのJS接着剤をダウンロード、解析、実行する必要があります。 wasm XHRが始まる前にこれらすべてを実行すると、現在とは非常に異なるロードスキームと一連のトレードオフになります。 特に、中小規模のプロジェクトの場合、これはスピードアップにはならないかもしれません。まだ測定していない場合は、これを測定する必要があると思います。

これはUnityにとって簡単なことではありません。 コンパイルされたコードの準備が整う前にJSグルーを実行できるように、emccが発行するコードに大幅な変更を加える必要があります。

おそらく、放出されたJSの新しいモデル、インポート用に1つのJSファイル、残りの1つのJSファイルを検討したいと思いますか? そしてそれはオプトインになるので、誰も壊さないでしょう。 とにかく、多くの考慮事項があり、測定なしでは何が最適かを推測するのは難しいです。

@kripken XHRの前ではなく、完了した後、およびエクスポートオブジェクトへの同期アクセスを必要とするスクリプトの実行を開始する少し前。 インスタンス化が解決したときに呼び出されるコールバックにコードを使用して、エクスポートを配置するのと同じくらい簡単なことだと思います。

うーん、私はまだこれを完全には理解していないと思います、申し訳ありません(特に、非同期性がインポートの取得と相互作用する理由がわかりません-インポートが同期して機能しないことの利点はありますか?)。 しかし、これがXHRの完了後であっても、上記の問題は依然として関連しているようです。つまり、インポートを生成し、エクスポートも受け取る単一のスクリプトがあります。 それを分割すると、トレードオフにつながる可能性があります。時間があるときに測定する必要があります。

エクスポートを使用するコードをコールバックに入れることについては、残念ながら、前述の理由だけで機能するわけではありませんが、新しいコンパイルモードを追加して、これらの測定の一部として調査することができます。

instantiateの署名はWebAssembly.instantiate(bytes, importObj)であるため、非同期コンパイル+インスタンス化を実行するには、 importObjを渡す必要があります。

オフラインで話していると、 @ lukewagnerは、ここでの主な問題はモジュールのコンパイル中にメモリを使用することであることに感銘を受けました。 全体として、この新しいAPIを実際に使用するのがいかに簡単であるかに関連する3つの問題があるようです。

  1. コンパイル時にメモリを提供します。
  2. コンパイル時にすべてのインポートを提供します(前のスーパーセット)。
  3. これをすべて非同期で実行します。

ツールチェーンが現在どのように機能しているかを考えると、上記のように2 + 3を実行すると、既存のユーザーが破損するため、困難です。 私たちはそれを行うことができますが、少なくとも最初はそうではないかもしれませんが、デフォルトではオンにしたくないかもしれません-コミュニティメンバーなどに相談する必要があります。そしてそれを本当にうまく行うには-新しいオーバーヘッドはありません-時間と作業が必要になります(すばやく行うことができますインポートまたはエクスポートのいずれかに間接層を追加することによって実行されます)。

しかし、他のいくつかのオプションは簡単に使用できます。

  • 1 + 3には、 instantiate(bytes, Memory) -> Promiseような新しいAPIが必要です。 これが使いやすい理由は、とにかくメモリを早期に作成できるためです(他のほとんどすべてのインポートはJS関数であり、早期に作成することはできません)。
  • 2自体、3なし、つまりnew Instance(bytes, imports) 。 つまり、バイナリデータの同期コンパイル+インポートです。 これが使いやすい理由は、現在のコードがinstance = new WebAssembly.Instance(new WebAssembly.Module(getBinary()), imports)ため、これを1つのAPI呼び出しに折りたたむだけです。

最後のオプションは理にかなっていると思います。 これは基本的に、新しいAPIの同期バージョンを追加することを意味し、既存の同期コンパイルオプションとの対称性を高めます。 そして、コンパイル時にメモリを知るという新しい最適化を非同期コンパイルに結び付ける理由がわかりませんか? (非同期は素晴らしいですが、別の問題ですか?)

インポート(メモリ)を記述するメタオブジェクトを使用して、コンパイルする前にインポートを割り当てる必要があるという制約を破ることをお勧めします。 次に、提供されたメモリが予想と一致せず、再コンパイルが遅れない場合、 instantiateメソッドはエラーをスローする可能性があります。

また、メモリに制約のあるデバイスに線形メモリを割り当てる前にコンパイルできること、線形アドレス空間でゼロに割り当てられたメモリ、およびおそらくガードゾーンのあるメモリのコンパイルを最適化できることも非常に便利です。 2の累乗にスピルゾーンを加えた固定最大サイズでメモリを最適化します。 このメタオブジェクトは、wasmユーザーデコーダー/リライターがネゴシエートされたメモリ特性に最適化されたコードを発行するために使用することもできます。

これは、何年も前のこのプロジェクトの開始前後に必要に応じて提案されているものです。

@kripken同期APIは技術的には必要ですが、絶対に推奨されないパスである必要があります。そうしないと、asm.js +と比較してリグレッションが発生する不要なメインスレッドジャンクが大量に導入されます。

私は、同期コンパイル/インスタンス化を明示的に阻止する必要がある(または、過去に議論したように、許可しない)必要がある理由のより良い例を提供することを意味してきました。 うまくいけば、これは議論のための追加の飼料を提供します。

ズームアウトして、ユーザーエクスペリエンスについて少し話しましょう。


AngryBotsデモを非同期で(asm.jsを介して)ロードする場合と、同期的に(V8のWebAssemblyを介して)ロードする場合の比較を次に

comparison

同期コンパイルは、ひどいユーザーエクスペリエンスを提供し、プログレスバーやその他のアプリケーションの読み込みを視覚的に示します。

努力がどうであれ、Emscripten、Unity、およびその他のツールがデフォルトでWebAssemblyを非同期にロードしてエクスポートすることを確認するために協力する必要があると思います。 cc @jechter @jujそれだけでなく、開発者が同期ロードコードを書くという罠に陥るのを非常に難しくする必要があると思います。

WebAssembly.compileWebAssembly.instantiateを明示的に奨励し、 new WebAssembly.Modulenew WebAssembly.Instanceを思いとどまらせる必要があります。


もう少し深く掘り下げて、右側のプログレスバーがWebAssemblyにとってどれほど悪いかを見てみましょう。

DevToolsパフォーマンスパネルでキャプチャされたトレースは次のとおりです。

screen shot 2016-12-28 at 1 26 59 pm

MacBookAirでプログレスバーが表示されるまで30秒かかります。

その時間は何ですか? メインスレッドが完全にロックされたときにwasmモジュールがダウンロードされてから約20秒にズームインしてみましょう。

screen shot 2016-12-28 at 2 18 36 pm

コンパイルには約20秒かかり、インスタンス化には約2秒かかります。

この場合、Unityローダーがサポートされている場合はすでに非同期WebAssembly.compile呼び出しているため、20年代は、V8が内部で同期コンパイルを実行しているためです。 cc @ titzer @ flagxorこれはV8が本当に修正する必要があるものです。

2秒のインスタンス化ジャンクは、同期new WebAssembly.Instance呼び出すUnityローダーコードが原因です。 これは、UnityコードとEmscriptenの両方で本当に修正する必要があるものです。


これは、開発者が自分の足を撃つかどうかのリスクではないことにも言及する価値があると思います。 平均的なWebページには、数十のサードパーティスクリプトが含まれています。これらのスクリプトはすべて、トップドキュメントをジャンクするWebAssemblyを含む可能性があります。

(トレースをさらに詳しく調べたい場合は、ここで完全なタイムラインを表示できます:https://chromedevtools.github.io/timeline-viewer/?loadTimelineFromURL = https://www.dropbox.com/s/ noqjwql0pq6c1wy / wasm?dl = 0)

非同期が素晴らしいことに100%同意します:)しかし、モジュールのコンパイルと同時にメモリを取得する最適化と直交していると言っています。 そして、非同期+その最適化を簡単に取得することはできません-そのコンボを取得することはできますが、オーバーヘッドがかかるか、新しいフラグを導入してデフォルトに段階的に導入する方法を見つけると時間がかかります。

したがって、メモリ/コンパイルの最適化を今すぐ、デフォルトでオンにし、完全な効率で実行したい場合は、それを非同期にすることも問題になります。 ただし、緊急ではない場合、デフォルトでオンになっていない場合、または新しいオーバーヘッドで問題がない場合は、問題ありません。

開発者はwasmを選択しているので、トップレベルの構造を新しいデフォルトで少し変更することは理にかなっていると思います(必要に応じて古い動作にオプトインする方法もあります)。 同期を使用している人

@kripken @lukewagner@ s3ththompsonが持っているのとは異なる結論に達すると思います。なぜなら、あなたにとって最も重要な部分は、既存の開発者にasm.jsからのシームレスな移行を提供することだからです。

これは正しいです?

私はこれが有効な懸念であることに同意します。 WebAssemblyを使用したIMOは、asm.jsよりもはるかに多くの開発者を呼び込んでいるため、私はそれを軽くしています。 アーリーアダプターを燃やすことは避けたいのですが、IIUCの既存の開発者はかなり柔軟性があり、非同期コンパイルが必要です

彼らが非同期コンパイルを望んでいて、それを取得するためにいくつかをリファクタリングする用意があると仮定すると、残っているのはコンパイル時にメモリを持っていることだけです。これはこのAPIが提供するものです。 それは落とし穴を避けるので、それは非常に望ましいです。

以前、これをサポートするためにEmscripten側で行われる作業の量に懸念を表明しました。 あなたはまだこれが問題だと思いますか?

FWIW、Unity5.6はWebAssembly.instantiateを使用します。

ジョナス

2016年12月28日には、11:42 PMで、セス・トンプソン[email protected]書きました:

私は、同期コンパイル/インスタンス化を明示的に阻止する必要がある(または、過去に議論したように、許可しない)必要がある理由のより良い例を提供することを意味してきました。 うまくいけば、これは議論のための追加の飼料を提供します。

ズームアウトして、ユーザーエクスペリエンスについて少し話しましょう。

これは、AngryBotsデモを非同期呼び出し(asm.js経由)でロードする場合と、同期呼び出し(現在のWebAssembly実装)でロードする場合の比較です。

同期コンパイルは、ひどいユーザーエクスペリエンスを提供し、プログレスバーやその他のアプリケーションの読み込みを視覚的に示します。

努力がどうであれ、Emscripten、Unity、およびその他のツールがデフォルトでWebAssemblyを非同期にロードしてエクスポートすることを確認するために協力する必要があると思います。 cc @jechter @jujそれだけでなく、開発者が同期ロードコードを書くという罠に陥るのを非常に難しくする必要があると思います。

WebAssembly.compileとWebAssembly.instantiateを明示的に推奨し、新しいWebAssembly.Moduleと新しいWebAssembly.Instanceを推奨しないようにする必要があります。

もう少し深く掘り下げて、右側のプログレスバーがWebAssemblyにとってどれほど悪いかを見てみましょう。

DevToolsパフォーマンスパネルでキャプチャされたトレースは次のとおりです。

MacBookAirでプログレスバーが表示されるまで30秒かかります。

その時間は何ですか? メインスレッドが完全にロックされたときにwasmモジュールがダウンロードされてから約20秒にズームインしてみましょう。

コンパイルには約20秒かかり、インスタンス化には約2秒かかります。

この場合、Unityローダーがサポートされている場合はすでに非同期WebAssembly.compileを呼び出しているため、20年代は、V8が内部で同期コンパイルを実行しているためです。 cc @ titzer @ flagxorこれはV8が本当に修正する必要があるものです。

2秒のインスタンス化ジャンクは、同期の新しいWebAssembly.Instanceを呼び出すUnityローダーコードが原因です。 これは、UnityコードとEmscriptenの両方で本当に修正する必要があるものです。

これは、開発者が自分の足を撃つかどうかのリスクだけではないことにも言及する価値があると思います。 平均的なWebページには、数十のサードパーティスクリプトが含まれています。これらのスクリプトはすべて、トップドキュメントをジャンクするWebAssemblyを含む可能性があります。

(トレースをさらに詳しく調べたい場合は、ここで完全なタイムラインを表示できます:https://chromedevtools.github.io/timeline-viewer/?loadTimelineFromURL = https://www.dropbox.com/s/ noqjwql0pq6c1wy / wasm?dl = 0)


あなたが言及されたのであなたはこれを受け取っています。
このメールに直接返信するか、GitHubで表示するか、スレッドをミュートしてください。

@jfbastienたぶん私はあなたが「結論」が何を意味するのか理解していません。 私は主にここでオプションを提示しています。 私自身は結論が出ません。

コンパイル時のメモリを今すぐ選択したい場合は、現在の同期コンパイルを簡単に変更して、できるだけ早くそれを使用できるようにするいくつかのオプションを提案しました。

または、非同期で今すぐ選択したい場合は、できるだけ早く使用できるオプション( "1 + 3"、つまり、コンパイル時にすべてのインポートを受信せず、メモリのみを受信する)を提案しました。

または、現在のAPI( "1 + 3"ではない)を使用したそのoptの非同期バージョンに焦点を当てたい場合は、それも取得できます。重大な変更になるため、慎重に計画する必要があります。 ここで私たちが既存のユーザーを壊すことを決定することは選択肢ではないと思うので、コミュニティに相談する必要があります。 おそらく、懸念はほとんどなく、私たちはそれを行うことができます。その場合、どれだけの労力は、許容できるオーバーヘッドの量によって異なります。オーバーヘッドをまったく受け入れることができない場合は、多くの可能性があります。 あるいは、私の個人的な直感である懸念があるかもしれません-どんな重大な変更も徐々に行わなければなりません-その場合、それはより長くかかります、私たちはおそらく新しいオプションから始めて、最終的にそれをデフォルトにすることを計画します。

繰り返しますが、私からの結論はありません。 上記はすべてオプションです。 それは本当にあなたがもっと気にかけていることに依存します:コンパイル時のメモリ、または非同期、あるいはその両方。 そして、新しいオーバーヘッドを許容するかどうかの問題。 そして、あなたがこれを緊急に望むか、待つことができるかなどなど。私は上記のいずれかでemscripten側で喜んでお手伝いしますが、人々は決定します。

または、現在のAPI( "1 + 3"ではない)を使用したそのoptの非同期バージョンに焦点を当てたい場合は、それも取得できます。重大な変更になるため、慎重に計画する必要があります。 ここで私たちが既存のユーザーを壊すことを決定することは選択肢ではないと思うので、コミュニティに相談する必要があります。 おそらく、懸念はほとんどなく、私たちはそれを行うことができます。その場合、どれだけの労力は、許容できるオーバーヘッドの量によって異なります。オーバーヘッドをまったく受け入れることができない場合は、多くの可能性があります。 あるいは、私の個人的な直感である懸念があるかもしれません-どんな重大な変更も徐々に行わなければなりません-その場合、それはより長くかかります、私たちはおそらく新しいオプションから始めて、最終的にそれをデフォルトにすることを計画します。

私が理解していることを確認するために:

  1. オーバーヘッドは何ですか?

    • これらのオーバーヘッドは、コンパイル時の非同期+メモリに固有のものですか、それとも後で修正できる実装上の制約ですか? IMOがA + Mに固有のものである場合は、APIをできるだけ早く修正する必要があります。

    • IIUCのオーバーヘッドは、インポートまたはエクスポートのいずれかで一時的なものであり、A + Mに固有のものではありませんが、それは正しいですか? これについてもう少し詳しく教えていただけますか?

  2. どのユーザーが破壊について話しているのですか? 同じコードでwasmもターゲットにしたいasm.jsユーザー?

別の言い方をすれば、無限の時間があり、「レガシー」がない場合、WebAssemblyの理想的な最終状態は何でしょうか。 私たちはその理想的な最終状態のために設計されたと思います、そしてあなたは途中でハードルを指摘しています、しかし私はまだそれが事実であるかどうかわかりません。 もしそうなら、WebAssemblyが移行を容易にするために一時的なギャップが必要かどうか、または一時的な負担がEmscriptenユーザーのサブセット(およびどのユーザー)に受け入れられるかを理解するのに十分な情報があるかどうかはわかりません。

一部のオプションのオーバーヘッドについて:上記のように、注意が必要なのは、現在、インポートを送信してエクスポートを同期的に受信する必要があることと、JSの準備が整うまでJSのインポートがないことです(ただし、メモリはあります) !)。 これを回避する1つの方法は、インポートまたはエクスポートのいずれかに間接層を追加することです。 たとえば、真のインポートの代わりにサンクを非常に早い段階で提供できるため(HTMLでは、JSの前)、同期的に提供しているように見えます(ただし、JSを取得する前でも簡単に作成できるのはサンクだけです)。 。 その後、JSを入手したら、サンクを更新して適切な場所を指すようにすることができます。 これにより、別のJS呼び出しのオーバーヘッドと、インポート呼び出しごとのJSオブジェクトルックアップが追加されます。 また、コードサイズと起動にいくらかのオーバーヘッドがあります。

ユーザーの破壊について:既存のemscriptenユーザーがフラグあります。 多くのユーザーやパートナーはそれについて満足しています。 これにより、asm.jsとwasmを比較でき、移植に労力を費やしたプロジェクトは、新しい移植作業なしでwasmのメリットを享受できます。 また、wasmへの移植中にスタートアップコードを非同期化する必要があり、何かが壊れた場合に、wasmを不必要に非難する可能性があるというリスクを回避します。

JSの準備が整うまでJSのインポートはありません(ただし、メモリはあります!)

これは偶発的なことのようであり、APIを使用して永遠に時間を費やすべきではありません。 さらに、 @ s3ththompsonが説明した理由により、コンパイル時のメモリの問題を無視しても、とにかく非同期にするためにインスタンス化が必要@ jfbastienに同意します。ここには、理想的な最終状態APIがあり、ここで妥協するべきではありません。

ユーザーの破壊について:単純な移行パス(「onload」イベント/プロミスなど)を提供する場合、ユーザーが移行するのは簡単であり、ニンジンがすべての主要なパフォーマンスに勝ちます。 正確なasm.jsソースのbackcompatがデフォルト構成の厳しい要件であるという証拠はないと思います。 まったく逆の例がたくさんあります。もちろん、それが要点なので、ユーザーは最適なパフォーマンスを達成するために何でも喜んで行います。

オフラインで@lukewagnerと話していると、間接レイヤーを追加することで、emscriptenのデフォルトの推奨設定でwasmのインスタンス化を有効にすることから始めるのが最善だと思います(上記のように、ただしエクスポートで)。 ほとんどのユースケースでは、おそらくオーバーヘッドはごくわずかです。 つまり、これにより、私たち全員がここで望んでいるメリットが得られます。

最終的には、その小さなオーバーヘッドを取り除くことができますが、それを行うための明らかに良い/正しい方法がないため、計画やメーリングリストの議論などをさらに必要とする重大な変更になるでしょう。 ただし、間接層のオーバーヘッドは非常に低いと考えられるため、この部分は緊急ではありません。

@kripken素晴らしい! さまざまなインスタンス/ JS /インポート/エクスポート/メモリ/テーブルを示す図があると便利です。 このディスカッションを別の場所(Emscripten / binaryen repo)に移動しますか? 私はC ++コードがどのように編成されるべきかについての精神的なイメージを持っていますが、あなたが同じイメージを持っていないことは今ではかなり明白です! あなたはそこでより多くの経験を持っているので、私はそれから学び、私ができる限り助けたいと思っています。

@jfbastien :確かに。 ダイアグラムで何を探しているのかはまだわかりませんが、ええ、別の場所の方が良いかもしれません。 emscriptenでこれを実装するために、前述の問題https://github.com/kripken/emscripten/issues/4711があり

IIUC Emscriptenは、これをデフォルトで使用するようになりました。 閉鎖。

@ s3ththompsonコメントをフォローアップするには、同期コンパイルとインスタンス化が役立つことに注意してください。 特に、最近、Node.js( v7.7.2 )でWebAssemblyモジュールを同期的にロードしてコンパイルしたいという状況に遭遇しました。 promiseを返すAPIのみが使用可能な場合、これは同期エクスポートを提供できないことを意味します。

非同期、同期、または両方のAPIを提供するかどうかを決定するときは、WebAssemblyを使用したい環境はブラウザーコンテキストだけではないことに注意してください。 私を含め、多くの人々が、JVMに似たNode.jsランタイムと組み合わせた効率的なコンパイルターゲットとしてのWebAssemblyの可能性に興味を持っています。 非同期のインポート/エクスポートNode.jsに到達

@kgryte私のコメントは、主に実行コンテキストとしてのブラウザに関係していることを明確にする必要がありました。 同期APIをまだ公開しているAPIサーフェスにたどり着きました。 ブラウザは、同期APIに渡されるモジュールにサイズ制限を課す場合があります(たとえば、Chromeはすでにそうしています)が、その制限は埋め込み者によって構成可能であり、ノードに適用する必要はありません。

@ s3ththompson説明してくれてありがとう。

このページは役に立ちましたか?
0 / 5 - 0 評価

関連する問題

thysultan picture thysultan  ·  4コメント

frehberg picture frehberg  ·  6コメント

artem-v-shamsutdinov picture artem-v-shamsutdinov  ·  6コメント

nikhedonia picture nikhedonia  ·  7コメント

dpw picture dpw  ·  3コメント