+ All Categories
Home > Technology > Browser Computing Structure

Browser Computing Structure

Date post: 30-Jun-2015
Category:
Upload: sensui-shogo
View: 192 times
Download: 0 times
Share this document with a friend
Description:
2014/1/25に開催されたFrontrend in FukuokaのBrowser Computing Structureのセッションの資料です。
109
Browser Computing Structure Frontrend in Fukuoka @1000ch
Transcript
Page 1: Browser Computing Structure

Browser Computing Structure

Frontrend in Fukuoka @1000ch

Page 2: Browser Computing Structure

@1000ch

Page 3: Browser Computing Structure

Frontend Developer

Page 4: Browser Computing Structure

目次変化するWebとJavaScriptの役割

ブラウザが何をしているかを知る

ブラウザが遅くなる原因を知る

最適化アプローチ

Page 5: Browser Computing Structure

変化するWebとJavaScriptの役割

Page 6: Browser Computing Structure

• テキストベースのWebサイト

• コンテンツの更新は遷移が中心

• 装飾は<marquee>とか<blink>とか…

静的なWeb

Page 7: Browser Computing Structure

• 非同期通信によるコンテンツの更新(Googleマップ・Googleサジェスト等)

• JavaScriptがダイナミックなWebサイトの可能性をHTMLにもたらした

動的なWeb

Page 8: Browser Computing Structure

• HTML5やCSS3といった、技術の標準化と飛躍的な進化

• ブラウザで出来ることが増えた(WebGL・WebAudio・WebSocket…)

リッチなWeb

Page 9: Browser Computing Structure

JavaScriptなしに HTML5を語れない

Page 10: Browser Computing Structure

対応の難しさベンダーの数×OSのバージョン に比例して増加する実装リスク

Page 11: Browser Computing Structure

確か存在するコストマシンスペックに左右される上にモバイル端末だとなおさら差が顕著

Page 12: Browser Computing Structure

パフォーマンスが 犠牲になりがち

Page 13: Browser Computing Structure

Amazon100msの高速化

売上1%増加

Mozilla

Google

2200msの高速化

ダウンロード15.4%増加

400msの高速化

検索回数0.59%増加

Page 14: Browser Computing Structure

パフォーマンスは最も重要なUX指標パフォーマンスはWebサイトの品質である

かっこよくても遅いサイトにユーザーは満足しない

Page 15: Browser Computing Structure

ブラウザが何をしているかを知る

Page 16: Browser Computing Structure

データの要求とダウンロード URLの入力やページ遷移等

HTMLレンダーツリーのレイアウトとペイント

ユーザーアクションの応答クリックやスクロールのインタラクション

Page 17: Browser Computing Structure

ユーザーアクションの応答クリックやスクロールのインタラクション

データの要求とダウンロードURL

HTMLやCSSの解析と描画 レンダーツリーのレイアウトとペイント

Page 18: Browser Computing Structure

ユーザーアクションの応答 クリックやスクロールのインタラクション

データの要求とダウンロードURL

HTMLレンダーツリーのレイアウトとペイント

Page 19: Browser Computing Structure

ユーザーアクションの応答 クリックやスクロールのインタラクション

データの要求とダウンロード URLの入力やページ遷移等

HTMLやCSSの解析と描画 レンダーツリーのレイアウトとペイント

Page 20: Browser Computing Structure

データの要求とダウンロードURL

HTMLレンダーツリーのレイアウトとペイント

ユーザーアクションの応答クリックやスクロールのインタラクション

ページのロード開始から

表示されるまで

Page 21: Browser Computing Structure

データの要求とダウンロードURL

HTMLレンダーツリーのレイアウトとペイント

ユーザーアクションの応答クリックやスクロールのインタラクション

ページが表示されてから

次の遷移までずっと

Page 22: Browser Computing Structure

Render ComputeNetwork

パフォーマンスの3大要素

Page 23: Browser Computing Structure

Render ComputeNetwork

ページ表示までのイニシャルコスト

→ファーストインプレッション

Page 24: Browser Computing Structure

Render ComputeNetwork

スクロールの滑らかさやページ応答

→ユーザーの使い心地

Page 25: Browser Computing Structure

Chrome DevTools

ブラウザ、そして最強の開発者ツール

FirebugもいいけどやっぱChrome

Command + option + i

Page 26: Browser Computing Structure

Google Chrome Canary

Chromeの開発者向けビルド

DevToolの新機能をいち早く試せる

たまに不安定…

Page 27: Browser Computing Structure

DevTools > Network

Network

HTTPリクエストの数

リソースサイズのチェック

バッドリクエストがないかどうか

ネットワーク周りの最適化

Page 28: Browser Computing Structure

DevTools > Timeline

Render

FPSの値のチェックレイアウトやペイントのタイミング

イベントの発火やGCの実行形跡

ブラウザがどのような処理をしているか大体わかる

Page 29: Browser Computing Structure

DevTools > Profiles

Compute

JavaScriptの実行コスト

ヒープ領域に置かれるオブジェクト

Timelineより細かいメモリの状態

スクリプト周りの調査

Page 30: Browser Computing Structure

Compute

今日はComputingの話

Page 31: Browser Computing Structure

Keep 60FPS• FPS = Frames Per Second

• ブラウザは1秒間に60回リフレッシュする

• 60FPSを維持するには1フレームの処理を16.67ms

に収める (16.67ms=1000ms / 60FPs)

• 一般的に30FPS出ていれば滑らかである

Page 32: Browser Computing Structure

ブラウザの処理

Load Script Render Paint Load Script Render

Page 33: Browser Computing Structure

Load Script Render PaintRender Paint Load Script

ブラウザの処理

16.67ms

Page 34: Browser Computing Structure

Paint Paint

特に処理がないとき

16.67ms

Page 35: Browser Computing Structure

20FPSのサンプルhttp://codepen.io/paulirish/full/nkwKs

Page 36: Browser Computing Structure
Page 37: Browser Computing Structure

60FPSのサンプルhttp://codepen.io/1000ch/full/KbLHh

Page 38: Browser Computing Structure
Page 39: Browser Computing Structure

ブラウザが遅くなる原因を知る

Page 40: Browser Computing Structure

Case#1 重い処理時間がかかるとペイントも遅れる

Page 41: Browser Computing Structure

Scriptが忙しいと…

Load Script Render PaintRender Paint Load

16.67msに収まらない

Page 42: Browser Computing Structure
Page 43: Browser Computing Structure
Page 44: Browser Computing Structure
Page 45: Browser Computing Structure

Case#2 GCScriptの実行を止めてしまう

Page 46: Browser Computing Structure

Garbage Collection?• JavaScriptでは、メモリの割当と解放がJavaScriptのエンジンによって自動で行われる。その仕組みがGarbage

Collectionである

• 最近の高水準言語にほとんど備わっている

• いわばルンバのような存在 by @ahomu

Page 47: Browser Computing Structure

GC発生のタイミング• ブラウザによって一定の周期で実行される他、メモリが少なくなってきたり、不要なメモリが出現すると実行される

• JavaScriptでは実行のタイミングを直接コントロールする術はない

Page 48: Browser Computing Structure

Window

AB

D

CE

Page 49: Browser Computing Structure

Window

AB

D

CEGCの対象になる

Page 50: Browser Computing Structure

GCの間はScriptが止まる

Load Render PaintRender Paint GC Load

16.67msに収まらない

Script

Page 51: Browser Computing Structure
Page 52: Browser Computing Structure
Page 53: Browser Computing Structure
Page 54: Browser Computing Structure

Case#3 メモリリーク何かと悪影響を及ぼす

Page 55: Browser Computing Structure

メモリリーク• メモリ領域が圧迫されると必然的にブラウザの実行速度は低下する

• メモリの回収はページ遷移時か、Garbage Collectionの実行により行われる

• メモリリークの代表的な原因は…?

Page 56: Browser Computing Structure

Understand memory leakshttp://www.ibm.com/developerworks/web/library/wa-jsmemory/

Page 57: Browser Computing Structure

コンソール循環参照

クロージャタイマー

Page 58: Browser Computing Structure

コンソール循環参照

クロージャタイマー

Page 59: Browser Computing Structure

function Timer() { this.timerId = setInterval(function() { console.log('This is timer log.'); }, 1000); } !!!var timer = new Timer(); timer = null;

Page 60: Browser Computing Structure

function Timer() { this.timerId = setInterval(function() { console.log('This is timer log.'); }, 1000); } !!!var timer = new Timer(); timer = null;

呼び出し元を破棄しても

タイマーが実行され続ける

Page 61: Browser Computing Structure

function Timer() { this.timerId = setInterval(function() { console.log('This is timer log.'); }, 1000); this.stop = function() { clearInterval(this.timerId); }; } !!!var timer = new Timer(); timer.stop(); timer = null;

Page 62: Browser Computing Structure

function Timer() { this.timerId = setInterval(function() { console.log('This is timer log.'); }, 1000); this.stop = function() { clearInterval(this.timerId); }; } !!!var timer = new Timer(); timer.stop(); timer = null;

タイマーはちゃんと止めること!

Page 63: Browser Computing Structure

クロージャタイマー

コンソール循環参照

Page 64: Browser Computing Structure

function Closure() { var value = 1000; return function() { return value; }; }

Page 65: Browser Computing Structure

function Closure() { var value = 1000; return function() { return value; }; }

valueは関数から

参照され続けてしまう

Page 66: Browser Computing Structure

function Closure() { var value = 1000; return function() { var another = 2000; return another; }; }

Page 67: Browser Computing Structure

function Closure() { var value = 1000; return function() { var another = 2000; return another; }; }

valueは参照されなくなる

のでGCに回収される

Page 68: Browser Computing Structure

循環参照 コンソール

タイマー クロージャ

Page 69: Browser Computing Structure

var family = []; !var child = { age: 10 container: family }; !var parent = { child: child, container: family }; !family.push(child); family.push(parent);

Page 70: Browser Computing Structure

var grandparent = { child: parent, container: family }; !family.push(parent);

雪だるま式に増えるメモリ

Page 71: Browser Computing Structure

A

C B

Page 72: Browser Computing Structure

A

C B

参照が残ってしまいGCで回収されない

Page 73: Browser Computing Structure

A

C B

参照がなくなったので

メモリが開放される

Page 74: Browser Computing Structure

参照関係の整理を!一般的なフレームワークはこのような

イベントリスナのモデルに従っていることが多い

Page 75: Browser Computing Structure

コンソール循環参照

タイマー クロージャ

Page 76: Browser Computing Structure

var object = { foo: 1, bar: 2 }; console.log(object); object = null;

Page 77: Browser Computing Structure

var object = { foo: 1, bar: 2 }; console.log(object); object = null;

コンソールから参照され

GCから回収されない

Page 78: Browser Computing Structure

メモリとの仁義なき戦い• いくら最適化してもGCは自動で実行されてしまう。そのインパクトを如何に小さく出来るかが重要

• 特に気を使わなければいけないのはページ遷移をしない、かつ滑らかさが重要な場合(シューティングゲームとか)

• Scriptから発生するLoadやRenderも忘れない

Page 79: Browser Computing Structure

最適化アプローチ

Page 80: Browser Computing Structure

Profiles未開放のオブジェクトやメモリの使用状態

使い心地の悪さを見逃さない スクロールが引っかかる等

Timeline60FPS

Page 81: Browser Computing Structure

Profiles未開放のオブジェクトやメモリの使用状態

使い心地の悪さを見逃さないスクロールが引っかかる等

Timelineでネックを見つける 60FPSと30FPSのボーダーを目印に

Page 82: Browser Computing Structure

Profilesで詳しく解析する 未開放のオブジェクトやメモリの使用状態

使い心地の悪さを見逃さないスクロールが引っかかる等

Timeline60FPS

Page 83: Browser Computing Structure

Collect JavaScript CPU Profile

JavaScriptの実行にかかった時間を調べることが出来る

Page 84: Browser Computing Structure

Take Heap Snapshot現在のページで実行され、ヒープ領域に置かれた

JavaScriptのオブジェクトの数を調べることが出来る

Page 85: Browser Computing Structure

Record Heap Allocations

JavaScriptの実行とともに使用されるメモリの

割当と解放の状態を調べることが出来る

Page 86: Browser Computing Structure

JavaScriptの

高速化セオリーを知る

Page 87: Browser Computing Structure

ArrayのforEach()よりforでループ アニメーションにはrequestAnimationFrame() “use strict”;を使う try/catch(例外の捕捉)は重い parseInt()より加減演算でキャストする DOMの探索や操作は最小限に 短い関数のインライン化 eval()やwith()を使わない new Date()よりdate.now() 評価順の工夫 正規表現のキャッシュ 重い処理の非同期化(WebWorker) ArrayのforEach()よりforでループ  アニメーションにはrequestAnimationFrame() “use strict”;を使う try/catch(例外の捕捉)は重い parseInt()より加減演算でキャストする DOMの探索や操作は最小限に 短い関数のインライン化 eval()やwith()を使わない new Date()よりdate.now() 評価順の工夫 正規表現のキャッシュ 重い処理の非同期化(WebWorker) etc…

Page 88: Browser Computing Structure

JavaScript Gardenhttp://bonsaiden.github.io/JavaScript-Garden/ja/

Page 89: Browser Computing Structure

Don't Guess it, Test it!

- Paul Lewis

Page 90: Browser Computing Structure

jsPerfhttp://jsperf.com

Page 91: Browser Computing Structure

メモリリークのサンプルhttp://1000ch.net/memleak

Page 92: Browser Computing Structure

GCを避ける2つの手法

Page 93: Browser Computing Structure

オブジェクトプール使わなくなった既定の型のオブジェクトをプールし

その型のオブジェクトを再利用する

Page 94: Browser Computing Structure

Object Pool

Object

Object

生成したオブジェクトを

再利用することで

メモリの再割当を抑える

Page 95: Browser Computing Structure

Object Poolshttp://beej.us/blog/data/object-pool/

Page 96: Browser Computing Structure

スタティックメモリ使用する全てのオブジェクトをあらかじめ初期化して

使う場合にはそのオブジェクト群から借用する

Page 97: Browser Computing Structure

Object Pool

Object Object

Object Object

オブジェクトの生成回数を

減らすアプローチ

Page 98: Browser Computing Structure

【番外編】V8エンジンの

最適化を阻害しない

Page 99: Browser Computing Structure

Design Elementshttps://developers.google.com/v8/design

Page 100: Browser Computing Structure

Fast Property AccessJITコンパイル時に静的なクラスを作成し JSのコードを動的に参照するのではなく

生成されたクラス(hidden class)を高速に参照する

Page 101: Browser Computing Structure

Dynamic Machine Code Generation

1度実行したコードをマシンコードにコンパイルし 次回以降はキャッシュしたものを実行する

(中間バイトコードもインタープリタも使わない)

Page 102: Browser Computing Structure

クラスの定義があったら…

function Point(x, y) { this.x = x; this.y = y; }

JITコンパイル時にクラスの静的な実態を生成する

function Point(x, y) { this.x = x; this.y = y; }Hidden Class

var point = new Point();次からコンパイル済の

クラスを参照するので高速

Page 103: Browser Computing Structure

function Point(x, y) { this.x = x; this.y = y; } Point.name = 'Name';

Hidden Classを

再度生成してしまうHidden Class

定義を途中で変更すると…Point.name = 'Name';

ブラウザが実行時に最適化したコードを

なるべく変更しないようにする!

Page 104: Browser Computing Structure

まとめ

Page 105: Browser Computing Structure

パフォーマンスは必須

環境の多岐化も考慮する

Page 106: Browser Computing Structure

ブラウザの気持ちを知ることが

最適化への第一歩

Page 107: Browser Computing Structure

銀の弾丸は存在しない

全ては最適化の積み重ね

Page 108: Browser Computing Structure

Thank you!@1000ch

http://github.com/1000ch

http://1000ch.net

Page 109: Browser Computing Structure

Photo Credits• http://www.flickr.com/photos/66331098@N03/6041212579

• http://www.flickr.com/photos/danichro/7284517300

• http://www.flickr.com/photos/articnomad/16153058/

• http://www.flickr.com/photos/sfgirlbybay/2739327181/

• http://www.flickr.com/photos/30859306@N00/3331140550

• http://www.flickr.com/photos/45540741@N06/7365063522/

• http://www.flickr.com/photos/chrissinjo/5368405044

• http://www.flickr.com/photos/cloudy-day/5319042359

• http://www.flickr.com/photos/57490760@N04/7218896186


Recommended