Mozilla Flux

Mozilla関係の情報に特化したブログです。

Firefox 60以降でもMozilla Add-ons(AMO)上で拡張機能を動作させる裏技

Firefox 57以降、初期設定のままだと拡張機能はMozilla Add-ons(AMO)などMozillaが運用するWebサイト上で動作しない。悪意ある拡張機能にMozillaの信用性を利用されないための措置だが、拡張機能の使い勝手は当然落ちる。マウスジェスチャが使えないだけでなく、たとえば右クリック+マウスホイール回転でタブを切り替えていく場合、該当するWebサイトがあると、そこで切り替えが止まってしまうのだ。

そこで、How to enable Firefox WebExtensions on Mozilla websites - gHacks Tech Newsなどで紹介されているテクニックを利用している人もいるだろう(Bug 1384330参照)。方法をおさらいしておくと、1.アドレスバーに"about:config"と打ち込んでページを開き、「動作保証対象外になります!」という警告が出たときは、「危険性を承知の上で使用する」をクリックして先へ進む。2. privacy.resistFingerprinting.block_mozAddonManagerの設定を新規作成し、真偽値をtrueにする。

だが、Firefox 60以降、このテクニックだけでは不十分になった(Bug 1445893参照)。拡張機能の動作を制限するドメインの仕組みが新たに追加されたためだ。このドメイン一覧からAMOを取り除くという一捻りが必要となる。

about:configの画面で検索ボックスにextensions.webextensions.restrictedDomainsの設定名を入力し、表示された設定をダブルクリックしてみよう。すると「文字列を入力してください」というダイアログが表示されるので、"addons.mozilla.org,"を消去し、OKをクリックする。これで再びAMO上で拡張機能が動作するようになる。ただし、公式にサポートされた方法ではないので、将来的に通用しなくなる可能性があることに注意してほしい。

Firefox Quantumのイースター・エッグ

今さらではあるが、Firefox 57以降を対象としたイースター・エッグの存在が判明したので紹介しておきたい(Bug 1405009)。

Firefox Quantumの新UI(Photon)では、オプション画面に検索機能が付いており、検索文字列と一致する項目をピックアップしてくれるのだが、一致する項目がない場合は、その旨のメッセージとともにモノトーンの画像が表示される。

f:id:Rockridge:20180430210051p:plainf:id:Rockridge:20180430210107p:plain
左:オプション画面の検索機能 右:一致する項目がなかった場合

ところが、検索文字列に「🔥🦊」の絵文字(つまり火と狐)を入力すると、専用のカラー画像が表示されるのだ。画像に出てくるキャラクターたちはPhoton UIの各所で用いられているが、ふだんはモノトーンで描かれているものが、色鮮やかに、しかも集合写真風に並ぶとそれなりに味わいがある。

f:id:Rockridge:20180430210432p:plain
イースター・エッグの画像

Australisのときは画像が動いていたので、それと比べると今回のイースター・エッグは慎ましいが、制作者の遊び心が感じられてよい。

Firefox QuantumのOff Main Thread Painting(OMTP)とRetained Display Listsについて

Windows版Firefox 58でOMTPが有効化

Firefox 58ではWindows版に限って、以前紹介したOff Main Thread Painting(OMTP)と呼ばれる機能が有効化されている(Bug 1403935)。このOMTPに対し、画像処理に関するものだという誤解が一部にあるようなので、その誤解を解いておきたい。

まずはGeckoのグラフィックス・パイプラインのおさらいから。Geckoでは、DOMツリー → フレームツリー → ディスプレイリスト → レイヤーツリーの順に処理が流れていき、最後にcompositorがレイヤーツリーを合成する。今回取り上げるのは、「ディスプレイリスト → レイヤーツリー」の処理の部分だ。

f:id:Rockridge:20171204000145p:plain
Geckoのグラフィックス・パイプライン

Off-Main-Thread Painting – Mozilla Gfx Team Blogによれば、Geckoの描画処理は、合成(Compositing)のフェーズを別にすると3段階に分けることができる。具体的には、1)ディスプレイリストの構築、2)レイヤーの割り当て、3)ラスタライゼーションである。

1)ディスプレイリストの構築では、ページ内の視覚的要素を収集し、ディスプレイアイテムと呼ばれる高水準プリミティブを生成する。2)レイヤーの割り当てでは、ディスプレイアイテムをグループにまとめてPaintedレイヤーと呼ばれる複数のレイヤーに割り当てる。3)ラスタライゼーションでは、レイヤーに割り当てられたディスプレイアイテムが実際に描画される。

これまでは上記3段階がすべてメインスレッドにおいて処理されてきた。これに対し、OMTPは3段階目のラスタライゼーションを別スレッドで非同期に処理する。この別スレッドは、ペイントスレッドと呼ばれる。

f:id:Rockridge:20180128204314p:plain
ラスタライゼーションの非同期化

メインスレッドはラスタライゼーションの手前で解放され、次の処理に移ることができる。また、ペイントスレッドはメインスレッドと並行してラスタライゼーション処理に集中することができる。この流れ作業によって、スレッド間での処理の受け渡しが発生するものの、全体としては、互いに前の処理を待つ時間を短縮することが可能になるわけだ。

f:id:Rockridge:20180128204257p:plain
非同期化による流れ作業の実現

OMTPが力を発揮するのは、メインスレッドの処理に余裕がない場合である。たとえば、重いJavaScriptを処理しながらグラフィックスの処理も行う場面では、ラスタライゼーションをペイントスレッドが担うことで、処理落ちを防ぐことができる。そうした場面でOMTPを有効化すると、Windows版で30%程度フレームレート(FPS)が向上することが、Mozillaの開発者の調査結果から明らかになっている。

f:id:Rockridge:20180128204241p:plain
OMTPによるFPSの向上

Retained Display Listsでディスプレイリストの構築コストに対処

Firefox 59以降のNightlyチャンネルでは、Retained Display Listsと呼ばれる機能が有効化されている(Bug 1416055)。この機能は前記の1)ディスプレイリストの構築に関わるもの。Geckoの描画処理において、ディスプレイリストの構築は処理時間の40%以上という高い割合を占める。Retained Display Listsは、リストの構築コストを大幅に削減するための技法だ。

Retained Display Lists – Mozilla Gfx Team Blogによれば、これまで、スクリーンの表示内容に変更が生じたときは、ディスプレイリストを一から構築し直していた。他方、Retained Display Listsの導入後は、これを原則として維持し、表示内容が変更された部分についてだけ新しいリストを構築して、新リストを旧リストに統合する。通常、表示内容が変更されるのは画面内の一部にとどまるので、新リストは比較的小さなもので済む可能性が高い。一から構築し直す場合と比べて処理時間を短縮できるわけだ。

Mozillaの開発者がFirefox 58 Betaのユーザーを対象にA/Bテストを実施しており、Retained Display Listsを有効化すると、16ミリ秒を超える「遅い」描画処理を30%近く削減できるという結果が出ている。しかも、Firefox 59には表示内容に全く変更がなければリストを維持し続ける機能(Bug 1419021)が追加実装されたため、現在ではさらに効果が大きくなっているとみられる。

f:id:Rockridge:20180128204323p:plain
Retained Display Listsの効果

OMTPのように「重いJavaScriptを処理しながら」といった制約がない分、Retained Display Listsのメリットは大きいが、表示内容に変更が生じた分だけディスプレイリストを構築する仕組みは複雑であり、完成までに時間がかかっている。現状ではFirefox 59リリース版への投入は難しく、Firefox 60で有効化されることになりそうだ。

マウスホイールでページをスクロールする際の小技(Firefox 58以降)

Firefox 58がリリースされ、既に手動アップデートが可能な状況になっている。パフォーマンスの向上については別記事を参照していただくとして、ここではマウスホイールでページをスクロールする際の小技を2つ取り上げたい。どちらもFirefox 58で実装された機能だ。

1つ目は、スムーズスクロールの挙動を変更するというもの(Bug 1402498)。about:configのページでgeneral.smoothScroll.msdPhysics.enabledをtrueに変更すると有効化される。加速・減速のシミュレーションにcubic-bezierを用いる現行方式とは異なり、新方式ではMass-spring-damperを用いるのだという。実際にマウスホイールを回してページをスクロールさせてみると、現行方式よりも加速の度合いが大きく、より少ないホイール回転で終端に到達する。新方式を好むユーザーも少なくないのでは、と思う。

2つ目は、Shiftキーを押しながらマウスホイールを回すと横スクロールになるというもの(Bug 143038)。macOS版ではOSの挙動に合わせて最初からそうなっているようだが、Windows版などでは旧式の拡張機能を使わないと実現できなかった。旧式拡張機能の廃止に伴い、16年前に登録されたバグが修正され、デスクトップ版における方式が統一された。

Firefox 58でWebAssemblyの起動を大幅に高速化

WebAssemblyは既にメジャーなブラウザすべてでサポートされており、その用途も、たとえばGoogle Earthが移植されるなど、ゲームに限られなくなってきている。もっとも、これまではダウンロード後のコンパイルに時間がかかるという問題があった。Firefox 58では2つの新技術でこの問題に対処し、WebAssemblyアプリケーションの起動を大幅に高速化する。

Making WebAssembly even faster: Firefox’s new streaming and tiering compiler – Mozilla Hacksによれば、1つ目の新技術はストリーミング(Streaming)という。ダウンロードの完了を待たずにコンパイルを開始するもので、この技術はWebAssemblyのファイル形式と相性がいい。単一のファイルのうち、最初にコード部分がダウンロードされるため、これをコンパイルしながら、データ部分のダウンロードの完了を待つことができるのだ。

f:id:Rockridge:20180121174236p:plain:w400
WebAssemblyファイルの構造

もう1つの技術は、段階的(tiered)なコンパイルである。動作は高速だが生成されるコードの最適化が弱いコンパイラと、動作は低速だが生成されるコードの最適化が強力なコンパイラを用意しておき、初めに前者のコンパイラがメインスレッドでWebAssemblyファイルのコンパイルを行う。コードの実行が始まったところで、これと並行して後者のコンパイラが別スレッドで動き出し、コードのコピーに対し最適化を施す。最適化が完了したコードは、メインスレッドのコードと置き換えられる仕組みだ(ホットスワップ)。

f:id:Rockridge:20180121180415p:plain:w600
WebAssemblyファイルの段階的なコンパイル

1段階目のコンパイラは、2段階目のそれよりも10倍から15倍も高速にコンパイルを行うことができる一方、生成されるコードの速度は2段階目のコンパイラと比較して、半分程度を確保している。この2段階のコンパイルはWebAssemblyのすべてのコードに対して適用されるが、それによってWebAssemblyの強みである処理速度を損なうことはない。

このように、Firefox 58では、1段階目のコンパイラがWebAssemblyファイルのダウンロード完了を待たずにコンパイルを開始し、実行中のコードは2段階目のコンパイラが最適化したコードに後で置き換えられるわけだ。では、実際にどの程度の威力を発揮するのだろうか。

GitHub上でMozillaの開発者が公開しているベンチマークを、Firefox 57.0.4(ビルド ID: 20180103231032)とFirefox 58 RC1(ビルド ID :20180115093319)の双方で走らせてみた。12.4MBのWebAssemblyファイルについて、WebAssembly.instantiate()の所要時間を計測するもので、単位はミリ秒(ms)。例えばダウンロード完了からの所要時間が1000msだとすると、1秒あたり12.4MBのコードを処理できていることになる。ベンチマークでは、そのスループットも結果として表示される。5回計測した平均は、以下のとおり。

Firefox 57 Firefox 58
所要時間 2611.9 ms 319.0 ms
スループット 4.8 MB/s 38.9 MB/s

Firefox 58のほうが約8.1倍も高速という結果になった。これだけ速ければ、実環境でも違いを体感できるはず。さらにそう遠くない将来、WebAssemblyのコンパイル結果はHTTPキャッシュに保存され、2回目以降の起動が加速される見通しだ。実行開始から一貫して速いと開発者に知れ渡れば、WebAssemblyアプリケーションの普及に弾みが付くことだろう。