最近、アニメーションがっつりなウェブアプリケーションを早くするみたいな仕事をしていて、ハードウェアアクセラレーションってどういう仕組みなんだろうと調べていたらこんな英語でこういう記事があったので、紹介してみる。
訳しつつ独自解釈を入れてみたのが以下のような感じ。
一般にアニメーショングラフィックスをCPUのみで処理しようとした際、アニメーションにおけるフレーム毎にピクセル単位で生成し、描画するという処理を行っている。一方でCPU+GPUを処理に用いる場合、アニメーションさせる要素をGPUで確保されている無数の「テクスチャー(レイヤー)」に書き込む。そのうえでCPUからのアニメーション処理要求に応じてGPUが内部的にアニメーションを行うことで、高速な処理を実現している。
一般にいうブラウザのHA(ハードウェアアクセラレーション)とは、アニメーションを行わせるDOM要素を抽出し、その単位でGPUテクスチャー(レイヤー)に保存しGPUに命令することを行っていることで描画性能を出すことを行っている。
一方でその内部処理は非常に複雑な処理であるということをウェブアプリ実装者は意識する必要がある。例えば「translate3dを使えばパフォーマンスが改善される」というのは通説だが、それはケースバイケースであり、あるケースにおいては極めて有効な手段であることもあれば、パフォーマンスが悪い理由が別にあるためほとんど効果が出ないこともある。したがってどのような実装を行えばよいのかを考える際は、ハードウェアアクセラレーションがどのようなものであるのかを理解する必要がある。
そのうえで意識するべきことはCPUとGPUのバス(データのやり取り)の量である。ウェブアプリケーションのレイヤー(composited layers)である。ブラウザはレイヤーごとにGPUテクスチャーを生成してしまうため、多くのレイヤーが生成されるとその分のメモリーを消費してしまう。その結果、フレームがスキップされてしまったりクラッシュの原因になってしまう。あるウェブアプリケーションでどれだけレイヤーが生成されているのかを確認するためにはブラウザのデバッグモードを利用するといい
■ Firefoxの場合
about:config -> layers.draw-borders を trueに
■ Chromeの場合
chrome://flags/#composited-layer-borders を enableに
CPUとGPUのバス(データのやり取り)の量を最小限に維持したままにすることも重要である。そのためには、あるアニメーションが始まってから終了するまでは他のアニメーションやレイヤーのアップデートをできる限り実行しないようにすることが必要である。
描画性能の最適化を図るうえでFPSを意識することは重要である。FPSを見るにはブラウザ下記のような設定をすればよい
■ Firefoxの場合
about:config -> layers.acceleration.draw-fps を trueに
■ Chromeの場合
chrome://flags/#show-fps-counter
このあたりで根気が尽きたのでいったん公開。
間違いがあればだれか修正してくれると嬉しい。