Upload
futomi-hatano
View
6.464
Download
1
Embed Size (px)
Citation preview
もくじ
• 組込機器とブラウザー
• 組込機器ブラウザーの問題
• パフォーマンスの定義
• ページのロード
• ペイント領域とGPUメモリー
• 画像のロード
• ビデオのロード
• メモリー消費
• prototype
• DOMアクセス
• まとめ
SBC (Single Board Computer)
Raspberry Pi B+ BeagleBone Black ODROID-U3 ODROID-C1
Cubieboard 1/2 Marsboard RK3066 Radxa Rock Lite
HummingBoard i1/i2
Banana Pi KDDI Open Web Board
貧弱なCPUと少ないメモリ
SONY Xperia Z3
QualcommSnapdragon 801CPU: 4 Core (2.5GHz)RAM: 3GB
Raspberry Pi B+
BroadcomBCM2835CPU: 1 Core (700MHz)RAM: 512MB
Cubieboard 2
AllwinnerA20CPU: 2 Core (1GHz)RAM: 1GB
HummingBoard i1
Freescalei.MX6 SoloCPU: 1 Core (1GHz)RAM: 512GB
Alcatel One Touch Fire
QualcommSnapdragon MSM7227ACPU: 1 Core (1GHz)RAM: 256MB
近年のスマートフォンは超贅沢品
バージョンが固定
• なかなかブラウザーは更新されない
• 機器のライフサイクルが長い
• 古いバージョンが長期間残り続ける
• いつか勝手に解決するとは思ってはいけない...
http://www.bbc.com/news/technology-20957218
貧弱なCPUと少ないメモリー
• 処理時間オーバー• スマートフォンではサクッと終わる処理がなかなか終わらない
• アルゴリズムを考え直すか、分割して処理する必要がある
• メモリーリーク• スマートフォンでは気にならなかったメモリーリークがすぐに顕在化
• JSによるメモリーのお漏らしは厳重にチェックする必要がある
• ブラウザーのバグが顕著に出る• 組込機器はCPUが貧弱でメモリが少ないため、PCやスマートフォンでは顕在化しない問題が起こる
パフォーマンスとは
• 速く• 起動を速く
• 処理を速く
• アニメーションを滑らかに
• 少なく• メモリ消費を少なく
• CPU処理を少なく
• 長く• 安定動作を長く
すべてをかなえてくれる魔法の杖は...
パフォーマンスとは
• 速く• 起動を速く
• 処理を速く
• アニメーションを滑らかに
• 少なく• メモリ消費を少なく
• CPU処理を少なく
• 長く• 安定動作を長く
すべてをかなえてくれる魔法の杖は...
ありません!!!
パフォーマンスとは
• 速く• 起動を速く
• 処理を速く
• アニメーションを滑らかに
• 少なく• メモリ消費を少なく
• CPU処理を少なく
• 長く• 安定動作を長く
すべてをかなえてくれる魔法の杖は...
ありません!!!
何を捨てるのか、何を諦めるのか、を決めるのも重要
しかし、ちょっとした配慮でパフォーマンスを改善
ネットワーク処理は高コスト
• ダウンロードサイズとファイル数は少ないほど良い
• HTML/CSS/JavaScriptのMinify
• 極端に言えば、すべてHTMLにインラインに埋め込むのがベスト
• パフォーマンスと保守性のバランスを考えましょう
• 極度にMinifyツールを使うとJSが動作しない場合も
• CSS Spriteもほどほどに
ペイント領域とGPUメモリー
• 一般的に良く言われる手法
• ペイント領域は可能な限り小さく
• GPUアクセラレーションが有効な環境ならレイヤーを活用
• 動かすだけなら JavaScript のタイマーによる位置移動は避ける
• CSS Transitions と CSS Transforms の活用
• 組込デバイスだと
• GPUメモリーの上限が低い
• レイヤー活用は必要最小限に
• ペイント領域を可能な限り小さくするのは言うまでもない
コンテンツの移動
setTimeout() と left プロパティによるアニメーション
CSS Transitions と CSS Transforms の translateX() によるアニメーション
移動のたびにペイント処理が実行され不効率
レイヤー処理により移動がスムーズかつGPUメモリー消費が少ない
レイヤーの使いすぎに注意
• 組込機器のGPUメモリーはさほど多くない
• メインメモリーやGPUメモリーの速度もネックになる
• 特にフルHDなど広い解像度を扱うコンテンツでは要注意
• 使いすぎると返って不効率
値のリアルタイム更新
<p>経過時間:<span id="t">0</span>ミリ秒。</p>
var el = document.querySelector("#t");(function countUp(now) {
el.textContent = Math.round(now);window.requestAnimationFrame(countUp);
})();
数値のみを書き換えているのに、行全体が再ペイント
JS
値のリアルタイム更新
<p>経過時間:<span id="t">0</span>ミリ秒。</p>
var el = document.querySelector("#t");(function countUp(now) {
el.textContent = Math.round(now);window.requestAnimationFrame(countUp);
})();
数値のみを書き換えているのに、行全体が再ペイント
JS
浮かせる/サイズを固定する
<p>経過時間:<span id="outer"><span id="t">0</span></span>ミリ秒。</p>
var el = document.querySelector("#t");(function countUp(now) {
el.textContent = Math.round(now);window.requestAnimationFrame(countUp);
})();
#outer {display: inline-block;width: 100px;height: 20px;position: relative;
}#t {
display: inline-block;width: 100px;position: absolute;text-align: right;
}
JS
CSS
表示と非表示の切替
<body><img id="logo" src="imgs/logo.png"> <footer>...</footer>
</body>
var el = document.getElementById("logo");var hidden = false;window.setInterval(function() {
hidden = !hidden;el.style.display =
hidden ? "none" : "block";}, 1000);
ロゴしか切り替えていないのにリフローの発生よりページ全体が再ペイントの対象に
実際に見た目にリフローがなくても、ブラウザーは再レンダリングを行おうとしてしまう。
JS
CSSで位置固定
#logo {position: absolute;
}
<body><img id="logo" src="imgs/logo.png"> <footer>...</footer>
</body>
var el = document.getElementById("logo");var hidden = false;window.setInterval(function() {
hidden = !hidden;el.style.display =
hidden ? "none" : "block";}, 1000);
JS
CSS
img要素のloadイベント
http://www.w3.org/TR/html5/embedded-content-0.html#the-img-element
HTML5仕様曰く:
If the download was successful and the user agent was able to determine the image's width and height, [...] fire a simple event named load at the img element.
ダウンロードが成功し、ユーザーエージェントが画像の幅と高さを判定できたら、[...] img要素で load という名前のシンプルなイベントを発出します。
loadイベントはレンダリング完了を表しているわけではない
組込機器では、loadイベントの発生と、実際にレンダリングが完了したタイミングの差が大きく出る
巨大な画像のロード直後の処理
• img要素のloadイベント発生直後に重い処理をするとペイント処理とかぶってしまいブラウザーが固まる場合がある
• ペイントが完了したというイベントは取れない
• 手を抜くなら、こうするしかない...
imgElement.onload = function() {window.setTimeout(function() {
// 何か次の処理}, 100);
};
JS
組込機器には大敵なビデオデータ
• 再生開始タイミングのパフォーマンスを気にするなら<video preload="auto">• たとえ再生されなくてもバッファリング分のメモリーを消費
• 複数のビデオを事前に用意するのは厳しい
• メモリーにやさしい方法を選ぶなら<video preload="none">• 再生開始のタイミングがかなり遅れる
• どうしても事前にビデオの寸法と尺を知りたいなら<video preload="metadata">
MP4の再生開始パフォーマンス
• ファイルの最後にメタ情報が格納されている• これによって再生開始が大幅に遅れる
• ブラウザーの挙動1. ファイルの先頭を読み取る
2. メタ情報がないと判定し、ファイルの末尾を読み取る
3. ファイルの先頭に戻ってバッファリング分のビデオデータをダウンロードする
ノコギリ型のメモリー消費
• ガベージコレクションは負荷が高いためアニメーションを妨げる
• 一般的にノコギリ型のメモリー消費は良くないと言われるが、それはデバイス環境とユースケース次第
• メモリーが少ない環境では、早めにガベージコレクションを発生させ、ピークを抑えるほうが良い場合もある
prototypeを使わない場合
var MyWallet = function(init_price) {this.price = init_price;this.earn = function(price) {
this.price += price;if(this.price > 1000) {
this.pay(this.price - 1000);}
};this.pay = function(price) {
this.price -= price;};this.look = function() {
return this.price;};
};
JS
prototypeを使った場合
var MyWallet = function(init_price) {this.price = init_price;
};MyWallet.prototype.earn = function(price) {
this.price += price;if(this.price > 1000) {
this.pay(this.price - 1000);}
};MyWallet.prototype.pay = function(price) {
this.price -= price;};MyWallet.prototype.look = function() {
return this.price;};
JS
メモリー消費に違いが出る(極端な例)
var list = [];for( var i=0; i<100000; i++ ) {
var w = new MyWallet(0);list.push(w);
}
prototypeを使わない場合 prototypeを使った場合
62MB 32MB
JS
• 流行りのライブラリーやプログラミング手法が良いとは限らない• メモリーが潤沢な環境を前提としていないかを考えるべき
• レガシーな手法も見直そう• メモリーが少ない時代に考えられた手法は今なお組込デバイスでは有効