highload++ 2012 proactive wpo
DESCRIPTION
Slides from my talk at Highload++ 2012 in Moscow, Russia. This mainly covers the use os YSlow as part of Continuous Integration to prevent regression to end user which is a form of proactive web performance optimization.TRANSCRIPT
Proactive WPO@marcelduran
about:me
I'm not here
I'm from here on
V is for Vigilante
http://usa-moscow.blogspot.com/2010/09/more-hot-water.html
Performance Radarhttp://www.flickr.com/photos/benfrantzdale/1056282822/
“if you can’t measure it, you can’t improve it”
— Lord Kelvin
worst case: no instrumentshttp://www.flickr.com/photos/timothyhackworth/753783003/
build test
deploy
users
review
reactive
better case: RUMhttp://www.flickr.com/photos/pj/6116201547/
Real User Measurementshttp://lognormal.com/features/
github.com//boomerang
lognormal
build test
deploy
users
monitor
reactive
YSlow manually
YSlow automationhttp://www.flickr.com/photos/snazzyguy/3381047684/
+
much better: RUM + YSlow (CI)http://donq.com/recipes/rum-sour/
+
build test
deploymonitor
users
wpo
proactive
jul/07
+183k users (formerly +210k)+3.3mi downloadsTop 25 2bi add-ons downloaded
jul/07 mar/11
~160k users (formerly 145k)
jul/07 jun/11mar/11
jul/07 jun/11mar/11 aug/11
~80k users
jul/07 jun/11mar/11 aug/11
oct/11
jul/07 jun/11mar/11 aug/11
oct/11 dec/11
jul/07 jun/11mar/11 aug/11
oct/11 feb/12dec/11
first 24 hours437
37so far
88976
5th anniversaryhttp://www.flickr.com/photos/spool32/5045502202
jul/07 jun/11mar/11 aug/11
oct/11 feb/12dec/11 apr/12
jul/07 jun/11mar/11 aug/11
oct/11 feb/12dec/11 apr/12 jun/12
YSlow Command Line
$ npm install yslow -g
$ yslow --help Usage: yslow [options] [file ...]
Options:
-h, --help output usage information -V, --version output the version number -i, --info <info> specify the information to display/log
(basic|grade|stats|comps|all) [basic] -f, --format <format> specify the output results format
(json|xml|plain) [json] -r, --ruleset <ruleset> specify the YSlow performance ruleset to be used
(ydefault|yslow1|yblog) [ydefault] -b, --beacon <url> specify an URL to log the results -d, --dict include dictionary of results fields -v, --verbose output beacon response information
Examples:
yslow file.har yslow -i grade -f xml -b http://server.com/beacon file1.har file2.har yslow -info all --format plain /tmp/*.har yslow -i basic --rulseset yslow1 -d < file.har curl example.com/file.har | yslow -i grade -b http://server.com/beacon -v
HAR file
{ "log": { "version": "1.1", "pages": [ { "startedDateTime": "2012-08-16T18:27:29.000+00:00", "id": "page_1_0", "pageTimings": { "onLoad": 13701, . . .
$ yslow file.har$ yslow file1.har file2.har file3.har$ yslow my-har-files/*.har$ yslow < file.har$ curl http://foo.com/file.har | yslow
-f, --format <format> (json|xml|plain)
$ yslow foo.com.har{ w: 98725, o: 89, u: 'foo.com', r: 9, i: 'ydefault', lt: 981 }
$ yslow --format plain foo.com.harsize: 96.4K (98725 bytes)overall score: B (89)url: http://www.foo.com/# of requests: 9ruleset: ydefaultpage load time: 981
$ yslow --format xml foo.com.har<?xml version="1.0" encoding="UTF-8"?><results> <w>98725</w> <o>89</o> <u>http://www.foo.com/</u> <r>9</r> <i>ydefault</i> <lt>981</lt></results>
-i, --info <info> (basic|grade|stats|comps|all)
$ yslow foo.com.har{ w: 98725, o: 89, u: 'foo.com', r: 9, i: 'ydefault', lt: 981 }
$ yslow --info grade foo.com.har{ w: 98725, o: 89, u: 'foo.com', r: 9, i: 'ydefault', lt: 981, g: { ynumreq: { score: 92, components: [] }, ycdn: { score: 80, components: ['a.com', 'b.com'] }, ... yfavicon: { score: 100, components: [] } }}
$ yslow --info stats foo.com.har{ w: 98725, o: 89, u: 'foo.com', r: 9, i: 'ydefault', lt: 981, stats: { doc: { r: 1, w: 18419 }, css: { r: 2, w: 20951 }, image: { r: 3, w: 29553 }, js: { r: 2, w: 10852 }, cssimage: { r: 1, w: 18950 } }}
$ yslow --info comps foo.com.har{ w: 98725, o: 89, u: 'foo.com', r: 9, i: 'ydefault', lt: 981, comps: [ {type:'doc', url:'foo.com', size:1841, resp:41, gzip:613}, {type:'css', url:'bar.css', size:3062, resp:98, gzip:989}, ... {type:'js', url:'baz.js', size:2445, resp:86, gzip:834} ]}
$ yslow --info all foo.com.har{ w: 98725, o: 89, u: 'foo.com', r: 9, i: 'ydefault', lt: 981, g: { ynumreq: { score: 92, components: [] }, ... } stats: { doc: { r: 1, w: 18419 }, css: { r: 2, w: 20951 }, ... } comps: [ {type:'doc', url:'foo.com', size:1841, resp:41, gzip:613}, ... ]}
-d, --dict
$ yslow -i basic --dict foo.com.har{ w: 98725, o: 89, u: 'foo.com', r: 9, i: 'ydefault', lt: 981, dictionary: { w: 'size', o: 'overall score', u: 'url', r: 'total number of requests', i: 'id of the ruleset used', lt: 'page load time', grades: '100 >= A >= 90 > B >= 80 > C >= 70 > D >= 60 > E >= 50 > F >= 0 > N/A = -1' }}
-r, --ruleset <ruleset>(ydefault | yslow1 | yblog)
Minimize HTTP RequestsUse a Content Delivery NetworkAvoid empty src or hrefAdd an Expires or a Cache-Control HeaderGzip ComponentsPut StyleSheets at the TopPut Scripts at the BottomAvoid CSS ExpressionsMake JavaScript and CSS ExternalReduce DNS LookupsMinify JavaScript and CSSAvoid RedirectsRemove Duplicate ScriptsConfigure ETagsMake AJAX CacheableUse GET for AJAX RequestsReduce the Number of DOM ElementsNo 404sReduce Cookie SizeUse Cookie-Free Domains for ComponentsAvoid FiltersDo Not Scale Images in HTMLMake favicon.ico Small and Cacheable
ydefault(aka YSlow V2)
23 rules
Minimize HTTP RequestsUse a Content Delivery NetworkAdd an Expires or a Cache-Control HeaderGzip ComponentsPut StyleSheets at the TopPut Scripts at the BottomAvoid CSS ExpressionsMake JavaScript and CSS ExternalReduce DNS LookupsMinify JavaScript and CSSAvoid RedirectsRemove Duplicate ScriptsConfigure ETags
yslow1(aka YSlow V1/classic)
13 rules
Minimize HTTP RequestsAvoid empty src or hrefGzip ComponentsPut StyleSheets at the TopPut Scripts at the BottomAvoid CSS ExpressionsReduce DNS LookupsMinify JavaScript and CSSAvoid RedirectsRemove Duplicate ScriptsReduce the Number of DOM ElementsNo 404sAvoid FiltersDo Not Scale Images in HTMLMake favicon.ico Small and Cacheable
yblog(aka small site/blog)
15 rules
-b, --beacon <url>-v, --verbose
$ yslow --beacon http://server.com/ foo.com.har{ w: 98725, o: 89, u: 'foo.com', r: 9, i: 'ydefault', lt: 981 }
$ yslow -b http://server.com/ --verbose foo.com.har{ w: 98725, o: 89, u: 'foo.com', r: 9, i: 'ydefault', lt: 981, beacon: { status: 200, headers: { "content-type": 'text/html; charset=utf-8', "date": 'Thu, 02 Aug 2012 17:23:33 GMT', "content-length": '3', "connection": 'close' }, body: 'ok\n' }}
before after
Case: Y! Continuous Deployment
before after
No Performance Test Suite
BOO!
YSlow for PhantomJShttp://www.flickr.com/photos/pedroferrer/3615212504
$ phantomjs yslow.js http://yslow.org
-f, --format <format>
( json | xml | plain | tap | junit )
$ phantomjs yslow.js -i basic --format tap http://yslow.org
TAP version 131..1ok 1 B (88) overall score
$ phantomjs yslow.js -i grade --format tap http://yslow.org
TAP version 131..24ok 1 B (88) overall scorenot ok 2 C (72) ynumreq: Make fewer HTTP requests --- message: This page has 7 external Javascript scripts ...ok 3 C (70) ycdn: Use a Content Delivery Network (CDN) --- message: There are 3 static components not on CDN. offenders: - "yslow.org: 1 component, 8.0K (8.0K GZip)" - "fonts.googleapis.com: 1 component, 1.0K (1.0K GZip)" - "widgets.twimg.com: 1 component, 0.8K" ...ok 4 A (100) yemptysrc: Avoid empty src or hrefnot ok 5 F (12) yexpires: Add Expires headers --- message: There are 5 static components without a far-future expiration date. offenders: - "http://yslow.org/stylesheets/styles-min.css"...
$ phantomjs yslow.js -i basic --format junit http://yslow.org
<?xml version="1.0" encoding="UTF-8" ?><testsuites> <testsuite name="YSlow" tests="1" failures="1"> <testcase name="overall score" status="C (79)"> <failure/> </testcase> </testsuite></testsuites>
-t, --threshold <score>( [0-100] | [A-F] | {json} )
default: 80
-t B-t 75-t '{"overall": "C", "ycdn": "F"}'-t '{"ycdn": "F", "yexpires": 75}'
-u, --ua "<user agent>"
e.g: -u "Mozilla/4.0 (compatible; MSIE 6)"
-vp, --viewport <WxH>
e.g: -vp 640x960
-ch, --headers <JSON>
e.g: -ch '{"Cookie": "foo=bar"}'
-c, --console <level>(0: none | 1: msg | 2: msg+line+source)
YSlow + CI = BFF
node.js server
local HAR file uploadcurl http://yslow.nodester.com/ -F '[email protected]'
remote HAR filecurl 'http://yslow.nodester.com/?har=http://server.com/foo.har'
HAR {json} stringcurl http://yslow.nodester.com/ -d 'har={"log":{"version":"1.1", ... }}'
+ +
curl "http://yslow.nodester.com/?har=http%3A%2F%2Fwww.webpagetest.org%2Fexport.php%3Ftest%3D120627_MC_5WD
&i=grade&b=http%3A%2F%2Fwww.showslow.com%2Fbeacon%2Fyslow%2F&v=1"
WPO at Twitter
High Performance
A A A A ...
best: RUM + (YSlow + WPT) CIhttp://donq.com/recipes/rum-sour/
++
build test
deploy
monitor
wpo
perf
users
proactive
performance boxes
branch A branch Bprod
...
branches comparison
X+100ms
branch A
X-50ms
branch B
Xms
prodvs
++
+vs
/getyslow
@yslowyslow.org
slides icons: http://www.iconfinder.com/
Cпасибо