22. How Long Is Too Long?
“0.1 second [100ms] is about the limit for
having the user feel that the system is reacting
instantaneously, meaning that no special
feedback is necessary except to display the
result.”
- Jakob Nielsen
23. Translation:
No single JavaScript job should
execute for more than 100ms to
ensure a responsive UI
28. JavaScript Timers
• Created using setTimeout()
• Schedules a new JavaScript execution job for
some time in the future
• When the delay is up, the job is added to the
UI queue
– Note: This does not guarantee execution
after the delay, just that the job is added
to the UI queue and will be executed when
appropriate
29. JavaScript Timers
• For complex processing, split up into timed
functionality
• Use timers to delay some processing for later
30. function timedProcessArray(items, process, callback){
//create a clone of the original
var todo = items.concat();
setTimeout(function(){
var start = +new Date();
do {
process(todo.shift());
} while (todo.length > 0 &&
(+new Date() - start < 50));
if (todo.length > 0){
setTimeout(arguments.callee, 25);
} else {
callback(items);
}
}, 25);
}
41. Web Workers
• Asynchronous JavaScript execution
• Execution happens in a separate process
– Not on the UI thread = no UI delays
• Data-driven API
– Data is serialized when sending data into
or out of Worker
– No access to DOM, BOM
– Completely separate execution
environment
42. //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);
};
60. The Cost of Customization
• Spriting is difficult
– Hard to know which images will be on the
page together
• Limited image caching
– With content constantly changing, getting
images into cache doesn't help much
• A lot more JavaScript/CSS
– And very different, depending on how the
user has customized the page
61. Areas of Focus
• Time to interactivity
• Ajax Responsiveness
flickr.com/photos/hape_gera/2123257808/
62. The time to interactivity is the
time between the initial page
request and when the user can
complete an action
63. Time to Interactivity
• For most pages, happens between
DOMContentLoaded and onload
– Can actually happen earlier
• Links work, forms can be submitted even while
the page is loading
– As long as JavaScript isn't running
• Difficult to measure
64. Net tab reveals some information
Where DOMContentLoaded and onload occur
65. YSlow reports onload time
Useful, but doesn't really determine time to interactivity
67. Simple User Actions
• Clicking a headline to read the story
• Performing a search
• Clicking on a favorite
Wait a second!
You don't need JavaScript
for any of that!
flickr.com/photos/marcoarment/2035853550/
75. flickr.com/photos/kartik_m/2724121901/
Results
• Page would fully render, but be frozen
– User can't interact while JavaScript is being
fetched/parsed/executed
• Delayed onload to after 5s on fast connection
• Time to interactivity tied to onload
• Experience was especially bad over slower
connections
– Page was unresponsive for 30s or more
83. flickr.com/photos/nateandmiranda/2625399653/
Results
• Page is interactive as
soon as each section
is rendered
• Reduced onload time
to ~2.5s on fast
connections
• Slow connection
experience vastly
improved
84. JavaScript Loads
• Small amount on page load
• Larger amount loaded in non-blocking manner
– Everything necessary for core JavaScript
interactivity
• Ajax responses can specify more JavaScript is
needed to handle the response
– True, on-demand loading
85. Areas of Focus
• Time to interactivity
• Ajax Responsiveness
flickr.com/photos/hape_gera/2123257808/
86. The biggest area of concern regarding Ajax
performance was around the apps. For our very
first test, it sometimes took as long as 7 seconds
to load a single app.
87. start stop
What exactly is taking 7 seconds?
The measurement itself was a huge black box – before doing anything,
we had to figure out exactly what was happening in that time
88. roundtrip
start stop
Roundtrip Time
The first step is the amount of time between when the browser sends
the request and the time it receives the response
89. roundtrip parse
start stop
Parse Time
Next, the JSON response returned from the server has to be parsed
90. roundtrip parse download
start stop
JavaScript/CSS Download Time
Each response can indicate it needs more JavaScript/CSS before the
content can be used
91. roundtrip parse download render
start stop
Render Time
The amount of time it takes to actually change the display via innerHTML
94. The right-side ads were a roundtrip issue
The server-side ad call took extra time plus the ad markup represented
50-60% of the returned markup
95. “Fixing” the ad
Entire right column now renders in an iframe. This defers the ad call
until after the app has been loaded in the browser, saving both
server time for app rendering and bytes in the response.
100. The larger the JSON string, the
longer it took to parse
Keep in mind there was no native browser JSON parsing when we
began testing the new page
The regular expression validation in the YUI JSON utility (based on
json2.js) could take up to 40% of the parse time
101. Shrinking the size of the HTML by
deferring the ad helped
But we still wanted to see if we could eek out better gains
102. [{
"msg": "Hello world!",
"day": 6,
"found": true,
}]
=====
<div class="foo"><a href="http://www.yahoo.com">Yahoo!
</a></div>
We experimented with an alternate response format where meta
data was in JSON form but HTML was included afterward in plain
text
105. On-demand JavaScript/CSS
downloading hurt app loading
time
Intended to decrease page load time, and did – but left us with this
side effect
106. Waiting until the user takes
an action ensures paying the
cost of download
What if you knew which
apps the user was going to
use?
Solution: predictive fetch of
JavaScript/CSS before you
need it
flickr.com/photos/mcgraths/3248483447/
107. After page load, we start to
download JavaScript/CSS for
the apps on the page
116. Avoid Slow Loading JavaScript
• Put scripts at the bottom
• Concatenate scripts into as few files as
possible
• Choose the right way to load your scripts
– Dynamically created scripts
– Deferred scripts
– Asynchronous scripts
117. Avoid Slow JavaScript
• Don't allow JavaScript to execute for more
than 50ms
• Break up long JavaScript processes using:
– Timers
– Web Workers
118. Lessons Learned
• Time to interactivity is a big deal
• Progressive enhancement creates a better
experience
– Allows for delayed load of JavaScript
• Load as much JavaScript as possible in a non-
blocking manner
• Ajax performance is a macro measurement
– Get more insight by looking at the parts
119. Achievements
• Reduced time to onload from ~5s to ~2.5s
– Actually better than previous version
• Very short time to interactivity
• Reduced time to open apps from ~7s to ~2s
• Maintained perception of speed from previous
version
flickr.com/photos/ficken/1813744832/