Upload
nicholas-zakas
View
12.594
Download
2
Tags:
Embed Size (px)
DESCRIPTION
E
Citation preview
Timers, Power Consumption, and Performance
flickr.com/photos/barbourians/6662357209/
Nicholas C. ZakasChief Architect, WellFurnished
New
@slicknet(Complaints:@souders)
flickr.com/photos/jepoirrier/954701212/
UI Thread
Update UI Execute JavaScript
flickr.com/photos/55733754@N00/3325000738/
<button id="btn" style="font-size: 30px; padding: 0.5em 1em">Click Me</button>
<script>
window.onload = function(){
document.getElementById("btn").onclick = function(){
//do something
};
};
</script>
Before ClickUI Thread
UI Queuetime
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclick
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclickDraw down state
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclick
When ClickedUI Thread
UI Queuetime
Update UI Update UIonclick
Draw up state
No UI updates while JavaScript is executing
JavaScript May Cause UI Update<button id="btn" style="font-size: 30px; padding: 0.5em
1em">Click Me</button>
<script>
window.onload = function(){
document.getElementById("btn").onclick = function(){
var div = document.createElement("div");
div.className = "tip";
div.innerHTML = "You clicked me!";
document.body.appendChild(div);
};
};
</script>
Each UI update applies
ALL CHANGESsince the last UI update
I gonna make a
namination!!
flickr.com/photos/oakleyoriginals/3065393607/
function naminate(element){
// start here
element.style.left = "10px";
// move to here
element.style.left = "30px";
// then to here
element.style.left = "50px";
// finally to here
element.style.left = "70px";
}
Why you no work???
flickr.com/photos/tudor/318123668/
function namimate(element){
// start here
element.style.left = "10px";
// move to here
element.style.left = "30px";
// then to here
element.style.left = "50px";
// finally to here
element.style.left = "70px";
}
Last state wins
setTimeout()
var tId = setTimeout(function(){
// do something
}, 1500);
// optional
clearTimeout(tId)
Code to execute
Delay in milliseconds
setTimeout()DOES NOT SAY
“Run this code after this delay”
setTimeout()DOES SAY
“Add this code to the queue after this delay”
<button id="btn" style="font-size: 30px; padding: 0.5em 1em">Click Me</button>
<script>
window.onload = function(){
document.getElementById("btn").onclick = function(){
setTimeout(function() {
//do something
}, 25);
};
};
</script>
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclick
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclickDraw down state
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclick
When ClickedUI Thread
UI Queuetime
Update UI Update UI
Draw up state
onclick
After 25msUI Thread
UI Queuetime
Update UI Update UIonclick
JavaScript
Added to back of queue
FutureUI Thread
UI Queuetime
Update UI Update UIonclick JavaScript
FutureUI Thread
UI Queuetime
Update UI Update UIonclick JavaScript
Update UI
If the JavaScript changes the UI, it triggers another
update
setTimeout() sends your code into the future
setTimeout(function(){
element.style.left = "10px";
}, 50);
setTimeout(function(){
element.style.left = "30px";
}, 100);
setTimeout(function(){
element.style.left = "50px";
}, 150);
setTimeout(function(){
element.style.left = "70px";
}, 200);
(function(){
var delay = 100;
function moveTheThing(){
// actually move the thing
setTimeout(moveTheThing, delay);
}
setTimeout(moveTheThing, delay);
}());
Animation Loop
(function(){
var msg = "Some reasonably long text that keeps scrolling.",
len = 25,
pos = 0,
padding = msg.replace(/./g, " ").substr(0,len)
finalMsg = padding + msg,
delay = 100;
function updateText(){
var curMsg = finalMsg.substr(pos++, len);
window.status = curMsg;
if (pos == finalMsg.length){
pos = 0;
}
setTimeout(updateText, delay);
}
setTimeout(updateText, delay);
}());
And More!
setTimout() all the things!!!
Problems
15.6
The default system-wide timer resolution in Windows is 15.6 ms, which means that every 15.6 ms the operating system receives a clock interrupt from the system timer hardware.
-Timers, Timer Resolution, and Development of Efficient Code (Microsoft)
var tId = setTimeout(function(){
// do something
}, 10);
What does it mean?
http://ejohn.org/blog/accuracy-of-javascript-time/
60
(function(){
var delay = 17;
function moveTheThing(){
// actually move the thing
setTimeout(moveTheThing, delay);
}
setTimeout(moveTheThing, delay);
}());
Animation Loop
Pretty please?!?!
http://ejohn.org/blog/analyzing-timer-performance/
Jumpy animationsInaccurate benchmarks
1ms all the timers!!!
http://www.belshe.com/2010/06/04/chrome-cranking-up-the-clock/
timeBeginPeriod()
timeBeginPeriod(1)
setTimout() all the things!!!
flickr.com/photos/antonfomkin/3046849320/
Modern CPUs are narcoleptic
ActiveC0
C1C2
C3
x86 CPU States
Low Power
HaltStop-Clock
SleepDeep Sleep
Enhanced Deep SleepDeep Power Down
C4C5C6
http://software.intel.com/en-us/articles/cpu-power-utilization-on-intel-architectures/
CPUs go to sleep when idle
The default timer resolution on Windows 7 is 15.6 milliseconds (ms). Some applications reduce this to 1 ms, which reduces the battery run time on mobile systems by as much as 25 percent.
-Timers, Timer Resolution, and Development of Efficient Code (Microsoft)
Laptops!
Plugged In 4ms 4ms 4ms 4ms 4ms
Battery 4ms 15.6ms 4ms 15.6ms 4ms
Background 1s 1s 4ms 1s* 4ms
* Internet Explorer 10
Web Timer Resolution Today
Battery 4ms 10ms 10ms 10ms 4ms
Background Tab - 10ms 10ms 10ms 1s
Web Timer Resolution Today
Background App - * * * 1s
* “Catches up” when switched back
Experiment• Hard shutdown and restart so
no other apps are running• Turn off brightness auto-adjust• Turn off screen locking• Leave WiFi/Mobile on• Load test page in browser• Profit!
Experiment• Test single timer at different
intervals:• 1000ms – 10ms
Low Frequency >= 1000ms
High Frequency < 1000ms
Time For 10% Power UseBy Frequency
Minutes 52-56 42-48 62-65
Timer frequency doesn’t matter
http://googlecode.blogspot.com/2009/07/gmail-for-mobile-html5-series-using.html
Experiment• Test single timer at different
intervals:• 1000ms – 10ms
• Test multiple timers at different intervals• 1000ms – 10ms x 10
Time For 10% Power UseBy Count
Minutes 52-56 42-48 62-65
(same)
Number of timers doesn’t matter
Number of timers does matter(accuracy)
http://ejohn.org/apps/timers
http://ejohn.org/apps/timers
http://ejohn.org/apps/timers
Flooding the QueueUI Thread
UI Queuetime
timer
timer
timer
Too many timers affects rendering
Elsewhere…
http://www.w3.org/TR/css3-animations/
Optimized animations using CSS
div {
animation-name: diagonal-slide;
animation-duration: 5s;
animation-iteration-count: 10;
}
@keyframes diagonal-slide {
from {
left: 0;
top: 0;
}
to {
left: 100px;
top: 100px;
}
}
Hey browser! I’m animating!
var tId = setTimeout(function(){
// do something
}, 1500);
Hey browser!
I want to do something
later
Could be animation. Could be polling.
Don’t sweat it.
http://www.w3.org/2010/webperf/
http://www.w3.org/TR/animation-timing/
moz webkit
var rId = requestAnimationFrame(function(time){
// do something
});
// optional
clearAnimationFrame(rId)
Code to execute
Time when the paint will happen
(function(){
function moveTheThing(){
// actually move the thing
requestAnimationFrame(moveTheThing);
}
requestAnimationFrame(moveTheThing);
}());
New Animation Loop
Hey browser! I’m animating!
(function(){
var element = document.getElementById("box");
function moveTheThing(){
element.style.left = (element.offsetLeft + 5) + "px";
requestAnimationFrame(moveTheThing);
}
requestAnimationFrame(moveTheThing);
}());
New Animation Loop
(function(){
var element = document.getElementById("box"),
start = Date.now();
function moveTheThing(time){
var since = (time || Date.now()) – start;
element.style.left = (element.offsetLeft + since)+ "px";
requestAnimationFrame(moveTheThing);
}
requestAnimationFrame(moveTheThing);
}());
New Animation Loop
<button id="btn" style="font-size: 30px; padding: 0.5em 1em">Click Me</button>
<script>
window.onload = function(){
document.getElementById("btn").onclick = function(){
requestAnimationFrame(function() {
//do something
});
};
};
</script>
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclick
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclickDraw down state
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclick
Call to requestAnimationFrame()UI Thread
UI Queuetime
Update UI
Update UI
onclick
Changes
Anim Frame
When ClickedUI Thread
UI Queuetime
Update UI Update UI
Draw up state
onclick
Changes
Anim Frame
Before Next FrameUI Thread
UI Queuetime
Update UI Update UIonclick
Anim Frame
Changes
Naminate!UI Thread
UI Queuetime
Update UI Update UIonclick Changes Anim Frame
Draw whatever changes are necessary
[requestAnimationFrame()’s framerate is] capped at 1000/(16 + N) fps, where N is the number of ms it takes your callback to execute. If your callback takes 1000ms to execute, then it's capped at under 1fps. If your callback takes 1ms to execute, you get about 60fps.
-Boris Zbarsky (Mozilla) via Paul Irish (Google)
Animate all the things!!!…with CSS and requestAnimationFrame
What about other things?
https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/setImmediate/Overview.html
var iId = setImmediate(function(){
// do something
});
// optional
clearImmediate(iId)
Code to execute
msSetImmediate()msClearImmediate()
<button id="btn" style="font-size: 30px; padding: 0.5em 1em">Click Me</button>
<script>
window.onload = function(){
document.getElementById("btn").onclick = function(){
setImmediate(function() {
//do something
});
};
};
</script>
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclick
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclickDraw down state
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclick
Call to setImmediate()UI Thread
UI Queuetime
Update UI
Update UI
onclick
ChangesAlways added after the last UI update in
the queue
When ClickedUI Thread
UI Queuetime
Update UI Update UI
Draw up state
onclick
Changes
Immediately!UI Thread
UI Queuetime
Update UI Update UIonclick Changes
https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/setImmediate/Overview.html
ON HOLD!
http://www.w3.org/TR/workers/
//in page
var worker = new Worker("process.js");
worker.onmessage = function(event){
useData(event.data);
};
worker.postMessage(values);
//in process.js
self.onmessage = function(event){
var items = event.data;
for (var i=0,len=items.length; i < len; i++){
process(items[i]);
}
self.postMessage(items);
};
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclick
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclickDraw down state
When ClickedUI Thread
UI Queuetime
Update UI
Update UI
onclick
Create Web WorkerUI Thread
UI Queuetime
Update UI
Update UI
onclick
Creates a background
thread/process/etc.
postMessage()UI Thread
UI Queuetime
Update UI Update UIonclick
process
Worker CompleteUI Thread
UI Queuetime
Update UI Update UIonclick
onmessage
FutureUI Thread
UI Queuetime
Update UI Update UIonclick onmessage
Recommendations
• Use as few as necessary• If multiple are necessary, use a single timer that can
accommodate allTimers
• Use CSS transitions and animations first• If not possible, use requestAnimationFrame()Animation
• Use web workers for efficient data processing• If no other options, use timers (see first point)Other
EtceteraMy company: • wellfurnished.com
My blog: • nczonline.net
Twitter • @slicknet
These Slides: • slideshare.net/nzakas