kitak blog

Kみたいなエンジニアになりたいブログ

Chrome DevTools でコストの高い描画処理を探す流れ

先日、Chrome DevTools の「Enable paint flashing」を使う - kitak.blog で、Chrome DevTools の「Enable paint flashing」を使って不要な描画処理を検知する方法を紹介しました。

不要な描画処理は行わないほうがいいに決まっていますが、必要と思われる描画処理でも、描画のコストが高くアプリケーションのパフォーマンスを低下させるものがあります( ここでのコストは描画にかかる時間とします )。

コストの高い描画処理として、例えば、以下の様に「ドットのボーダーに囲まれたり」、「角丸だったり」、「影のついているもの」が、知られています(かなり極端な例ですけどね)。

f:id:kitak:20151103163121p:plain

この記事では、DevToolsのTimelineを使ってコストの高い描画処理を探す流れについて紹介します。
Timelineの細かい機能の説明は、最新号のWEB+DB Pressの特集に載っているので、そちらに譲ります。

WEB+DB PRESS Vol.89

WEB+DB PRESS Vol.89

コストの高い描画処理を探す方法も↑の特集に書いてあってアレなのですが、僕は普段こうやってるよ、ぐらいの内容を書こうと思います。

コストの高い描画処理を探すタイミングとしては、実装を一通り終えた後です。画面を触ってみて、違和感を感じたら、違和感を感じた操作の前後のイベントをTimelineで記録します(「Paint」のチェックボックスにチェックをつけるのを忘れないようにする)。 操作によって違和感を感じるということは、fpsの変動があるはずなので、以下のようなアクティビティのグラフをながめて、fpsがあるときからガクっと低下している(グラフが高くなっている)、かつ、緑色(Painting)が目立つフレームを探して範囲を絞ります(グラフに「ツマミ」のようなものがあるはずです)。

f:id:kitak:20151103181239p:plain

絞り込んだら、グラフの下の左ペイン「RECORDS」から「Paint」を探します。記録ボタンの右にある漏斗ボタンを押すとレコードを絞り込めるので「Paint」と入力して絞り込むと楽です。

Paintレコードを選択して、さらに下のペインの「Paint Profiler」タブを選択すると、描画コマンドの一覧、描画にかかった時間、描画した内容を確認できるので、後は各レコードの内容をみて、コストの高い描画処理を探すかんじです。

下は最初に示したコストの高い効果をつけた場合とつけていない場合それぞれのレコードです。影や角丸の効果の有り無しで描画時間が28~50ms違いました。レンダリングの1フレームの一部として考えるとかなり大きいです( 60fpsの場合1フレームは16.67ms、30fpsの場合1フレームは33.33ms )。

f:id:kitak:20151103190125p:plain

f:id:kitak:20151103190133p:plain

原因を特定したら、コストの高い描画をおこなわないようにデザインの変更ができるかどうかデザイナーと調整します。 また、違和感の原因は、JavaScriptスタイルシートの記述によって、コストの高い描画処理を複数フレームで連続的に行っていることにあるかもしれません。その場合は、Paintイベントの前のブラウザのUIやJavaScriptの処理によって発生したイベントを調べて、描画の回数を減らしたり、一回だけ描画がおこなわれるように改善します。

fpsの低下の原因はPainting以外のイベント( Loading, Scripting, Rendering )による可能性もあるので、全てのfpsの低下=描画によるもの、というわけではありません(相対的にPantingにコストがかかりがちにはなりますが)。例えば、JavaScriptで時間のかかる処理をおこなう関数を呼び出したり(Scriptingが増える)、まずいDOM操作をおこなって何度もリフロー・レイアウトを発生させたら(Renderingが増える)、1フレームにかかる時間は増えて、fpsは低下します。前者は「Profiles」で時間のかかっている関数を特定できますし、後者は「Timeline」のRenderingに関係するイベントに警告マークが表示されるのでそこから改善をおこなうことができます。

「かつての」コストの高い描画処理を探す方法

Chrome 46までは、「Rendering」タブに「Enable continuous page repainting」という機能があって、有効にすると画面全体の描画を繰り返し行い、描画にかかった時間の推移をリアルタイムで画面右上にモニタ表示してくれました。 その機能があった頃のコストの高い描画処理を探す方法として、機能を有効にしてモニタを見ながら画面を触って「お、なんかここらへんで描画に時間がかかっているぞ」と思ったら、Elementsタブで原因となっていそうな要素を非表示にしたり、スタイルのプロパティを外して、描画にかかる時間が減るか調べることでレンダリングの改善につなげる、というやり方がありました。

この方法の難点はElementsタブをつかって手当たり次第に探す感じが否めないことと、コストの高い描画処理が何なのか、Timelineと比較してぼんやりとしか分からないことです※。 また、繰り返し描画がおこなわれることでPCに負荷がかかります。実際、ファンの音がすさまじいことになっていました。

現在は先に述べたようにTimelineの機能でコストの高い描画処理を探すことが可能なので、Chrome 46で「Enable continuous page repainting」は削除されました( refs: Issue 515763 - chromium - Devtools UI: Add an elements toolbar - An open-source project to help move the web forward. - Google Project Hosting )。 DevToolsのTipsを検索すると、かつての方法が紹介されているかもしれませんが、現在は利用できないので注意が必要です。

※ Skia Debuggerというツールを使うと各描画コマンドでどれぐらい時間がかかったか調べることができますが、導入が面倒です。SkiaはChromeで使われているグラフィックスライブラリです。