understanding page load / ziling zhao (google)
Post on 06-Jan-2017
615 Views
Preview:
TRANSCRIPT
Understanding Page LoadZiling Zhao - Engineer at Google
What I will talk about
● Page Load Latency○ Time leading from a click to a usable website
● Traditional and dynamic page loads● A few tips and things to avoid● How the browser works● Tools that can help you explore site performance● Most of this was picked up while optimizing YouTube
Who am I?
● Software Engineer on YouTube○ Working on Desktop and Mobile Web
● Been at Google for 4 ½ years● Prior to Google, I worked at Cisco Systems● Graduated from the University of Washington● Specialize in web performance
Why care about page load speed?
● Customers are from different parts of the world● People have slow connections and slow CPUs● Malware, antivirus, memory pressure, etc.● Mobile users have resource constraints● People want smooth app-like experiences● Slow websites turn users away!
Two types of page loads.
TraditionalPage Load
First page load, as well as any full page load.
Measured starting from when the request is sent for the page.
Ends when the important parts of the requested page is viewable and ready.
"Cold"
DynamicPage Load
AJAX driven site navigation.
Starts when an action (typically user driven) triggers a navigation to the next page. This should be before the actual request.
Ends when the important parts of the requested page is viewable and ready.
"Warm"
Monitor your performance.
Response-Time Rules of Thumb
0.1s - Instantaneous
1s - Seamless
10s - Attention threshold
Jakob Nielsenhttp://www.nngroup.com/articles/response-times-3-important-limits/
Network dominatesload time.
Examining at a web page load.
Chrome DevTools - Network Panel
WebPagetest
WebPagetest - highload.co
http://www.webpagetest.org
Page Load Basics
A CDN serves content closer to your customers.
Low latency. Cookieless, smaller response/request size.
Extra DNS lookup and TCP connection for separate domain
● Use a CDN
● Cache static content
● Connection keep-alive
● Use gzip transfers
● Compress Images
● Minify your javascript/css
● Minimize first byte time
● Reduce number of downloads
List static assets not being served off of a CDN
Page Load Basics
Avoid the roundtrip.
● Use a CDN
● Cache static content
● Connection keep-alive
● Use gzip transfers
● Compress Images
● Minify your javascript/css
● Minimize first byte time
● Reduce number of downloads
Check for cache headers
These images never change● Set a max-age or expires header
ETag still incurs a round trip● Browser needs to ask the server
if content has changed○ RTT 289ms!
Page Load Basics
Do your handshake once.
Reduce your transfer size.
● Use a CDN
● Cache static content
● Connection keep-alive
● Use gzip transfers
● Compress Images
● Minify your javascript/css
● Minimize first byte time
● Reduce number of downloads
Keep connections open and gzip
Page Load Basics● Use a CDN
● Cache static content
● Connection keep-alive
● Use gzip transfers
● Compress Images
● Minify your javascript/css
● Minimize first byte time
● Reduce number of downloads
Image size reduction
Compress Images
Original Image● JPEG Quality 94● Resolution: 1500 x 1001 pixels● File Size: 795KB
Compressed Image● JPEG Quality 70● Resolution: 1024 x 683 pixels● File Size: 152.5KB
WebP● WebP Quality 70● Resolution: 1024 x 683 pixels● File Size: 136.2KB
Page Load Basics
Use something like uglify/closure compiler/YUICompressor.
● Use a CDN
● Cache static content
● Connection keep-alive
● Use gzip transfers
● Compress Images
● Minify your javascript/css
● Minimize first byte time
● Reduce number of downloads
Minify your large javascript files
Probably don't need another version.
Page Load Basics
Chunk your responses if you have RPCs or heavy server processing.
Serve static content early.
● Use a CDN
● Cache static content
● Connection keep-alive
● Use gzip transfers
● Compress Images
● Minify your javascript/css
● Minimize first byte time
● Reduce number of downloads
Transfer-Encoding: Chunked
Page Load Basics● Use a CDN
● Cache static content
● Connection keep-alive
● Use gzip transfers
● Compress Images
● Minify your javascript/css
● Minimize first byte time
● Reduce number of resources
Reduce the number of resources
● This used to be simple○ HTTP/2 makes things complicated
● Under HTTP1○ 6~ concurrent connections per server for all tabs
■ Reduce the total number of resources needed○ Sprite your assets, reduce the number of small images○ Reduce CSS/JS downloads
● But can you serve SPDY/HTTP2?
SPDY/HTTP2 and QUIC
● Connection multiplexing○ Allows multiple requests over one socket
■ Only creates one connection per server■ Reduces the need to sprite your images or shard static
domains● Header compression● Faster SSL handshake● Serverpush resources before client asks for them● QUIC is a UDP-based transport
○ currently used for YouTube video serving
Dev Tools
After the first byte
The browser starts getting busy
● The browser must take the CSS and HTML and join them together○ HTML is parsed into a DOM (Document Object Model)○ CSS is parsed into an CSSOM
● Styles are applied/recalculated● The page is layed out and painted
○ Elements are positioned and pixels are drawn● Resources linked to in your page must be
downloaded● Javascript must be executed
Rendering is (mostly)
single threaded.
The render-thread has a lot to do
● A single render thread (per tab) handles a lot of important tasks○ Parsing○ Styling○ Layout○ Painting○ Javascript○ Event handling, etc.
● Network operations are on a separate process○ One shared network manager across tabs
Page load walkthrough.
After the first byte
● Browser parses HTML to construct the DOM (Document Object Model)
● CSS is parsed to form the CSSOM
● DOM + CSSOM = Render Tree○ This is how the
visible elements will be displayed.
● Render Tree is painted
HTML
DOM Tree
After the first byte
● Browser parses HTML to construct the DOM (Document Object Model)
● CSS is parsed to form the CSSOM
● DOM + CSSOM = Render Tree○ This is how the
visible elements will be displayed.
● Render Tree is painted
HTML
DOM Tree
CSS
CSSOM
Where does the CSS come from?
The browser has to read the <link> before CSS downloads.
After the first byte
● Browser parses HTML to construct the DOM (Document Object Model)
● CSS is parsed to form the CSSOM
● DOM + CSSOM = Render Tree○ This is how the
visible elements will be displayed.
● Render Tree is painted
HTML
DOM Tree
CSS
CSSOM HTML Parser
Network Manager
After the first byte
● Browser parses HTML to construct the DOM (Document Object Model)
● CSS is parsed to form the CSSOM
● DOM + CSSOM = Render Tree○ This is how the
visible elements will be displayed.
● Render Tree is painted
HTML
DOM Tree
CSS
CSSOM HTML Parser
Network Manager
Render Tree
Javascript is blocking.
Parser + Javascript on the same thread
● Javascript can read and write to the DOM○ The parser is cautious and will pause until javascript is
downloaded and run● The browser can paint the partial page while blocked
○ Being blocked in <head> means there is nothing to paint● General advice:
○ Have stylesheets in the head and send them early○ Put javascript at the bottom of your page to avoid
blocking the parser
Be careful with JS in <head>
● Stylesheets block painting● Putting inline <script> right after <link rel="
stylesheet"> will block the parser until stylesheet is downloaded○ Browser assumes js will read stylesheet
● If you must put scripts in the head.○ Keep it small, maybe inline○ It may be better to put it before your external CSS
■ Otherwise it will block until CSS is done downloading before executing
After the first byte
● Browser parses HTML to construct the DOM (Document Object Model)
● CSS is parsed to form the CSSOM
● DOM + CSSOM = Render Tree○ This is how the
visible elements will be displayed.
● Render Tree is painted
HTML
DOM Tree
CSS
CSSOM HTML Parser
Network Manager
Render Tree
Paint
Display
The Preloader
The Preloader
● Also known as: Speculative/look-ahead pre-parser● Making your site run-faster since 2008● 20%~ page load improvement● While the parser is blocked, another parser flies
ahead and finds all downloadable resources○ Stylesheets, scripts, images, html imports
Network Priorities - Chrome
● Network requests are executed in priority order○ Layout blocking network requests are HIGHEST/MEDIUM
priority (CSS/HTML)○ Layout blocking mode allows one low priority request at
a time (this may change).○ Scripts are LOW○ Async XHR's are LOW priority○ Images are LOWEST or IDLE priority
Pre-loader - Chunked Transfer
● Chunked encoding + scripts at the end○ Pre-loader can't see it until the chunk is sent
■ Your script download will be after other resources○ Can use async and defer to put scripts earlier
■ async - Doesn't block parser for download, will pause to execute● This will put it in LOWEST priority
■ defer - Doesn't block for download, execute after parser is completed (keeps order)
Scripts at footer can load earlier than images
chrome://net-internals#events
Warning: JS module loaders
● Cannot take advantage of the pre-loader● Script loaders will only load scripts after:
○ Your bootstrap script downloads and is executed○ Bootstrap script execution will be blocked by any
previous CSS or javascript● Same applies to CSS loaders
○ Especially damaging since CSS is typically fetched at MEDIUM priorities
Dynamic Page Transitions
Dynamic page transitions
● Faster than full page loads○ We can make them even faster
● Fewer network requests● Higher expectations for mobile web apps
○ Animate between page loads■ Must be careful to avoid janking the animations.
● We want to hide latency and make it feel seamless○ Ideally instantaneous if you prefetch
Dynamic page load
Jankiness can be introduced at almost every step.
When the user expresses an intent is where it starts.
User Input, can be a touch, click, scroll, anything that signifies a dynamic page load should occur.
User Input
Tim
e
Dynamic page load
Often, page transitions require you to clean up or animate some stuff.
This can involve removing event listeners, turning off animations, removing DOM elements, etc.
We typically will want to fetch the page data and then run dispose because why wait?
User Input
Dispose XHR
Tim
e
Dynamic page load
Note that network happens on a separate thread and does not block the render thread.
The XHR however is on the same thread and cannot run in parallel with dispose.
User Input
Dispose
XHR
Tim
e
Network Manager
hl.c
o/ne
xt-p
age
Dynamic page load
After the response comes back an event handler for the XHR will run and mutate the web page.
After modifying the page, javascript code for the specific page may need to be initialized.
User Input
Dispose
XHR
Tim
e
Network Manager
XHR.onload
Mutate DOM
Init Page JS
hl.c
o/ne
xt-p
age
DOM mutation causes work
Dynamic page load
If you inject HTML, work must be done by the browser to parse the text into a DOM tree and appended.
The part of the DOM that was mutated needs to go through style recalculation and layout.
Then the DOM needs to be re-painted.
User Input
Dispose
XHR
Tim
e
Network Manager
hl.c
o/ne
xt-p
age
XHR.onload
Mutate DOM
Parse
RecalcStyle
Layout
Init Page JS
Paint
Dynamic page load
Your dispose call could have modified the DOM as well. If so, parse, layout, and paint will also occur after dispose.
Your JS + browser work can delay the handling of network responses.
User Input
Dispose
XHR
Tim
e
Network Manager
hl.c
o/ne
xt-p
age
XHR.onload
Mutate DOM
Init Page JS
Parse
RecalcStyle
Layout
Paint
Parse
RecalcStyle
Layout
Paint
Dynamic page load
From the user's perspective, the latency of going from one page to the next is the equivalent of starting with the user input all the way till the last paint.
So, we are done right?
User Input
Dispose
XHR
Tim
e
Network Manager
XHR.onload
Mutate DOM
Init Page JS
hl.c
o/ne
xt-p
age
Parse
RecalcStyle
Layout
Paint
Parse
RecalcStyle
Layout
Paint
DynamicPage Load
Deals with intra-site navigation. Typically AJAX driven.
Starts when an action (typically user driven) decides to load a page. This can be before the actual request.
Ends when the important parts of the requested page is viewable and ready.
"Warm"
Dynamic page load
Just because the DOM was changed via your XHR doesn't mean the page is ready.
You may have loaded additional stylesheets, more images, etc.
User Input
Dispose
XHR
Tim
e
Network Manager
XHR.onload
Mutate DOM
Init Page JS
hl.c
o/ne
xt-p
age
Parse
RecalcStyle
Layout
Paint
Parse
RecalcStyle
Layout
Paint
Dynamic page load
Just because the DOM was changed via your XHR doesn't mean the page is ready.
Often times there are css or images in your new page that need to be loaded.
When the CSS comes in, the page needs to be reflowed and repainted.
Tim
e
Network ManagerXHR.onload
Mutate DOM
Init Page JS
css
imag
e.pn
g
imag
e2.p
ng
Parse
RecalcStyle
Layout
Paint
RecalcStyle
Layout
Paint
Dynamic page load
Sometimes there is additional data to load, maybe from third party sources, or just delay loaded components.
Be aware of where and when your javascript is running during these critical moments.
Tim
e
Network ManagerXHR.onload
Mutate DOM
Init Page JS
mor
e da
ta
css
imag
e.pn
g
imag
e2.p
ng
moreData.onLoad
RecalcStyle
Layout
Paint
Parse
RecalcStyle
Layout
Paint
Keep therenderThreadidle
Break up long running Javascript
● Delay non-essential javascript● Debounce event handlers
○ readyStateChange/scroll/resize events fire way more often than you care■ These events will queue up behind slow js handlers
● Javascript should run in short chunks for animations○ For 60fps animations, limit javascript to < 16ms
(including browser render time!)○ requestAnimationFrame
Don't run js for long periods of time.
RAILResponse Animation Idle Load
https://developers.google.com/web/tools/chrome-devtools/profile/evaluate-performance/rail
0 - 16ms Threshold for animations
0 - 100ms User input response
100 - 300ms Detectable delay
300 - 1000ms Keeps user focus
1000+ms Users lose focus
10s+ Abandonment
RecalcStyle
Layout
Paint
Reduce/eliminate parse time
● Using innerHTML requires the browser to parse HTML text into DOM○ Often faster to use alternatives:
■ createElement/cloneNode/appendChild■ <template> importNode
● innerHTML is also a security issue● Try not to block parse with scripts. Parse
Parse time blocks on inline scripts.
Make recalcstyle and layout faster
● Mutate as few DOM elements as possible○ The browser can optimize for subtree changes
● Reduce the size of your DOM○ Rule of thumb: no more than 3000~ elements on a page
● Simplify the number of CSS rules and selector complexity
● Hide things that are not visible○ display: none
● Avoid mutating stylesheets.
Parse
RecalcStyle
Layout
Paint
RecalcStyle
Layout
Recalculate Style + Layout in Devtools
Speeding up paints
● Use GPU rasterization on mobile web○ Use meta viewport tag containing width=device-width
and minimum-scale=1.0● Use layers where it makes sense
○ Do research, be careful where you do it■ Don't create too many layers
○ Creates separate textures■ can eliminate the need to paint at all
Parse
RecalcStyle
Layout
PaintPaint
Networking for dynamic pages
● Layout blocking mode isn't active anymore● Typically fewer requests for dynamic transitions
○ Be careful cancelling a request with HTTP/1. Socket is closed and requires to be rebuilt
● Do you value images or AJAX?○ Image priorities are LOWEST/IDLE vs. XHR which is LOW
Summary
● Profile your page loads○ Test with webpagetest.org
● Make your page transitions seamless○ Keep your render thread idle and happy
● Understand how the browser loads your page○ Both first page load and intra-site page loads○ Analyze your render thread!
Questions?
Extra Slides
Real User Metrics
● What does your website feel like to the average user?○ Are you optimizing the correct area?
● Fully understand the flow of your website○ What actions/events are important to your users?
■ When does this action/event start?○ What are the blocking steps?
■ Are they blocked on network? CPU? User input?● Need large data sets
○ Server side performance tends to be consistent○ Client side performance is noisy and requires large data
sets.
Measuring start and stop
● Start as early as possible.○ Use the navigation/resource timing APIs.
● Where to stop depends on your site.○ Content above the fold is typical.
■ onLoad is not a good measure.○ If you're a video site, you may care more about the video
playing.
Navigation/Resource Timing API
Profiling tools I use
● DevTools○ All types of goodies○ High overhead, accessible, (mostly) easy to use
● chrome://tracing○ Gives you insight to Chrome○ Hard to use○ High overhead
● Web Tracing Framework○ Setup required○ Low overhead instrumented profiling
Chrome DevTools - Network Panel - Throttling
Chrome DevTools - Timeline
● Arguably most powerful tool in devtools● High overhead● Observe render thread blocking operations
○ What javascript functions were called○ How much time did parse/recalculate style/layout/paint
take?● Style Invalidation Tracing/Paint Inspection/Memory
profiling● Lots more stuff!
Chrome DevTools - Timeline
chrome://tracing
● A very detailed view into Chrome● Hard to use
○ A lot of data■ Collects data from all of chrome, not just your tab
○ Limited collection buffer size○ Limited amounts of app specific JS information available
● Best run in its own Chrome instance
chrome://tracing
Web Tracing Framework
● Written for Google Maps○ http://google.github.io/tracing-framework/○ Made for tracking FPS and inspecting WebGL
● Instrumented profiler○ Low overhead○ Setup cost
■ Minified code exports readable names to profiler○ Does not play with Chrome Devtools○ No network view
Web Tracing Framework
top related