Tip:
Highlight text to annotate it
X
PAUL IRISH: Yeah, OK.
So let's start.
So I'm going to talk a little bit about the tools that are
available to identify and improve some of the things
that we actually saw tonight.
And to start off, I want to kind of separate some of the
performance ideas into two separate buckets.
If this works for you guys.
I don't know.
It seems kind of OK.
The user experience of performance is mostly separate
into things.
Like, give me the damn thing that I wanted, and now that I
have it, I want to interact with it really nicely.
So, and give me the damn thing I wanted it's page load, often
abbreviated as PLT, page load time.
In here we're talking about things like the network
waterfall, getting image assets that are appropriately
sized, non-blocking delivery of all of our assets, getting
the CSS that we need to render the top of the page, quickly
and not much else, and also fonts, can we
see the text quickly.
When we're talking about runtime performance we'll talk
about, like, I want to interact with the page, I want
to click a button and see that response very quickly.
Any sort of transitions, animations when I'm scrolling,
does it stick to my finger?
Like, I am scrolling with my finger on the device and it
should just be moving immediately with things.
What we heard about with memory leaks and garbage
collection, and also JavaScript based innovation
like with request animation frame.
But, to show a little bit more about this stuff, I kind of
want to take an example.
So we're going to start off with a demo.
This is a site for a festival in Canada, and it's the
Canadian National Exhibition.
So we're actually just going to go over to the site now,
the live site, and we're going to play around.
I'm actually going to do it here in Chrome Canary.
OK.
Cool.
So how does this look?
Oh, it's too wide.
OK.
That seems good.
So, Canadian National Exhibition.
My friend Mike Taylor who works for Firefox found this
site and he said, I defy you to find a site that is jankier
in its scroll.
And I was like, I know of a site, actually.
So like this one, what is it?
Inception explained, is it?
Is this it?
It's really bad.
It is-- so Paul mentioned parallax sites before.
Parallax sites can get into trouble really fast, and this
site is so cool, but the frame rate on this is just so poor.
It's rough.
But let me go back to what I was talking about.
So Canadian National Exhibition.
So here we are.
We got some things happening.
We got this [INAUDIBLE] background, full
bleed in the back.
This header that kind of moves,
scrolls up as I go down.
But let's actually look in the tools to see what we're
talking about.
All right.
So first thing, I'm just going to turn off this debug mode I
had on earlier.
And always first thing, go to Timeline, start recording.
I use Command E and we just kind of scroll up an down.
OK.
So we're seeing a lot of activity already.
All right?
A lot of stuff.
We're seeing mostly purple, right?
I'm scrolling in on this area just to kind of get a better
zoom, and it looks like Recalc Style is consuming a lot of
each of these frames.
So, OK.
Recalc Style.
Some things could be happening, I'm
not really sure what.
So we hover on the item and we can see the JavaScript call
stack is associated with us.
So the last thing that happened was here inside
Remove Class inside jQuery.
OK.
So I'm going to click that just to find out
what exactly it was.
We're minified here.
OK.
We'll pretty print down at the bottom.
Looks good.
Now I'm going to come back and just repeat that click again.
OK.
Cool.
So now we repeat the click and it brings me
to the exact place.
I really like it when the cursor does it's pretty thing.
So it brings me right to the class name assignment.
So there's a setting in the class name on an element, and
that is what triggered the recalc style.
OK.
That's good to know.
Now let's find out why that happened.
We look down into the user code.
And so here we go inside CNE.js.
Let me try clicking that once again.
Line 33, ah, ooh, ah.
Remember how Paul might have mentioned do as little as you
can inside your scroll handlers?
So inside their scroll handler they get the height of the
window, the scroll top, they do a little bit of math, and
then they toggle some classes on the HTML element in every
single scroll.
Toggle, toggle, toggle, toggle.
Not great.
Certainly not great.
But we can make this better.
So I'm going to--
so the best way to do this is-- you can see it's a
conditional toggleClass, right?
You're using the second argument inside jQuery's
toggleClass.
They conditionally change it depending on that
math working out.
So that's OK.
So, ideally, you set this in an F block, and you only touch
the DOM if you satisfy that requirement.
That makes a bit more sense.
We could actually change things a little bit, so I'm
just going to edit the JavaScript right here.
Oh, oh, one sec.
This is OK.
All right.
I'm going to edit the JavaScript right here so I'm
just going to back space-- oh, come on.
All right.
Cool.
And we're just going to get the DOM element itself, and
then we're going to use the classList from HML5.
And turns out, classList toggle actually has the exact
same method signature as jQuery's toggleClass.
And now I'm just going to hit Command S and Chrome is just
going to update that function on the fly.
Which is pretty cool.
So then we're going to go back to Timeline and I'll start
recording again and repeat my action.
Yeah.
Nice.
Pretty sweet.
So here we are.
We do not have massive recalc style anymore, but we do have
some green paint going on.
Hmmm.
Now, on this device, I am still hitting mostly 60 FPS so
that's kind of OK.
But on mobile devices I certainly would not be.
I want to see if I can do anything
about this paint first.
So, first things first, I'm going to come over into the
Settings and turn on Show Paint Rectangles.
And usually, when I do this, I like to turn on the Show
Composited Layer Borders at the same time.
Kind of go hand in hand.
So, bring DevTools down a little bit and now I'm just
going to scroll up and down.
So my paint recs are in a red, and we're seeing things.
A lot going on, but I can definitely see up top, this
section, the header is just in red non-stop.
Now, the reason why is because the header is position fixed,
and the content is moving beneath it.
But that is--
that's not going to work.
So it's basically repainting this, even
though it really shouldn't.
It knows what that looks like, right?
So the trick here is what?
What's the fix for this fixed position element?
AUDIENCE: Translate(Z)?
PAUL IRISH: Ooooh, yeah!
Translate(Z).
There it is.
I'm like, I'm excited to type it and then I
also, like, dread it.
It's like a combination of things, really.
OK, OK.
Webkit-transform translate(Z).
Oh, my friend.
Some people do like the 3D version, but then you have to
do zero, comma, zero, comma.
This is my favorite.
All right.
So I got that in, I promoted the layer and, in fact, there
is now this little gold border around the top.
And let's see if I can--
if I just toggle this you can see that gold border coming on
and off because that is now a layer.
All right.
So we're going to put it back on.
And if I scroll up here-- oh, cool, yeah.
We do not paint that.
But then we get about here and it moves,
and we see that paint.
And actually, let's fix this.
So the movement is here--
top-- we just move the top.
Now what's probably a better way of moving this top other
than just changing position absolute?
If we want to move an element?
AUDIENCE: Translate.
PAUL IRISH: Translate.
Yeah, sounds good.
Let's do a transform translate.
All right.
So WebKit and--
well, WebKit and Blink still have prefixed transform, so we
will do that.
Hop over here and do a Translate(Y).
And that seems to work.
And since I have a CSS transition down here, I should
probably update that.
Ah, OK.
Now that's a bit nicer.
I still do see red.
Hmmm.
Let's see if-- ah, yes.
Is that right?
You know--
ahh, oooh, ahh.
And it feels--
I don't if it feels smoother to you, but it
feels smoother to me.
It feels good.
All right.
So that's pretty good.
And let's take a look over in the Timeline.
All right.
Cool.
So, in general, in the middle, we got, like,
nothing going on.
We got a little bit of paint up when I'm going between the
top or when a new image is coming in.
That's pretty good.
So that's a little bit of things that we can do inside
the DevTools.
I actually made a video showing kind of taking this
all the way.
The background has a fixed position and we can actually
move that to the body element and get some wins there.
But I'm going to come back to my slides first.
Slides first.
Oh, yeah.
All right.
So I want to walk through some of those operations that we
are seeing.
Recalc Style.
So what's happening inside recalc style is it is getting
all the style rules that affect the page.
This is anything inside a style sheet, an inline style,
the user agent style sheet.
It's getting all the style rules, it's bringing them into
an object model, then it takes all those selectors that you
got hanging around and matches those against
what's in the DOM.
It says, oh, yeah it is that one right there.
Yes, uh huh.
The selector matching.
Now, as Paul said, happens really fast.
Usually in recalc style, the selector matching takes up
about 10% of the general purple bar.
Not very much.
Don't worry about it.
Now that it has that mass against the DOM, it calculates
the computed style for every single DOM element.
So you know in JavaScript when you ask for a Get Computed
Style, it's doing that.
But for every CSS property, for every element, it figures
out how things should look.
Makes sense.
OK.
Moving on to layout.
Layout is the geometry of the page.
And I want to show kind of one way to look at layout.
So I'll open up this little demo right here and--
come on.
Jsbin server is in the UK isn't it?
AUDIENCE: Yep.
PAUL IRISH: Yeah.
It's like looking at a loaded spinner.
All right, cool.
So I'm going to click these buttons like that.
Now, what I'm going to do is I'm going to hit Switch Layout
and we're going to start this animation.
Now, if I open up Timeline and record, you can see that as
that animation's happening, we're getting a
lot of layout costs.
And that makes sense because layout is reevaluating the
geometry of the page.
And this sort of animation here has to figure out this
new text flow, and when the text flows then we get a new
height for where person two starts and
person three starts.
And it's a lot of work to figure out that new geometry.
And it happens every single frame of that animation.
It's a bit expensive.
Now, the next thing after layout is
determined, is paint.
We heard a lot about this from Paul.
Paint hurts a lot on low-end devices.
Old Android phones with not a lot of hardware have a tough
time updating anything when it requires paint on every frame.
Debugging this with continuous paint mode is probably one of
the best ways to do it.
So I'm going to show that real quickly.
I said real quickly and then I loaded up a Jsbin URL.
Come on, England.
Come to me, the bits.
All right.
Handy trick.
DevTools, at the bottom, you might like it on the right.
You can just take the bar here and drag it up to the--
you can also click the button.
Great.
I have a lot of DevTools extensions and I'm just going
to make excuses.
OK.
You might have noticed inside of Chrome Canary that I have--
wow.
Let's go back.
So we're here, we're looking at this page, we have lovely
boxes all over the place.
That's real good.
But we're going to turn on Continuous Paint mode.
Now, Continuous Paint mode basically says to Chrome, hey,
I know you know what it looks like, but I just want you to
tell me what it looks like again and again and again and
again and again.
So it's just going to repaint everything that
needs to get painted.
So if I look at Timeline, it is just doing the same work
over and over again.
But what this allows us to do is make some changes and see
how it affects that graph up there.
So right now we're looking at eight milliseconds or so per
paint of the entire page.
Now we can try some different things.
So maybe I'm going to come over here and
toggle the box shadows.
So I turn on box shadows and you can see pretty quickly--
sorry about that--
paint time dives really, really high.
So the box shadow is adding quite a bit to how long it
takes to paint the page.
I also know that there's a border radius on these boxes.
I can try turning that off, see if that makes any
difference.
It does make a slight difference, yeah?
But this gives you an option to kind of figure out things.
Now, a handy trick when you're using continues painting mode
is the H key hides DOM elements.
So you can kind of walk through you're DOM, hide
things and see what the effect is.
So maybe you'll hide the header, kind of get that out
of the way, and kind of bisect the DOM, figuring out where
your costs are.
This H works all the time.
It's pretty handy.
All right.
So that's Continuous Painting mode real quick.
I got a question recently, which is, there's all these
operations inside the DevTools Timeline.
What is the order that I should see them in?
And what we're looking at right here is, basically, it.
So a lot of times you start off with some JavaScript, it
touches the DOM, it changes something, then the browser
does have recalculate style, has to layout the page, has to
paint it and probably composite some layers.
Ideally this is the flow and there's only one operation
per, basically, paint.
Paint is the user got to see something.
When we were talking about layout thrashing before,
layout thrashing is, oftentimes, we're doing a
bunch of recalc style and then layout, and then recalc style,
layout, recalc style, layout.
And the user doesn't see anything.
There are no paints.
So ideally, you have only one layout per paint.
So here's a little cheat sheet for kind of taking action from
what the Timeline is telling you.
If the Timeline is telling you, oh, my god, lots of
yellow, there's so much time being spent inside JavaScript.
I should point out that that Canadian expo site--
remember when I profiled it before?
Was there any yellow at all in it?
No.
There was no JavaScript at all slowing down that site.
It was all inside the rendering inside.
But, if you're in a case where you are in a lot of
JavaScript, you can use the flame chart.
I'm going to show this really quickly.
Who has seen the flame-- who has seen or
used the flame chart?
It's good.
It's a powerful thing.
So this is MathJax.
And they're really good polyfill for MathML.
But I want to check out how fast it can
render these things.
So I'm going to turn off these, come down here-- and so
it's actually just rendering this stuff out, and I can
choose to render it in SVG or HTML CSS.
Come over to Profiles and I'm going to collect a JavaScript
CPU profile and record.
Change this.
All right.
Cool.
Now, normally when you come into the JavaScript profile
you see something like this.
Just go down to the bottom right there and
select flame chart.
What is going to give you is a view like this.
And so this is a time based view of JavaScript execution.
And it progresses from left to right over time just like you
expect in a timeline.
And in fact, if you want, you can record on the Timeline and
on the JavaScript profiler at the same time.
But you see some spikes, you want to go investigate what's
actually happening, and so I'll take a look
at the SVG one first.
So we can see there's actually a good amount of latency,
there's good gaps between all these flames.
And if you look on Timeline, there's actually a bunch of
network activity that's happening
between these things.
So they're making network requests as they're trying to
pull together things, and it's a bit inefficient.
Over in this version they don't have that problem, but
we can identify kind of where all the function costs are
coming from.
Now, height is just call stack.
So height is really not important.
What's important is width because width is time.
But we're able to see here kind of what are the functions
that are taking up time.
We also get to understand the execution code paths here, and
what calls what and how do we go from start to finish in
this operation.
All right.
So that's if we're spending a lot of time in script.
If we're spending a lot of time in layout, dig into the
JavaScript that's triggering it.
In DevTools Timeline like I showed before, you'll see a
call stack.
Find out what you're doing in JavaScript that is forcing the
browser to do a layout.
With paints, find what is actually being repainted.
Turn on all those paint rects, turn on the layer borders and
see what's happening.
You might have to promote a layer using translate(Z) to
get out of a pain storm.
This often happens with fixed position elements,
but you kind of--
take another look at what Paul showed you.
You can bisect what are actually expensive things
happening using Continuous Paint mode.
And if none of these things answer your questions, it's
time to dig into about:tracing which is a really extensive
tool and I'm not going to touch it right now.
But, to tackle kind of like all of these operations, and
how they actually map to your CSS, we should probably take a
look at that.
So, if we take this little block of CSS, the selector up
there-- that does have to get matched up to a DOM element--
so the selector will be caught up in recalc style.
The height effects the geometry of the box, so that
is mostly captured inside the cost of layout.
And a text shadow does not affect any geometry of the
page whatsoever.
It is just a visual effect, right?
So it will have no effect whatsoever
inside layout and paint.
Now, this is helpful to know because if you turn on
Continuous Painting mode, it's only going to give you numbers
that reflect things that have an effect on paint.
So you change the height of a box inside Continuous Paint
mode, not much, really--
you're not going to get a good result.
But another way to look at this is that different CSS
properties kind of effect these different things.
So, like Paul mentioned before, transform and opacity
are really fast because the GPU can handle it 100%.
So this happens here.
They do not need to--
if you're touching transform and opacity--
you do not need to lay these out, you do not
need to paint them.
A few happen in paint, so this is box shadow, border radius.
There are visual effects.
Like I said, they don't affect any geometry.
Outline is also here, because outline is similar to border
but outline you can change an outline from one pixel to 100
pixels and everything stays the same place.
But a lot of things--
a lot of CSS properties do affect the layout.
Of course, anything that affects the position of the
boxes, width, margin, border, absolute positioning, relative
positioning.
These things affect layout.
And actually--
I took a look at all the CSS properties.
Chrome actually just recently--
yesterday, I think--
released some numbers around the popularity of all CSS
properties on the web.
And this is them.
So width is the most popular CSS property.
Who would have expected that?
But it's interesting to kind of look at these and identify
kind of what sequence of operations they force.
And so most actually do effect the geometry the page, but of
course, opacity, like I mentioned, does not.
Another cool way to look at this is animatable.
Lea Verou made this tool and, hopefully, I can show this
really quickly.
So this is just using keyframe animations just to change a
single CSS property on a bunch of different things.
But it's pretty cool to bring this up and try it out to see
what it actually looks like inside Timeline.
So, like I said, we'll take a look at font size.
Font size.
There we go.
So as we animate font size, font size does cause layout
and we see it right here.
Box shadow, like I mentioned, does not have any effect on
layout and--
did I lie?
Oooooh, tough Paul.
Let me try one more.
There we go.
That's pretty good.
So we're doing a transform animation.
It's just staying on the GPU.
We're not going back to layout.
So this is extremely efficient when it comes to animations.
So, in transitions there's a lot of things.
There's four things that a browser can do really, really
fast and jank-free.
It can scale, can move, can rotate, can fade.
These translate in CSS to these guys.
I should point out, you might need the null transforn hack.
Maybe.
But, if you're doing any animations, any visual
effects, you want to be doing them with these operations.
These can be fast.
It can be fast on low-end hardware, it can be fast on
high-end hardware.
Every other operation is going to incur layout, or maybe a
good amount of paint.
So it's going to be slower.
Now, when it comes to measuring we want to know that
these measurements--
these performance enhancements that we're doing
are good for people.
If we take a look at Twitter, the load event-- window.load--
fires about midway through the network waterfall.
And the end of activity is quite a bit later.
So looking at window.load for knowing that the page is kind
of done is not going to work out.
So we need better ways to identify how
successful are we.
So this is an approach developed by a guy named Pat
Meenan who runs WebPageTest.
So up at the top we have the film strip view of loading a
page that's been optimized two different ways.
And so you could see that the third way is delivering
content to the user faster than the other ones.
Down here is a plot of the percentage of the visual
progress plotting these out.
So you can see here we're already showing things to the
user, and so that's why gold is jumping up.
Now, if we want to take this and turn it into a metric, we
can take the area above that line and just kind of absorb
it into a figure.
So this is called the speed index.
It's basically the area above the curve that accounts for
what the visual progress being shown to the user.
So this is a nice quantitative measurement for getting a
successful picture in front of the user.
Now, in the real world, we want to be able to identify
things like how as we're developing a project over
time, are we regressing performance, are
we improving it?
Adobe Topcoat is a CSS library that has a really nice
framework set up for benchmarking.
So they're using a project called Telemetry that
Chrome works on.
And so this is actually a view of their button element, and
on the horizontal axis we just have commits.
And we can actually see for the mean frame rate, the load
time, and the layout, how things are progressing.
And so you can actually see this is a pretty big
regression in load time of this test case.
And then things actually did slow down later here as well.
But we're able to track this over time
which is really powerful.
Another developer took a look at this and applied this to
Bootstrap over the history of the project from 1.0 to 3.0.
And so this is just a quick view of the drop downs
component inside Bootstrap, and we're looking at the first
paint metric.
First paint is a tricky one and it's hard to find good
metrics, but I think speed index is one of the best ones.
Inside Google Analytics there's a few tools for these.
You're looking at network activity, you can identify
page load time, domain look up, page download time.
All these are the exact same as window.performance.timing,
but since all major browsers support this, Google Analytics
will report it here.
You could also get these numbers split up by browser,
by operating system.
So this is just a view I made of browser
and operating system.
Here you can see Safari on iOS is considerably slower on page
load time than the rest.
And I think that's mostly because it's on a mobile
network whereas nearly all these others
are desktop on Wi-Fi.
SpeedCurve is a really cool site.
Its still in private beta right now but it's hoping to
give you a lot more insight when it comes to the
performance of your site over time.
And so here is HML5 Rocks-- which I work on--
plotted against Amazon and TripAdvisor.
You can kind of see that.
But one tool that I really want to show is WebPageTest
and I'm going to show it with a site called Retailmenot.
This page I just loaded now.
I'm going to do a shift refresh because it's so fast.
The developers behind this worked quite a bit on the page
load time and it really shows, but what's really cool is
taking a look at what WebPageTest tells us.
So I ran this just earlier today.
So we did--
this is Retailmenot assuming a cable internet connection
inside Chrome.
And so here--
if you've seen WebPageTest before, it's been
around for a while--
you might know it has waterfalls and stuff.
It has a lot more than that.
I really encourage you to take another look.
First thing I'm going to show is the film strip view.
So over here in the film strip view we have, just like
before, every 100 milliseconds we have a snapshot of what the
page looks like.
And you can see at 0.9 seconds we start to have an actual
page being rendered.
It's really cool, as I scroll through this
you can see my waterfall.
We're kind of going through my network waterfall and we're
seeing that correlation.
Now, another really nice thing is that you can ask
WebPageTest to capture the DevTools Timeline recording.
And so we can just view the DevTools Timeline
associated with this.
So I'm just going to do that right now.
So Chrome DevTools is a web app, as you know, so we're
just viewing this as a web app.
And this is the actual recording that we were looking
at on WebPageTest, and we can see a lot more.
So we can see, here's the data coming in, HTML, Google
Analytics causes a layout, they're asking for an offset
width so you get the screen size.
Then we come down here and pretty soon we get a paint.
And so this is that paint.
It's at 818 milliseconds, that's why we are seeing a
thumbnail right then.
The last thing I'll show is that it even takes those
numbers from the Timeline and aggregates them over the load
of the page.
So we can actually see, for that entire duration that it
was recording, let's summarize all the time it spend in
layout, in JavaScript, in paint.
And so we can see here, for that page load time, where was
the browser spending its time?
So here, we're mostly spending a lot of time in JavaScript,
to be honest.
But layout does contribute a little bit to this.
All right.
So WebPageTest, really cool, had a lot of features
recently, and the nice thing is that you can take the
difference between multiple recordings and be able to
track your performance over time.
If you do want to use this, the site--
if you use WebPageTest.org--
the site it has to be--
the site you're testing has to be online--
but you can run a private instance.
So you can run against a development
server if you want.
It's all open source.
All right.
So to sum up, few things.
We heard a lot of numbers tonight.
Under 60 milliseconds is smooth animation, under 100
milliseconds feels pretty much instant, under one second,
mmmm, I'm OK with it, over a
millisecond, users are unhappy.
So here are some aggressive, aggressive but good goals, and
things that we should really be striving towards.
When it comes to mobile connectivity, it is hard to
deliver things fast, but users get really
impatient quite fast.
Shoot to show the content that's above the
fold in under a second.
One important part of this is serving the above the fold
content in the first 14 kilobytes of the response.
This includes the CSS that you need to render everything
that's above the fold, you can defer the rest of
the CSS later on.
You don't need it just yet.
If I fit it in that first 15--
14 kilobytes, that number is not totally magic.
It's based off of how TCP Slow-start works.
It's the first time that you're really going to get a
considerable amount of data back.
Maximum of 200 milliseconds server response time, 60 fps
on scrolling, 60 fps on transitions, and a speed index
of under 1,000 would be pretty good.
So aside from reaching those goals, which are hefty but
good, what can you do?
I think it's hard to kind of work on-- it seems, talking to
the people that I do, a lot of people explain that it's hard
to make the case to work on performance.
You've got to ship features, you got to get that out the
door, people expect the end result.
And I think we really need to be able to make the case that
performance is incredibly important.
And the best way to do that is-- you can show them the
numbers from Google and Amazon and Microsoft, and anyone who
has said that it effects the bottom line significantly--
but I think most people really want to see it with their own
site, with their own data.
So find in your own analytics ways to correlate performance
wins to actual business wins that they care about.
So maybe the speed index correlated to conversion rate.
People that are experiencing your site faster are
performing better.
Make the case to your client that performance often might
trump their feature request.
That awesome cool feature that the user will find once they
register for your site probably won't get to that if
they're waiting 10 seconds for the site to load.
Set up infrastructure to track your perfs so you can identify
over the development of project if you're regressing
performance or if it's improving.
And, to be honest, there's some tools available.
I showed some of them tonight, but I think it's still quite
early in the space and the open source community could
use a lot more to kind of help everyone
track this stuff better.
So I encourage you to join a project or start a new project
to help everyone in this area.
All right.
Thanks, everyone.
Stick around.
We're going to do Q&A in a little bit.
Thank you.
[APPLAUSE]