46

コンテキスト: 巨大なログ ファイルを処理して表示する Web アプリケーションがあります。通常は約 10 万行の長さですが、最大で 400 万行以上になることもあります。そのログ ファイルを (ユーザーが開始したものと JavaScript を介して) スクロールし、適切なパフォーマンスで行をフィルター処理できるようにするために、データが (ajax を介して JSON で) 到着するとすぐに各行の DOM 要素を作成します。これは、バックエンドで HTML を構築するよりもパフォーマンスが優れていることがわかりました。その後、要素を配列に保存し、表示されている行のみを表示します。

最大 100k 行の場合、これには数秒しかかかりませんが、500k 行 (ダウンロードを除く) の場合、それ以上の場合は最大 1 分かかります。もっとパフォーマンスを上げたいと思ったので、HTML5 Web Workers を使ってみました。ここでの問題は、DOM の外部であっても、Web Worker で要素を作成できないことです。そのため、Web Workers で json から HTML への変換のみを行い、結果をメイン スレッドに送信することになりました。そこで作成され、配列に格納されます。残念ながら、これによりパフォーマンスが低下し、少なくとも 30 秒以上かかるようになりました。

質問: Web Worker で DOM ツリーの外側に DOM 要素を作成する方法はありますか? そうでない場合、なぜですか?要素の作成は問題なく並行して行われる可能性があるため、これにより同時実行性の問題が発生することはないように思えます。

4

9 に答える 9

17

わかりました、@Bergi が提供した情報を使用してさらに調査を行ったところ、W3C メーリング リストで次の議論が見つかりました。

http://w3-org.9356.n7.nabble.com/Limited-DOM-in-Web-Workers-td44284.html

また、Web Worker で XML パーサーまたは DOM パーサーにアクセスできない理由の抜粋:

DOM 実装コードのいずれも、これまでにいかなる種類の非 DOM オブジェクトも使用していないか、使用している場合でもそれらのオブジェクトは完全にスレッドセーフであると想定しています。少なくとも Gecko ではそうではありません。

この場合の問題は、複数のスレッドで同じ DOM オブジェクトが操作されることではありません。問題は、異なるスレッド上の 2 つの DOM オブジェクトが両方ともグローバルな 3 番目のオブジェクトに接触していることです。

たとえば、XML パーサーは、Gecko ではメイン スレッドでしか実行できないいくつかのことを実行する必要があります (DTD のロード、オフハンド。他にもいくつか見たことがありますが、オフハンドを思い出すことはありません)。

ただし、 jsdomがその例であるパー​​サーのサードパーティ実装を使用する回避策も記載されています。これにより、独自の個別のドキュメントにアクセスすることさえできます。

于 2013-08-07T11:44:16.130 に答える
12

Web Worker で DOM ツリーの外側に DOM 要素を作成する方法はありますか?

いいえ。

なぜだめですか?要素の作成は問題なく並行して行われる可能性があるため、これにより同時実行性の問題が発生することはないように思えます。

それらを作成するためではありません、あなたは正しいです。しかし、それらをメインに追加するには、document後でワーカーからアクセスできないように、別のメモリに送信する必要があります (ブロブの場合と同様)。ただし、WebWorkers で利用できる Document 処理はまったくありません

データが (ajax 経由で JSON で) 到着するとすぐに、各行の DOM 要素を作成します。その後、要素を配列に保存し、表示されている行のみを表示します。

50 万を超える DOM 要素を構築するのは大変な作業です。表示されている行に対してのみ DOM 要素を作成するようにしてください。パフォーマンスを向上させ、最初の数行をより速く表示するために、処理を小さな単位に分割し、その間にタイムアウトを使用することもできます。激しい Javascript ループがブラウザをフリーズするのを防ぐ方法を参照してください。

于 2013-08-06T16:58:59.210 に答える
3

Web ワーカーを使用して html 文字列を作成できない理由がわかりません。しかし、パフォーマンスが大幅に向上するとは思えません。

これは Web-Workers とは関係ありませんが、解決しようとしている問題に関連しています。スピードアップに役立つ可能性のあるいくつかのことを次に示します。

  1. DocumentFragments を使用します。データが入ってきたら要素を追加し、一定間隔で (1 秒に 1 回など) フラグメントを DOM に追加します。この方法では、テキスト行が読み込まれるたびに DOM に触れる必要はありません (再描画が発生することもありません)。

  2. バックグラウンドで読み込みを行い、ユーザーがスクロール領域の下部に到達したときにのみ行を解析します。

于 2013-08-05T16:58:43.310 に答える
1

設計にはいくつかのアンチパターンがあります。

  1. DOM オブジェクトの作成にはかなりのオーバーヘッドがあり、一度に何百万ものオブジェクトを作成する可能性があります。
  2. Web ワーカーに DOM を管理させようとすることは、まさに Web ワーカーが向いていないことです。DOM イベント ループの応答性を維持するため、他のすべての処理を行います。

カーソル パターンを使用して、任意の大きなデータ セットをスクロールできます。

  1. DOM は、開始位置と要求された行数 (カーソル) を含むメッセージをワーカーに送信します。
  2. Web ワーカーはログにランダム アクセスし、取得した行 (カーソル データ) をポスト バックします。
  3. DOM は、非同期カーソル応答イベントで要素を更新します。

このように、手間のかかる作業はワーカーによって行われ、そのイベント ループは DOM ではなくフェッチ中にブロックされます。その結果、ブロックされていないユーザーは、すべてのアニメーションがいかにスムーズであるかに驚くことになります。

于 2016-06-12T06:30:45.767 に答える
1

https://developer.mozilla.org/en-US/docs/Web/Guide/Performance/Using_web_workersによると、残念ながら Web ワーカーから DOM にアクセスすることはできません。

于 2013-08-05T11:24:39.140 に答える
0

そのため、Webworker で DOM を直接作成することはできませんが、メイン スレッドの外でかなりの処理を行う別のオプションがあるかもしれません。

私が作成したこの jsPerf をチェックしてください: http://jsperf.com/dom-construction-obj-vs-str

基本的に、DOM から取得した値とすべて同じ値を持つ POJSO を発行し、メッセージを受信した後にそれを DOM オブジェクトに変換することができます (これは、結局のところ、HTML を取得するときに行っていることです。POJSO は単に低いだけです) 追加の文字列処理を必要としないため、オーバーヘッド)。このようにして、イベント リスナーの発行などを実行することもできます (たとえば、イベント名の前に '!' を付け、その値をテンプレートが提供するビュー引数にマップします)。

一方、DOM パーサーが利用できない場合は、必要に応じてテンプレートを変換したり、テンプレートを高速な形式にコンパイルしたりするために、独自のものが必要になります。

于 2016-02-23T22:44:16.913 に答える