Slide 1

Slide 1 text

Hands on Web Performance Workshop Andy Davies @andydavies Tobias Baldauf @tbaldauf #VelocityConf London 2013

Slide 2

Slide 2 text

We’re planning to cover ● Tools ● Techniques ● Live Analysis But…

Slide 3

Slide 3 text

…this session is about YOU so feel free to jump in with questions

Slide 4

Slide 4 text

What sites should we test? http://man.gl/londonworkshop

Slide 5

Slide 5 text

Do you use WebPageTest?

Slide 6

Slide 6 text

PhantomJS http://github.com/ariya/phantomjs/

Slide 7

Slide 7 text

Phantomas { "url":"http://tobias.is", "metrics":{ "requests":11, "gzipRequests":2, "postRequests":0, "redirects":0, "notFound":0, "timeToFirstByte":107, "timeToLastByte":120, "bodySize":151897, "contentLength":206417, [...] http://github.com/macbre/phantomas

Slide 8

Slide 8 text

All together now! #!/usr/bin/env bash URL_to_measure="$1" Metrics_to_analyze=('timeToFirstByte' 'requests' 'cssSize') Phantomas_JSON_output=$(phantomas --format=json --url "${URL_to_measure}") for((i=0;i<${#Metrics_to_analyze[@]};i++)) ; do eval ${Metrics_to_analyze[$i]}=$(echo "$Phantomas_JSON_output" | jq ".metrics."${Metrics_to_analyze[$i]}) export ${Metrics_to_analyze[$i]} done bats --tap performance-tests.bats #!/usr/bin/env bats @test "Time to first byte" { [ "$timeToFirstByte" -lt 200 ] } @test "Number of HTTP requests" { [ "$requests" -lt 30 ] } @test "CSS size" { [ "$cssSize" -lt 15360 ] } #1..3 ok 1 Time to first byte ok 2 Number of HTTP requests not ok 3 CSS size # (in test file /test/webperf/performance-tests.bats, line 23) http://github.com/technopagan/simple-website-speed-test

Slide 9

Slide 9 text

WebPagetest API http://github.com/marcelduran/webpagetest-api

Slide 10

Slide 10 text

Run WPT Run! webpagetest test http://velocityconf.com --server wpt.yourdomain.tld --location Local-SGS2 --wait { "statusCode": 200, "statusText": "Ok", "data": { "testId": "131019_VF_1", "ownerKey": "b5cf1cb86be59d94f3ee714f15da3efe5cf05b7z", "jsonUrl": "http://wpt.yourdomain.tld/jsonResult.php?test=131019_VF_1", "xmlUrl": "http://wpt.yourdomain.tld/xmlResult.php?test=131019_VF_1", "userUrl": "http://wpt.yourdomain.tld/results.php?test=131019_VF_1", "summaryCSV": "http://wpt.yourdomain.tld/csv.php?test=131019_VF_1", "detailCSV": "http://wpt.yourdomain.tld/csv.php?test=131019_VF_1&req=1" }

Slide 11

Slide 11 text

SwissArmyKnife Results "response": { "statusCode": 200, "statusText": "Ok", "data": { "testId": "131019_VF_1", "summary": "http://wpt.yourdomain.tld/results.php?test=131019_VF_1", "from": "Samsung Galaxy SII - Native", "runs": 1, "successfulFVRuns": 1, "successfulRVRuns": 1, "average": { "firstView": { "loadTime": 6285, "TTFB": 2852, [...]

Slide 12

Slide 12 text

TAP & Jenkins Integration

Slide 13

Slide 13 text

What if we want to test more than one page?

Slide 14

Slide 14 text

./sitespeed.io -u http://news.bbc.co.uk

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

Setup your own HTTP Archive… Barbara Bermes - http://man.gl/1eHoyqB

Slide 21

Slide 21 text

Lots of data!

Slide 22

Slide 22 text

hist(results$reqTotal, xlim=c(0,200), ylim=c(0,375), breaks=seq(0,200,by=5), main="", xlab="Number of Requests", col="steelblue", border="white", axes=FALSE) axis(1, at = seq(0, 225, by = 25)) axis(2, at = seq(0, 400, by = 25)) library(RMySQL) drv = dbDriver('MySQL') con = dbConnect(drv, user='user', password='password', dbname='dbname', host='127.0.0.1') results = dbGetQuery(con,statement='select * from pages;') Import data into R Plot histogram of requests / page

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

Sometimes bi-modal distributions

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

Commercial tools available too…

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

Let’s look at some live sites

Slide 31

Slide 31 text

Performance isn’t just about load time http://www.flickr.com/photos/jaxport/8554780980

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

Painting every 20ms!

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

Logo is actually made of four images that fade from one to another. CPU load varies between 7 - 20% Has detrimental impact on mobile battery life

Slide 37

Slide 37 text

A Tale of CSS Checkbox Hacks #toggle:checked ~ .menu { display: block; } http://css-tricks.com/the-checkbox-hack/ http://thenittygritty.co/toggle-navigation-with-pure- css http://bugs.webkit.org/show_bug.cgi?id=45168 body { -webkit-animation: bugfix infinite 1s; /* here be dragons */ } @-webkit-keyframes bugfix { from { white-space: default; } to { white-space: normal; } }

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

Be neighborly Adjacent sibling selector trumps general sibling selector #toggle:checked + nav .menu { display: block; }

Slide 40

Slide 40 text

Lessons learned Working in web performance is as much about educating as optimizing. Choose your battles http://josefbrandenburg.com http://sapdesignguild.org

Slide 41

Slide 41 text

Thank You (we’re around all week) Office Hours: 12:30 Thursday Andy: @andydavies [email protected] Tobias: @tbaldauf [email protected]