Mozilla Hacksの「Inside a super fast CSS engine: Quantum CSS (aka Stylo)」を読みました。Firefox Quantum期に、Servo由来の新しいCSS engineであるQuantum CSS、当時の名前でStyloがFirefoxへ入っていく背景を説明する記事です。
前回紹介したWebRenderの記事がpainting/compositing寄りの話だったのに対し、今回の記事はその手前、HTMLとCSSから各要素の見た目を計算するstyle computationの話です。
記事の要点
- Quantum CSSは、ServoからFirefoxへ移植された最初の大きなコンポーネントとして紹介されています。
- CSS engineは、DOM nodeごとにどのCSS ruleが適用されるかを決め、各CSS propertyのcomputed valueを作ります。
- その中核には、selector matchingとcascadeがあります。
- CSS propertyは膨大なので、computed styleをそのまま全nodeに持たせるのではなく、fontなど関連する値をstyle structとして共有します。
- Styloはstyle computationを複数CPU coreへ分散し、DOM treeの枝ごとに並列処理します。
- DOM treeは不均等になりやすいため、work stealingで空いたcoreが他のqueueから仕事を取れるようにします。
- Rustを使うことで、並列処理で怖いdata raceをコンパイル時に防ぎやすくしています。
- Firefox由来のrule treeでrestyle時のselector matchingを減らし、Safari/Chrome由来のstyle sharing cacheを発展させて初回計算も高速化します。
リンク先も見てわかったこと
記事内から参照されているdata raceの説明記事を読むと、並列処理の難しさがよりはっきりします。複数の処理が同じデータへ同時に触ると、再現しづらいバグにつながります。StyloがRustを使った意味は、単に新しい言語を採用したことではなく、Firefoxの中核で安全に並列化するための土台を得たことにあります。
また、記事中で紹介されているRustのparallelismやwork stealingに関する動画リンクも、Styloが「CSS engineをちょっと速くした」程度の話ではなく、ブラウザ内部の計算を現代的なCPUの複数coreへどう分散するかという話だと示しています。
WebRender記事と合わせて読むと、Firefox Quantum期の設計方針が見えてきます。Styloはstyle computationを並列化し、WebRenderは描画側をGPU向けに再構成する。どちらも、既存のWeb互換性を保ったまま、内部の仕事の分け方を大きく組み替える取り組みでした。
気づき
今回の気づきは、Quantum CSSの速さは「CSS selectorを速く探す」だけではなく、「同じ仕事を繰り返さない」「並列化しても壊れない」「過去の最適化を捨てずに組み合わせる」という複数の設計が重なっている点です。
並列化は目立つ要素ですが、それだけでは足りません。restyle時にはrule treeで以前のmatching結果を再利用し、似たnodeにはstyle sharing cacheでcomputed styleを共有します。さらに、その並列処理をRustで安全に書けるようにする。記事を読むと、性能改善は単一の特効薬ではなく、計算量、メモリ、再利用、安全性を同時に詰める仕事だとわかります。
もう一つ印象的なのは、Quantum CSSが「4つのブラウザの先行技術を組み合わせた」と説明されていることです。Servoの並列化、Firefoxのrule tree、Safari/Chrome系のstyle sharing cacheなど、ブラウザ間で積み上がってきた知見をFirefoxの中に再構成している。Webエンジンの進化は、競争だけでなく、長年の実装知識の再利用でもあるのだと感じました。
読むとよさそうな人
- Firefox Quantum期の高速化で、Styloが何を担当したのか知りたい人
- CSS engineがselector matchingとcascadeで何を計算しているのか整理したい人
- Rustがブラウザ内部の並列処理にどう効いたのかを知りたい人

コメントを残す