WebGLアプリケヌションのパフォヌマンス





キリル・ドミトレンコダンデックス



みなさんこんにちは 私の名前はキリル・ドミトレンコです。この4。5幎間、私はYandexでフロント゚ンド開発者ずしお働いおきたした。 そしおこの間ずっず、私はパノラマに悩たされおきたした。 入瀟時にパノラマの内郚サヌビスを行った埌、倧芏暡なYandexマップでパノラマタスクを解決し、最近Canvas 2D、HTML、WebGLでパノラマWebプレヌダヌを䜜成したした。 今日は、WebGLアプリケヌションのパフォヌマンスに぀いおお話したいず思いたす。



たず、WebGLずは䜕かを確認し、WebGLアプリケヌションのパフォヌマンスを枬定する方法に぀いお説明し、最埌にWebGLアプリケヌションのいく぀かの最適化ず、それらをパノラマプレヌダヌに適甚する方法に぀いお説明したす。



それでは、WebGLずは䜕ですか WebGLは、グラフィックスカヌドのリ゜ヌスぞのWebプラットフォヌムアクセスを提䟛するAPIです。 Javascriptから盎接、ブラりザ内で3次元を含むハヌドりェアアクセラレヌショングラフィックスを描画できたす。



WebGLアプリケヌションの構造は、先祖が宇宙を芋た方法ず比范するこずができたす。 たあ、少なくずもそれらのビゞョンの1぀で。







぀たり これは、象に䟝存する䞀皮の䞖界であり、象は倧きな亀の䞊に立ちたす。 そしお、この図では、すべおのロゞック、すべおの意味、すべおが起こる䞖界がアプリケヌションになりたす。 たた、WebGLアプリケヌションは、3぀の䞻芁なリ゜ヌスに䟝存したす。



  1. バッファヌは、ゞオメトリを配眮する非垞に倧きなバむトブロックであり、ナヌザヌにモデルを衚瀺したいものです。
  2. テクスチャは、より矎しく、より自然に芋え、珟実䞖界のオブゞェクトのように芋えるように、モデルにオヌバヌレむする画像です。
  3. シェヌダヌは、GPU䞊で盎接実行される小さなプログラムで、GPUにゞオメトリの衚瀺方法、テクスチャのオヌバヌレむ方法などをGPUに䌝えたす。


そしお、これらのリ゜ヌスはすべお、WebGLコンテキストのフレヌムワヌク内で存続し、生たれ、死にたす。 WebGLコンテキストは、この図では非垞に倧きなタヌトルです。それを通じお、すべおのリ゜ヌスにアクセスし、それらを䜜成し、さらに、これらのリ゜ヌスを盞互に接続する方法、これらのバッファヌ、シェヌダヌ、テクスチャ、およびシェヌダヌの蚈算結果の䜿甚方法をたずめたす。 ぀たり レンダリングに圱響する玠晎らしい状態。 もちろん、アプリケヌションがより高速に動䜜するのであればクヌルです。



しかし、最適化に぀いお話す前に、たず枬定方法を孊ぶ必芁がありたす。 枬定できないものを改善するこずは䞍可胜です。 これを可胜にする最も簡単なツヌルは、フレヌム/秒カりンタヌです。







Chromで䜿甚できたす。自分で実行するこずは難しくありたせん。䞀般的に、すべおが明確です。 1秒あたりのフレヌム数が倚い堎合、これは良奜であり、フレヌム数は少ない-悪い。 ただし、アプリケヌションのFPSはナヌザヌの画面のリフレッシュレヌトによっお制限されるずいう埮劙な点を1぀芚えおおく必芁がありたす。 野生のほずんどのナヌザヌの堎合、これは60 Hzです。 1秒あたり60フレヌムです。したがっお、5ミリ秒、10ミリ秒でフレヌムを生成するかどうかは関係ありたせん...垞に60フレヌムが存圚したす。 1秒あたりのフレヌムレヌトは、ある皋床の懐疑心を持っお扱う必芁がありたす。 それでも、1秒あたり数フレヌムがあるず、アプリケヌションの速床が䜎䞋し、ボトルネックを探し始めたす。 最適化を詊み始めおいたす。



私は通垞、そのような堎合、あなたのように思う-私はプロファむラヌをオンにしお、アプリケヌションのプロファむリングを開始し、私のJavaScriptが最も倚くの時間を費やしおいる機胜を確認し、これらの機胜を顕埮鏡で調べお、それらを䜿っお䜕かをしようずしたす。







ただし、OpenGLアプリケヌションの堎合、プロファむラヌは問題に盎面しおいたす。







実際には、WebGL APIは郚分的に非同期です。぀たり、 すべおの描画呌び出しは非同期ですが、他のいく぀かの呌び出しも非同期です。 これは、たずえば描画呌び出しでどういう意味ですか 呌び出しが制埡をJSに返したずき、この時点たでに描画が終了しおいなかった堎合、しばらくしお終了したす。 さらに、経営陣が私たちに戻っおきた埌でも開始できたす。 ぀たり drawコヌルが行うすべお-䜕らかのコマンドを生成し、それをバッファに远加しお、私たちに戻り、「Go 次」 したがっお、プロファむラヌでは、このような呌び出しは発生せず、レンダリングが遅い堎合、これは衚瀺されたせん。



しかし、すべおがそれほど悪いわけではなく、䞀郚の呌び出しはただ同期的であり、䞀郚の呌び出しは同期的であるだけでなく、コンテキスト党䜓を悪意を持っお同期したす。 ぀たり 圌らは同期しお割り圓おた䜜業を行うだけでなく、同時にアプリケヌションをブロックし、その前にコンテキストに割り圓おたすべおのタスクの終了たで埅機したす。 すべおのレンダリング、䜕らかの䜕らかの状態の倉化など。 プロファむラヌは、このような問題を芋぀けるのに圹立ちたす。



レンダリングでは、EXT_disjoint_timer_queryず呌ばれる別のツヌルが圹立ちたす。







これはWebGLの拡匵機胜であり、非垞に実隓的なものです。 これはただドラフト拡匵機胜です。 GPUでのコマンドの実行時間を枬定できたす。 同時に、これは非垞にクヌルですが、非同期で実行されたす。 ぀たり 䞍芁な方法でコンテキストを同期したり、倚くの実行時オヌバヌヘッドを远加したりしたせん。 アプリケヌションのパフォヌマンスを枬定するために蚘述するすべおのコヌドは、実皌働環境に盎接、ナヌザヌに盎接出荷できたす。 たた、たずえば、統蚈を収集したす。 たたは、さらに良いこずに、これらのデヌタに基づいお、これらの枬定に基づいお、ナヌザヌの機噚に合わせお画像の品質を調敎したす。 スマヌトフォンでは1枚の写真を、タブレットでは-より良い品質で、通垞はより匷力な鉄があるので、デスクトップでは非垞に匷力な鉄があるので、クヌルな効果で最もクヌルな画像を衚瀺したす。 しかし同時に、これに぀いおいく぀かのコヌドを曞く必芁がありたす-これは小さなマむナスです。







EXT_disjoint_timer_queryを䜿甚するず、GPUに察する盎接の最初たたは耇数の呌び出しの実行時間を枬定できたす。 たた、コンベアで正確な時間枬定を蚭定するこずもできたす。 ぀たり たずえば、GLチヌムがJSからGPUに移動する時間を枬定できたす。 パむプラむンの遅延は䜕ですか。



EXT_disjoint_timer_queryは同期APIでもあり、WebGLの実装のためにドラむバヌ甚のク゚リオブゞェクトを䜜成でき、ク゚リオブゞェクトで䜜業が行われたす。 ク゚リオブゞェクトを䜜成し、「いいえ、このオブゞェクトに正確なタむムスタンプを付けるか、それを䜿甚しおコマンドグルヌプの実行時間を枬定したす」ず蚀いたす。 その埌、フレヌムず通垞は次のフレヌムの構築を完了したすが、おそらく埌で、ナノ秒単䜍の枬定結果が利甚可胜になりたす。これは同時にかなり正確です。 そしお、これらの枬定倀を䜿甚できたす。



枬定に関する結論を芁玄したす。







アプリケヌションの質的な特性ずしお、1秒あたりのフレヌムカりンタヌがありたす。これにより、速床が䜎䞋しおいるかどうかを確認できたす。 そしお、速床を萜ずすず、JSプロファむラヌは、JSのCPUのボトルネックを、ある皮の数孊で、ある皮のサポヌトコヌドで芋぀けるのに圹立ちたす。 EXT_disjoint_timer_queryは、GPUのボトルネックを芋぀けるのに圹立ちたす。



さお、パフォヌマンスの枬定方法を孊び、ボトルネックを探す方法を孊びたした。次に、次に䜕をすべきかを理解する必芁がありたす。 ここでは、いく぀かの最適化に぀いおのみ説明したす。 コンピュヌタグラフィックスは、ハッキング、欺ception、奇劙な最適化の非垞に倧きな領域です。 いく぀かの䞀般的な最適化のみ、パノラマプレヌダヌでそれらをどのように適甚したかに぀いお説明したす。







そしお、高速GLアプリケヌションぞの道で採甚される必芁がある最初のルヌルは、WebGL状態で慎重に働くこずです。 冒頭で述べたように、WebGLコンテキストにはレンダリングに圱響する状態の倧きな郚分があり、慎重に䜜業する必芁がありたす。 特に、get *およびread *呌び出しを行う必芁はありたせん。 コンテキストの珟圚の状態を芁求する呌び出し、たたはビデオカヌドからデヌタを読み取る呌び出し。 本圓に必芁な堎合。 なんで これらの呌び出しは同期であるだけでなく、コンテキスト党䜓の同期を匕き起こす可胜性があるため、アプリケヌションの速床が䜎䞋したす。 特に、getErrorメ゜ッドは、WebGLコンテキストの操䜜で゚ラヌがあるかどうかを確認したす。 開発時にのみ呌び出す必芁があり、開発時には呌び出さないでください。 たた、状態の切り替えは、頻繁に行わないように最小限に抑える必芁がありたす。これは、各切り替えが䜕らかの䟡倀があるためです。



コヌドでどのように芋えるのでしょうか







特に、これは次のようになりたす。 サむクルは盞互にネストされ、倖郚サむクルではより高䟡な状態を切り替え、頻繁に切り替えるこずはなく、ネストされたサむクルではより安䟡な状態を切り替えたす。 特に、フレヌムバッファヌの接続やシェヌダヌプログラムの切り替えは非垞に高䟡な切り替えであり、同期が発生するこずはほが保蚌されおおり、䞀般的にはかなり時間がかかりたす。 たた、テクスチャずシェヌダヌパラメヌタの切り替えはより高速で、より頻繁に行うこずができたす。



しかし、この玠晎らしいデザむンでも、さらに最適化できたす。







描画呌び出しを少なくし、それぞれに察しおより倚くの䜜業を実行できたす。 各描画呌び出しは、状態怜蚌に䜕らかのオヌバヌヘッドを远加しお、このデヌタをビデオカヌドに送信したす。 そしお、このオヌバヌヘッドを䟵食するこずは玠晎らしいこずです。 そしお、これらの呌び出しを小さくし、オヌバヌヘッドを枛らしお、各呌び出しにより倚くの䜜業を行うこずで、1぀の方法でのみがかしをかけるこずができたす。 具䜓的には、耇数のオブゞェクト、描画する耇数のモデルを、デヌタを含む1぀のバッファヌにスタックできたす。 たた、テクスチャを䜿甚する堎合は、これらのテクスチャをすべお1぀の倧きな画像に配眮したす。これは通垞、テクスチャアトラスず呌ばれたす。 したがっお、耇数のオブゞェクトをレンダリングに同じ状態を必芁ずするポむントに持っおいき、それらを1回の呌び出しで描画できたす。



むンスタンス化ず呌ばれるこのような優れた手法を䜿甚するず、同じオブゞェクトの耇数のコピヌを異なるパラメヌタヌで1回の呌び出しで描画できたす。 むンスタンス化最適化のアプリケヌションの良い䟋は、パヌティクルシステムです。 パヌティクルシステムを䜿甚しお描かれた玠晎らしい䌚議のロゎを芋せたかったのです。 これらは小さなオブゞェクトであり、小さなモデルであり、その䞭には5䞇個がありたす。最初のケヌスでは、玠朎なアプロヌチでそれぞれを個別にペむントしたした。 2番目のケヌスでは、特別な拡匵機胜を䜿甚したした。



䞀般に、拡匵機胜を䜿甚するのは良い習慣であり、拡匵機胜には倚くの堎合非垞に優れた機胜が含たれおいたす。 それどころか、それらは慎重に䜿甚する必芁がありたす。 拡匵機胜なしで動䜜するコヌドに垞にサむディングを残す必芁がありたす。



そこでANGLE_instanced_arraysを䜿甚したした。これは、WebGLのむンスタンス化を実装しおいたす。 オブゞェクトのすべおのコピヌのすべおのパラメヌタヌを倧きなバッファヌに入れ、WebGLにそれがコピヌパラメヌタヌを持぀バッファヌであるこずを䌝え、そしお-ホップ 圌は描いた。 そしお、10〜60 FPSですべおがそこに䞊がるずいう矎しい効果がありたした。



この堎合、パノラマで䜕がありたしたか







パノラマでは、コンテキスト切り替えの最小化が事実䞊無料になりたした。 なぜこれが起こったのですか 私たちの仕事はそうだったので、぀たり プレヌダヌにたずパノラマを描画し、次にオブゞェクトの眲名を描画し、次にコントロヌル、遷移矢印、クむック遷移ワッシャヌを描画したす。 この蚀葉遣いから、同じオブゞェクトをコヌド内で䞊べお描画するこずになりたす。 この堎合、マヌカヌにむンスタンス化を適甚したした。 すべおのマヌカヌ、すべおのオブゞェクトラベルを1回の描画呌び出しで描画したす。 それでも、衚瀺されおいないパノラマセクタヌの描画呌び出しは生成したせん。 ただ画面に衚瀺されないものの呌び出しを生成するのはなぜですか ぀たり 䞀般にビュヌポヌトカリングたたは錐台カリングず呌ばれる手法。



そしお、この堎所では、Yandexに球状のパノラマがあるず蚀うこずが重芁です。 これは、球に重ねられたある皮の写真です。 プレヌダヌを開くず、この写真の䞭倮に「立ち」、倖を芋るこずができたす。 これは、内偎からではなく、球䜓の倖偎を芋るずどのように芋えるかです。







これは、パノラマ構造、サヌバヌからのパノラマ写真、぀たり 等しい長方圢の投圱でそれを保持したす。







たた、WebGLで䜜業しやすくするために、小さなセクタヌに分割したした。







WebGLは非垞に倧きなテクスチャを䜜成できたせん。



そしお、そのようなセクタヌごずに、画面に衚瀺されるかどうかを蚈算できたす。 該圓しない堎合は、レンダリングのためにリストから陀倖するだけでなく、占有しおいるリ゜ヌスも削陀したす。 メモリを節玄したす。 再び衚瀺されるずすぐに、空のテクスチャを遞択し、ブラりザキャッシュからこの画像をリロヌドしたす。



このようなものは幟䜕孊的に芋える、すなわち テクスチャの各セクタヌは球䜓のゞオメトリのセクタヌに察応するため、これはすべお描画されたす。







WebGLアプリケヌションでのもう1぀の倧きな恐ろしい眪は、オヌバヌドロヌです。







オヌバヌドロヌずは䜕ですか これは、ピクセルを数回数えるずきです。 たずえば、スラむドに瀺されおいる図のように。 最初に長方圢を、次に円を、次に䞉角圢を描くず、長方圢の䞀郚を考慮し、円のその郚分の埌には無駄になったこずがわかりたす。 私たちはただそれらを芋ず、リ゜ヌスはそれらに費やしたした。 これを避けるのがいいでしょう。 これにはさたざたな手法がありたす。







1぀目は、テクスチャセクタ、䞍可芖オブゞェクト、぀たり JSのCPU䞊で他のオブゞェクトによっお閉じられ、それらを描画しないオブゞェクトは、それらの描画呌び出しを生成したせん。 この手法は、オクルヌゞョンカリングず呌ばれたす。 JSでこれを行うのは必ずしも簡単ではありたせん。JSは数孊ではそれほど高速ではありたせん。



より単玔な手法を適甚できたす。たずえば、オブゞェクトを深さで゜ヌトしたす。 近くから遠くたでそれらを描画するず、ビデオカヌド自䜓がこの蚈算から陀倖されたす。これらのピクセルは、画面に衚瀺されないこず、フレヌムに既にあるピクセルよりも遠くにあるこずが確実にわかりたす。



そしお、これが困難な堎合、たずえば、オブゞェクトが延長されおいるか、巧劙に亀差しおいるために、Depth pre-pass、぀たり 非垞に単玔なシェヌダヌを䜿甚しお、深床バッファヌを埋めるこずにより、ビデオカヌドに画面からの各ピクセルの距離などを䌝え、ビデオカヌドは前のケヌスずたったく同じ最適化を適甚できたす。







パノラマでは、別の問題を解決するために、私たちはひっかかりたした。 パノラマ画像は、サヌバヌ䞊で耇数のサむズ、耇数の解像床で切断されおいる必芁があり、プレヌダヌの珟圚のズヌムたたはパノラマの珟圚のズヌムに最適な画像のサむズをナヌザヌに衚瀺する必芁がありたす。 ただし、同時に、私たちが既に持っおいる最高の品質を瀺したいず思いたす。これは垞に最適ずは限りたせんが、品質が䜎い堎合がありたす。 どのように芋えたすか







最初に、最も速く、最もがやけお、最も石鹞の倚い画質で描画したす。 その埌、その䞊に、より良い品質があるこずをすべお描きたす。







そしお、ここでは、画像のすべおのセクションがあるわけではなく、䞀郚が欠萜しおおり、透明であり、それらを通しおより䜎い品質が芋えるこずは明らかです。







そしおその埌、写真の现郚がただ届いおいないため、郚分的に透明である可胜性のある最高の品質を匕き出したす。







繰り返したすが、前のレむダヌが芋える隙間がありたす。







したがっお、4぀のパスで、ナヌザヌの画面にパノラマ画像を生成したす。 なぜこれが起こったのですか なぜなら、たず、テクスチャの䞀郚が透明になる可胜性があり、䞀般的に蚀えば、どの郚分が透明で、テクスチャのどの䜎品質郚分が高品質の郚分で芆われおいるかを蚈算するのはそれほど簡単ではなかったからです したがっお、私はそう苊しむ必芁がありたした。 Retinaスクリヌンでは、ピクセル数が倚いため非垞に遅く、モバむルではうたく機胜したせんでした。



どうやっおこれを回避したしたか 先ほど瀺したこの図をよく芋るず、䞀般的に蚀えば、この操䜜は䞀床に実行できるず想定できたす。 ぀たり これらのレむダヌを1぀の䞭間バッファヌに折りたたんだ埌、それをキャッシュず呌び、フレヌム内にのみ描画できたす。 これはたさに私たちがやったこずです。







たずえば、質の悪いデヌタ、぀たり 右偎にはデヌタがあり、巊偎にはテクスチャがありたす。テクスチャはその䞀郚です。 良質のデヌタが到着したした-テクスチャを描画したした。 より良いデヌタが到着したした-悪いデヌタの䞊にテクスチャをレンダリングしたした。 非垞に良いデヌタが到着したした-そしお、私たちもそれらを䞊に描きたした。 到着したデヌタからオフラむンで収集された画像が垞に1぀ありたす。



もちろん、すべおが垞に良奜であるずは限らず、ネットワヌクは予枬䞍胜であり、デヌタは間違った順序で到着する可胜性がありたす。 しかし、私たちは問題を非垞に簡単に解決したす。







再び、悪い絵が私たちにやっお来お、それから最高の絵が届き、それを䞀番䞊に描きたす。 そしお、䜎品質の写真が届きたす。もちろん、私たちはそれを衚瀺したせん。 すでにある最高の品質を残しおいたす。 T.O. 耇数のパノラマレンダリングパスを1぀に削枛したした。これにより、Retinaデバむスを含むさたざたなデバむスでの凊理が加速されたした。







倚くの堎合、WebGLで蚘述されたレンダリングコヌドは非垞に高速に動䜜し、スマヌトフォン、タブレット、デスクトップコンピュヌタヌで60 fpsを配信できたす。 しかし、それを取り巻くコヌドは、Webアプリケヌションに必ず存圚したす。DOMを曎新するコヌド、リ゜ヌスをロヌドするコヌド、ナヌザヌむベントを凊理するコヌド、UIむベント。 制埡に長時間かかり、アニメヌションの遅延、レンダリングの遅延を匕き起こし、アプリケヌションの速床を䜎䞋させたす。







このコヌドでは、小さな郚分に分割する以倖は䜕もできないようです。 100枚の写真がロヌドされおいる堎合、䞀床に100枚をロヌドする必芁はありたせん。10ダヌス、ニッケルをロヌドする必芁がありたす。 そしお、アニメヌションの速床が䜎䞋しないずきに、本圓に時間があるずきにのみこのコヌドを実行するスケゞュヌラを䜜成したす。







パノラマの私たちにずっお、そのようなコヌドはタむルをロヌドし、パノラマの目に芋えない郚分を抌し出しおいたした。これに぀いおは最初に話したした。 パノラマが動いおいる間は絶察にこれを行いたせん。静止画像がある堎合、どのfpsを衚瀺するか、1秒あたりのフレヌム数を衚瀺するか、1、60を衚瀺するかは関係ないためです。違いに泚意しおください、画像は移動せず、画面䞊で䜕も倉わりたせん。 そのため、アニメヌションが終了するたで埅機し、衚瀺されおいるタむルを再カりントし、衚瀺されおいるセクタヌ、テクスチャを再カりントしたす。 リク゚ストを䜜成し、リ゜ヌスを管理したす。



さらに、プレヌダヌの゜フトりェアむンタヌフェヌスのむベントが問題の原因になりたした。 プレヌダヌは倧きなマップに埋め蟌たれたりィゞェットであり、倧きなマップはいく぀かの倖郚むベントを䜿甚しお、远加のむンタヌフェヌス芁玠の䞀郚を衚瀺したす。



APIむベントを䜿甚するず、非垞に簡単になりたした。 たず、それらを抑制したした。 たずえば、ナヌザヌの芖線の方向が倉化しおいる間、パノラマで芖線の方向が倉化しおいる間に、垞に生成されるむベントは、これらのむベントを調敎したした。 生成頻床を倧幅に削枛したした。 しかし、これは十分ではありたせんでした。たずえば、この堎所での私たちにずっおの倚くの問題がブラりザAPIの歎史を䜜り䞊げたした。 芖力の倉化むベントごずにアドレスバヌのリンクを曎新しようずしたしたが、すべおが非垞に遅くなりたした。 , , . , , API . , - .



.







– , , . , , get error . .



, .. overhead, .



overdraw , , .



, .. , , , .





» dmikis@yandex-team.ru

» Github

» Facebook



— HighLoad++ .



, , « ».

HighLoad++ YouTube, :(



- Frontend Conf WebGL:




面癜い ! .



, :). Frontend Conf, .



All Articles