Make the entire web faster
| Delay | User reaction | 
|---|---|
| 0-100 ms | Instant | 
| 100-300 ms | Feels sluggish | 
| 300-1000 ms | Machine is working... | 
| 1 s+ | Mental context switch | 
| 10 s+ | I'll come back later... | 

 
      | Content Type | Avg # of Requests | Avg size | 
|---|---|---|
| HTML | 8 | 44kB | 
| Images | 53 | 635kB | 
| Javascript | 14 | 189kB | 
| CSS | 5 | 35kB | 
 
      
| DNS Resolution | 130ms average, see Google DNS | 
| TCP handshake | TCP Fast Open & CWND proposals | 
| Request pipelining | SPDY: multiplexing, compression, ... | 
| Parsing & execution | You're running Chrome, right? | 

Modest to no noticeable speedup after 5mbps! Errrrr.. why!?
Created via webpagetest.org: IE 8, from Tokyo... Yikes?
(faster) connectivity won't save us, better protocols can help, but...



<script> _gaq.push(['_setAccount','UA-XXXX-X']); _gaq.push(['_setSiteSpeedSampleRate', 100]); // #protip _gaq.push(['_trackPageview']); </script>
Google Analytics > Content > Site Speed


 
    Content > Site Speed > Page Timings > Performance
Migrated site to new host, server stack, web layout, and using static generation. Result: noticeable shift in the user page load time distribution.
 
    Content > Site Speed > Page Timings > Performance
Bimodal response time distribution?
    Theory: user cache vs. database cache vs. full recompute
    
<script>
  _gaq.push(['_trackTiming', 'category', 'label', time]);
  _gaq.push(['_trackTiming', 'jQuery', 'Load library', 20]);
  _gaq.push(['_trackTiming', 'slide', slideNum, timeOnSlide]);
  //                                            ^^^ win.
</script>
    
  ResourceTiming interface to allow Javascript mechanisms to collect complete timing information related to resources on a document.
W3C draft / work in progress
 
    cnn.com waterfall: blocking JS requests, missing assets, missing cache headers on images and JS. Plenty of room for improvement.
Question: what are the blue and red lines in the waterfall?
 
    <script src="file-a.js"></script> <script src="file-b.js" defer></script> <script src="file-c.js" async></script>
<script src="file-a.js"></script> <script src="file-b.js" defer></script> <script src="file-c.js" async></script>
 
    #protip: investigate a good script loader
 
    cnn.com timeline: evaluate every request, track JS execution time, style reflows, etc.
60%+ of the weight of the page is images (on average)
 
    #protip: automate it.
$> Google Chrome --remote-debugging-port=9222
$> curl localhost:9222/json
[ {
   "devtoolsFrontendUrl": "/devtools/devtools.html?host=localhost:9222&page=1",
   "faviconUrl": "",
   "thumbnailUrl": "/thumb/chrome://newtab/",
   "title": "New Tab",
   "url": "chrome://newtab/",
   "webSocketDebuggerUrl": "ws://localhost:9222/devtools/page/1"
} ]
    
    
       
    
ws = Faye::WebSocket::Client.new(resp.first['webSocketDebuggerUrl'])
ws.onopen = lambda do |event|
  ws.send JSON.dump({id: 1, method: 'Network.enable'})
  ws.send JSON.dump({
    id: 2,
    method: 'Page.navigate',
    params: {url: 'http://twitter.com/#!/search/html5?q=html5&' + rand(100).to_s}
  })
end
ws.onmessage = lambda do |event|
  p [:new_message, JSON.parse(event.data)]
end
    
    
"method":"Network.responseReceived",
"params":{
  "type":"XHR",
  "response":{
     "url":"http://api.twitter.com/1/trends/available.json?lang=en",
     "status":200,
     "statusText":"OK",
     "mimeType":"application/json",
     "connectionReused":false,
     "fromDiskCache":false,
     "timing":{
        "requestTime":1333830921.9814498,
        "connectStart":1,
        "receiveHeadersEnd":234
        // ...
    
     
    Connect your Android device via USB to the desktop & view and debug the code executing on the device
 Google PageSpeed
Google PageSpeed

require 'net/https'
require 'json'
uri  = URI.parse('https://www.googleapis.com/pagespeedonline/v1/runPagespeed')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
params = { :key => 'API KEY', :url => 'http://railsconf2012.com/',
           :strategy => 'desktop', :rules => '...' }
uri.query = URI.encode_www_form(params)
req = Net::HTTP::Get.new(uri.request_uri)
res = http.request(req)
jj JSON.parse(res.body)
    
    API Documentation, widget examples, etc.

Goal: no surprises in the recommendations.

Open-source Apache module that automatically optimizes web pages and associated resources.
ModPagespeedCssInlineMaxBytes 2048 ModPagespeedImageInlineMaxBytes 2048 ModPagespeedCssImageInlineMaxBytes 2048 ModPagespeedJsInlineMaxBytes 2048 ModPagespeedCssOutlineMinBytes 3000 ModPagespeedJsOutlineMinBytes 3000 ModPagespeedRetainComments "[WILDCARD PATTERN]" ModPagespeedJpegRecompressionQuality -1 ModPagespeedImageLimitOptimizedPercent 100 ModPagespeedImageLimitResizeAreaPercent 100 ModPagespeedMaxInlinedPreviewImagesIndex 5 ModPagespeedMinImageSizeLowResolutionBytes 10240 // ...
<VirtualHost *:80>
    ServerName www.your-awesome-html5-app.com
    DocumentRoot /apps/foo/public
    ModPagespeed on
    /* ... */
</VirtualHost>
    PageSpeed Service fetches content from your servers, rewrites the pages by applying web performance best practices and serves them to end users via Google's servers across the globe.
Setup:
Stay tuned for more...
+Ilya Grigorik, @igrigorik, igrigorik@google.com
Blog @ www.igvita.com
Slides: bit.ly/html5devconf-speed