Dec 11, 2010
XULに追加された「layer」属性には、XULと低レベルのレイヤの入り交じりっぷりが顕れていた
Firefox4 オワタ - alice0775のファイル置き場で既報だけど、Bug 588764 – Content area needs a grey border and shadow around itというバグのパッチでborderのためだけに新たにXULのボックスが追加された。
最初このパッチを見た時、僕は「なんじゃこりゃ」と思った。こんなもんレイアウト目的の空divと同じ発想じゃないか! 何やってんだ! こんなもんCSSのborderでやりゃいいじゃないか! と。(既にタブの中にもレイアウト調整用のボックスが入ってるけど、まあ、それはさておく。)
でも当該バグの最初の方についてるコメントや最初のバージョンのパッチでは、hbox#browser(ブラウズ領域のコンテナ要素)に対してCSSでborderを設定してるんだよね。それで分からなくなった。何でわざわざ、ボーダーのためだけにXUL要素を増やしたのか。そこには何か理由があるんじゃないのか? っていうかそもそも、この追加された要素に付いてるlayer="true"
ってのは何なんだ?
と疑問に思ったので議論の流れを追ってみたら、Bug 590468 – Reduce size of chrome document layer due to status barという別のバグが参照されていた。layerという属性もこのバグのパッチで導入されたらしい。
そっちの議論を読んでみたところ、どうもこういうことらしかった。
- ブラウザウィンドウのXULの要素ツリーは、(部分的に省略して要点を残すと)
となっている。<vbox> <toolbox/> <hbox id="browser" style="background:transparent"> <browser/> <hbox> <hbox id="browser-bottombox/> </vbox>
- この時、hbox#browserは透明だが、toolboxとhbox#browser-bottomboxは不透明なので、結果的に、その上位のvbox要素はウィンドウ全体を覆う大きさの描画領域を持つ事になる。
- browser(コンテンツ領域のインラインフレーム)の描画領域は、最上位のvboxの描画領域の上に載っかっている形になる。
- そのため、例えばツールバー上の1箇所に変更があった時であっても、最上位のvboxの描画領域全体が再描画されて、その上に載っかっているコンテンツ領域の描画領域も再描画される、という無駄な処理が沢山行われてしまう。
- それだけでなく、最上位のvboxの描画領域全体の情報を保持するために無駄にメモリを使う事になる。必要なのはtoolboxとhbox#browser-bottomboxの分のメモリだけで、hbox#browserの部分(完全に透明)のメモリは不要なのに。
- この無駄をなくしてパフォーマンスを改善するためには、描画領域の大きさをもっと賢く計算する必要がある。この例だったら、「最上位のvboxの大きさの描画領域」ではなく、本当に必要な「toolboxの大きさの描画領域」と「hbox#browser-bottomboxの大きさの描画領域」という2つの最小限の領域を求めるようにしないといけない。
- しかし、今それをやるには人的リソースが足りない。
- なので次善の策として、「このXUL要素には専用に描画領域を割り当ててくれ」ということをGeckoの低レベル(よりネイティブ寄り)の描画処理に伝える方法として、XULにlayerという属性を導入する。
layer="true"
が指定されたXUL要素は、強制的に専用の描画領域を持つようになる。- hbox#browser-bottomboxが専用の描画領域を持つようになった事で、最上位のvboxのために必要な描画領域はtoolboxの大きさだけで済むようになった(hbox#browserの部分が透明なので、その部分は描画領域が確保されなくなる)。
- この変更によって、toolbox、コンテンツ領域、hbox#browser-bottomboxのそれぞれが、お互いに重なり合わない描画領域を形成するようになった。
- ひいては、描画周りのパフォーマンスが向上した。
最近はWebGLとかどんどんネイティブ寄りの所に突っ込んでいってパフォーマンス改善に注力してるようなので、こういう事もまあ必要なんだろう。Firefox 4リリースが近くて大規模な変更を入れられる余裕が無いから、インテリジェントな判断が必要な所について、インテリジェントな判断のためのロジックを実装する代わりに、人力でインテリジェントな判断をあらかじめ下しておこう、という苦肉の策のようだ。
そこで最初の話に戻るんだけど、単純にhbox#browserにCSSでborderを設定してしまうと、こういう事が起こってしまうという指摘がなされたようだ。
- hbox#browserのボックスが完全な透明ではなくなってしまう。
- よって、最上位のvboxの描画領域がtoolbox+hbox#browserの大きさに拡大されてしまう。
- すると、描画領域がコンテンツ領域と重なる状態に戻ってしまう。
- 描画周りのパフォーマンスが落ちてしまう。これじゃ元の木阿弥だ。
- なので、hbox#browserにCSSのborderを設定するのは諦める。
- 代わりに、hbox#browserの中・コンテンツ領域の前後にボーダーのためのボックスとしてvbox#browser-border-startとvbox#browser-border-endを追加して、さらにそれらを
layer="true"
と指定する。- これで、toolboxとvbox#browser-border-startとvbox#browser-border-endとhbox#browser-bottomboxとコンテンツ領域のそれぞれが、重なり合わない描画領域を持つ状態になる。
- よって、描画周りのパフォーマンス低下は起こらない。
Alice0775さんが「やっつけ仕事」と評した事について、僕は最初は単に「空divのようなボックスの使い方」についてだけ言っていたのだと思ったんだけど、このような背景事情を知って、それではなくて「インテリジェントな判断をするためのロジックを組むという真っ当なやり方をせずに、人力で解決する」というアドホックな対応の事をこそ「やっつけ仕事」と評されていたのだと、やっと悟ったわけです。
という風にlayer="true"
が導入された背景を調べた事によって、アドオン作者も「Firefoxのウィンドウ内にXUL要素を追加すると、場合によっては最上位のvboxの描画領域が広がる事でパフォーマンスが低下してしまう」ということを意識しておかないといけないのだなあ、ということが分かった。ああ、もう、実に厄介な話だなあ……
wikieditish message: Ready to edit this entry.