Mozilla Hacksの「The whole web at maximum FPS: How WebRender gets rid of jank」を読みました。Firefox Quantum期の記事で、Servo由来の描画技術であるWebRenderが、なぜ単に「速い」だけでなく「滑らかさ」を重視していたのかを説明しています。
この記事は2017年時点の内容で、WebRenderは当時Firefoxへ統合されていく途中の技術として紹介されています。前に紹介したFirefox 100のProcess Isolation記事ではWebRenderが前提技術として出てきましたが、今回の記事はそのWebRender自体がどんな発想で作られたかを掘り下げています。
記事の要点
- WebRenderの目的は、単に描画を速くすることではなく、60FPS以上の滑らかさを安定させることです。
- ブラウザは1フレームを約16.67ms以内に描画する必要があり、この時間枠を超えるとフレーム落ちやjankとして見えます。
- 従来のブラウザは、変更部分だけを塗り直すinvalidationや、layerとcompositingで作業量を減らしてきました。
- ただしlayerはメモリを使い、どこをlayer化するかの判断を誤ると逆に遅くなることがあります。
- WebRenderは、paintingとcompositingを分ける発想を見直し、GPUを3Dゲームエンジンのように使う方向へ進みます。
- Layoutからはframe treeではなく、高水準の描画命令であるdisplay listを受け取り、RenderBackendがGPU向けのdraw callへ変換します。
- Early culling、render task tree、batching、opaque/alpha pass、Z-cullingなどで、GPUが無駄な仕事をしないようにします。
- テキストglyphなど一部は当時まだCPU側で扱われ、PathfinderでGPU化の実験も進められていました。
リンク先も見てわかったこと
記事冒頭で参照されているQuantum CSS / Styloの記事では、Servo由来のCSS engineが並列処理を使ってstyle計算を速くする話が扱われています。WebRender記事でも、CPU側で残るglyph描画などを並列化する文脈で、Styloのwork stealingが参照されています。Firefox Quantum期の性能改善は、CSS計算と描画の両方で「並列化」と「仕事量の削減」を進めていたことが見えてきます。
servo/webrenderのGitHubリポジトリでは、WebRenderがGPU-based rendererとして説明されています。Webページを単なる2Dの塗りつぶしではなく、GPUに向けた描画命令として組み立てる発想が、このリポジトリ説明からも確認できます。
Pathfinderは、フォントやベクターグラフィックスをGPUで扱うための実験として記事内で参照されています。WebRenderがすべてを一気にGPUへ移したわけではなく、どの処理をCPUに残し、どの処理をGPUへ移すかを段階的に見極めていた点が重要です。
気づき
今回の気づきは、WebRenderの本質は「毎フレーム全部描く」という単純な力技ではなく、「全部描けるだけの形に仕事を組み替える」ことにあるという点です。GPUは大量のピクセルを並列に処理できますが、draw callが細かすぎたり、shader切り替えが多すぎたり、見えないものまで塗ったりすると、その強みを活かせません。
だからWebRenderは、display listから不要なものを早く除外し、render task treeで中間textureを減らし、batchingでGPUの状態変更を減らし、Z-cullingで隠れるpixelの計算を避けます。単に「GPUを使えば速い」ではなく、GPUが得意な形へWeb描画を再構成しているところが面白いです。
また、記事の中で何度も出てくるのは最高速度よりも一貫性です。平均FPSが高くても、数フレームだけ重くなればユーザーにはjankとして見えます。WebRenderは、速さのピークを上げるより、性能の崖を減らして滑らかさを保つための設計だったと読むと理解しやすくなります。
読むとよさそうな人
- ブラウザのpainting、compositing、GPU描画の違いをざっくり知りたい人
- Firefox Quantum期の性能改善でWebRenderがどんな役割を持っていたか知りたい人
- jankやframe budgetを、ブラウザ内部の描画パイプラインから理解したい人

コメントを残す