Google I/O 2012 - Jank Busters: Building Performant Web Apps


Uploaded by GoogleDevelopers on 29.06.2012

Transcript:
>>Nat Duca: All right. It's time to talk about jank, everybody.
Before I even do introductions, which is what usually comes first, I want to actually teach
you the word jank. Jank spotting, right? We all should do it,
and that's the first part of this talk. So if you go to HTML5 Rocks, hopefully everybody
has done this. It's a great resource. And you scroll up and down in an article, sometimes
it janks. And especially on bigger screens or slower computers, it feels yucky.
Now, let's define yucky. Watch the scroll bar as I scroll. See how it jumps? Watch on
your own computer. Scroll up and down. That's jank. It's the screen not updating in some
way. So the purpose of our talk today is to get
you, so that when you walk out the door, you can make your site or HTML5 Rocks, take your
pick, so that when I do the same thing, no jank. Right?
This is our goal. I hope we succeed at it. The reason that we're up here is we work on
jank all the time. I'm Nat Duca, I'm on the Chrome Developer team. I work on the rendering
engine for Chrome, GPU, 60 frames a second, blah-blah-blah.
>>Tom Wiltzius: I'm Tom Wiltzius, I'm the project manager on the Chrome graphics team
thinking about all the same stuff. >>Nat Duca: So we care a lot about this and
we want you to as well. So a nice smooth Web app is about feeding
your display. So you've got many displays surrounding you. These are displays.
There's a lot of variety as it turns out. For various reasons, for budget reasons, for
power reasons, different screens update at different rates.
Now, what is this update thing? You've heard the word vsync thrown around
over the course of I/O a few times. And what this is is your screen is going to pull into
memory somewhere and just pull out picture from the GPU or whatever and put it up on
either the LCD or the CRT, and it's going to do that in a fixed heartbeat. You can't
control it, especially not from software. It's just going to do that.
Now, this is mostly a good thing. And being smooth, having a smooth animation, something
that slides across the screen and looks really, really nice and buttery, is about having your
picture ready when that happens, just before it happens. And you have to do so being aware
of the fact that different screens are going to do that at different rates.
So in the yesteryear and even up to last year, some of the best JavaScript libraries out
there animated would set timeout. jQuery, for instance, I think had an eight-millisecond
set timeout thing. And we're here today to say --
>>Tom Wiltzius: Don't do it. >>Nat Duca: Please don't do it.
Now, it's kind of complicated why you shouldn't do it, so we built a simulation here for you
to help you understand this. So what you're seeing here is a couple of
sliders. This determines my refresh rate of the screen.
So you know, if I'm a low power Chromebook that's unplugged and decided that it should
go into low power mode, it's at 50-hertz and the blue line means in time it's going to
update the screen at that point. Let's bring that back up to 60 for a minute.
So then we've got our set timeout, right, the old school animation approach, and that's
at 16. So here's the thing. There is our set timeout.
It fires, then it fires again, exactly 16 milliseconds later. And then again, so on
and so forth. Now, see the relationship between the timer
firing and the blue line? It's moving. And in fact, you see this arrow, which is showing
when whatever you did in that set timeout, the arrow draws a line to where the monitor
-- which refresh of that monitor is going to pick up your picture. So if each one of
those timeouts moves something to the left by one pixel, you will get a picture showing
up when the vsync line runs. Now, here's the problem. 16 into 60-hertz
does not equally go, right? 16 milliseconds and 16.6 are the two numbers that really -- 16.6
repeating are your two magic numbers, and that's only for a 60-hertz display. The problem
here -- there are really two. The first problem is that as you go on in time -- I'm just scrolling
to the right to show you more and more of these patterns. Sometimes you get a situation
where the same 16-millisecond time lap fires twice in the same VBlank interval, these two
lines. So this red X'd one never made it on the screen. So that's going to be an apparent
jank. You won't see that, so all of a sudden just for one fraction of a second you'll see
-- you'll feel like, oh, something's wrong. The other problem is that these lines are
varying in angle. Now, what that means is if you're moving something at a constant stream,
trying to move something smoothly across the screen, the steeper the line, the more the
velocity, the apparent velocity of your image will match what you're computing. But the
more slanted the line, the more it will appear to your eyes to slow down. So in this case
if I just moved something slowly across the screen, you would at a very, very subtle level
feel like the object was slowing down and then suddenly would skip and then it would
slow down, but it would be very, very minor. So this is not buttery smooth.
>>Tom Wiltzius: No. We even call it sometimes an uncanny value of smoothness. You may be
thinking in a 60-hertz setup does it really matter so much if I drop one frame in 50,
like if I'm going to drop the 50th frame? And the answer is yes, it does. You'll notice
these things, but it's more, as Nat is saying, a feel. So this is the kind of thing that
we can become very attuned to, and if you start to notice it you're going to see these
tiny little hitches. >>Nat Duca: And tweaking the number doesn't
make it better. You can turn it to 10, it just drops more frames. You're gonna get more
jank. If you turn it up to 17 because, hey, 17 is closer to 16.6, you'll get the same
thing, it's just gonna longer for that to happen.
And if you want to pass 16.6, the browser will drop that decimal point on the floor
and give you 16 anyway. So don't use set timeout. We're sort of beating
this point because there's been discussion in the world about whether this is a good
thing. So what should you do? Well, stay on time
every time by using requestAnimationFrame. It's a drop in replacement for set timeout.
The quality of the implementation of requestAnimationFrame is not 100% on all browsers right now. Some
browsers are trying to get little nitty-gritty corner cases just perfect, but unlike set
timeout, which is sort of permanently messed up, we have hope as Chrome or Mozilla or any
of these to make it better. So please do use it.
And the reason is because then when you're on a high-speed monitor or a low-powered screen,
your rAF is always on time. >>Tom Wiltzius: This is supported in all the
major browsers at this point. This is very much the direction everyone is going.
>>Nat Duca: But this is not the only thing that you need to do to be jank-free because
otherwise we could all leave and go get drunk or something.
So anyway, we can't do that, we have to also keep in budget. So let's talk about budget.
So what I have here is a requestAnimationFrame script that's just rotating this thing, right?
Pretty straightforward. And what I've also done is I've graphed, just with the canvas,
the time that I'm getting between these requestAnimationFrames. And you can see they're nice and regular.
There's a good line here. Now, this big jank button, right, it's a big
red button, don't press it, but if you press it, it puts it to sleep, just puts V8 to sleep
for awhile and what happens is there are two things to watch. You will see the spike on
the graph, right? But also look at the actual spinner. See how it's sort of jumping? So
this isn't terribly surprising, but this visualization of seeing this graph spike is incredibly useful
and it's so useful that we've actually built it right into devtools.
So a new feature announcement, or you've seen it maybe, this is Chrome devtools frame mode
and it's recording now and what we're seeing is that same graph of the time between frames
live, plotted up top, so you see a long frame. So let's try it out. Let's go here. I'm gonna
start a new recording. I'm going to press the big jank button.
Go back. So now that nice, beautiful, flat thing that we saw now has these nasty things
in it. And your eye should be drawn to that because that's jank.
So if I zoom in on this, right, if I click on one of these, one of the cool things you're
seeing is these are good frames. These individual columns are nice, smooth 16-millisecond frames.
16, 17, it will be a little bit noisy. But this one -- that one is right out.
Tom, is a 100-millisecond frame smooth? >>Tom Wiltzius: Nope.
>>Nat Duca: He's good. He's a good PM. So this is the jank that we introduced. And
in fact, devtools is awesome. We can go to here, see that big timer-fired event and see
that that's the big jank button. Now, it's not just about avoiding the big
timeouts in your code, like you could just write a memo and say "Don't sleep for 100
milliseconds," okay, now your Web page is jank-free, but not quite.
So the other part of this puzzle is sticking within your budget. So I've got two buttons
here, this early button. And as you can see, there's a little bit of noise, but that's
not me clicking the button. I'm pressing this button really hard and the frame graph is
pretty stable, right? And then I'm going to do the same thing, and
I have this eight milliseconds late thing, and you can see we're getting regular jumps.
Now, let's go back to the recording. I had a recording going.
So here are the ones when I pressed early. Okay? See how the line here didn't go up?
What this is saying to me is that I used some time during my frame to do JavaScript, but
I didn't push out my frame. Now, let's look at this down in the bottom
bin. So if I scroll down I have to sort of find it.
The recording is a little long, so bear with me. There it is.
So here's our eight-millisecond fired call. And we fit it in between these two frames.
See how it just fit right in? So because it just fit right in, it didn't
push out the frame. But if I go over here and look at this one -- so there's one of
those timers that actually fired. And you can -- even without zooming in too far on
it, you can see that basically we started too late and so we pushed out the frame, and
this frame ran long. This frame is 21 milliseconds, right, instead of the 16.
So this would have janked. And in fact, if you sit there in these slides and really pound
on the eight milliseconds late button, just hitting it, you will start seeing the spinner
feel a little bit janky. So the rule here is you've got 16 milliseconds
to do everything, including all this stuff that Chrome needs to do to put the picture
on the screen. If you're going to do work, you've got to
stay in that budget and you've got to measure it in order to verify that you're staying
in the budget. So that's a nice toy example. It's one type
of example, but what do we do in the Web browser most of the time? We scroll. Almost all of
my Web browsing time is scrolling. So you can get janked there, too, and in fact
we showed it once. Here's a toy example Number 2 of jank scrolling.
So this code moves these divs around in an onscroll handler.
Is it's a pretty straightforward example. It's not exactly the prettiest thing in the
world, but we want to show you two things. First I want to make you very, very comfortable
with when you see this kind of pattern, just pop into the timeline and take a recording.
So let's do that. Up and down, we're having some fun here. Hopefully we're having some
fun. There it is. So here are some frames. So the
first thing that should stand out to you is look at the size of these things.
Again, back to jank expert. Are these fast? >>Tom Wiltzius: Only on a five-hertz screen.
>>Nat Duca: These are long frames. This is not okay. So we need to make this okayer.
Technical term alert, okayer. So what I'm seeing here between these two
lines, just pick any pair of lines, I'm seeing some green, which is painting, and I'm seeing
some event. If I expand this out you see just tons and
tons of stuff happening in this event. So what I think when I see this is I go, let's
hit this. This is pretty obvious or maybe it's obvious.
So when we pop into the source code for this, what the Chrome devtools is pointing us at
is this line. So what this is doing is it's trying to pull
up -- the test is just trying to pull up the scrolltop in order to then use it in a formula.
Now, one of the key parts of most Web browsers is that when you ask for layout information
or style, and scrolltop is part of that, it has to recalculate the world essentially or
a lot of the world. And in this case that means figuring out all
the div positions and everything and doing a big think, and then it will give you back
the scrolltop. Now, then we take the value that we've computed
and we shove it into this left position of our item, which goes and tells the browser,
"Hey, the world has changed again. If you get asked about the world's state again, recompute
again." So what's happening here is that we compute
style, we dirty style, we go around the loop again and we do this over and over and over
again. And this is why we're seeing so many purple entries in the timeline. Of course,
this being the demo I have made that behind a check box, right?
So in theory this should be faster now, right, but don't believe it. Trace it or record it.
So I've got a recording going and we're going to scroll again.
Oh, happy day, it's gone. But hey, Tom, is that fast yet?
>>Tom Wiltzius: Still not fast enough. >>Nat Duca: It's not smooth yet. I need a
light that's are we smooth yet? So our paint is a problem and we've got to hit this too.
So painting, what's painting? So painting is the part where we take the
styles that you've given us and we do the drawing. So Line 2, fill, draw image, do a
blur. All of that stuff, and it takes time. So when you see big paintings, start looking
at things that could be costly. So when I look at this doc and I look in the elements
inspector -- the only thing up here really is a bunch of images, so it's a pretty easy
case. But we look at these images and we've just
got tons of styles on them. We've got, you know, background image, we've got a box shadow,
you know. Hmm, let's remove that. So I've got a heavy
painting class this is all in. So if I toggle that off like that and we hit record again,
this should be better. And in fact, because of a bug in devtools
it's not completely smooth, but if you look at the actual costs, remember our paint time
was -- what was it, like 40 something? So it's gone from 40 something to about four
milliseconds. So definitely those CSS files that I toggled off are to blame. And in fact,
when devtools is off this is nice and smooth. So we busted some jank in some synthetic demos,
kind of cool, but in general what we're trying to teach you is keep your eye open for costly
things, long frames. Anything bigger than 16 is right at you've got to bust it.
Garbage collection can do this to you, just manipulating lots of DOM, heavy script obviously.
Timers are particularly something you have to be careful of. Be aware of a timer that
comes in just about at the end of the frame because it can push out that frame. Same goes
for XHR. Use the devtools features in order to bust this stuff up and make your website
smoother. But there's more and Tom is going to tell
you about it. >>Tom Wiltzius: Thanks, Nat.
So Nat's been talking a lot about sort of what JavaScript, et cetera, can get in the
way of your animations running smoothly. And there's sort of an implied limitation to what
the browser can do in everything that Nat's just said. And that's that why can't some
of this happen at the same time? It doesn't really seem like there should be anything
related between handling some XHR callback in JavaScript and the browser painting, like
you might not be actually touching the DOM at all.
But unfortunately for better or worse, the way browsers are today it's a pretty good
assumption that everything happening in a given tab happens on one thread; i.e., that
XHR callback can block painting, right? Also, that XHR callback could block your requestAnimationFrame
from running. So if you remember, we've got this requestAnimationFrame
that's ticking at the vsync heartbeat, but it can't run if some heavy block of JavaScript
is running. This is a pretty severe limitation, right, because this means that you can't really
be running in animation at the time when you've got to do more than 16 milliseconds of JavaScript
work at a time. Either you have to break up your JavaScript
into really little bite-sized increments and handle them in the rAF callback or you can
use CSS animation. CSS animation is one of the exceptions to
everything happens in one thread rule. We brought to Chrome for Android first, so we're
going to do a demo Android in a second, but pretty soon this is going to be everywhere,
including on desktop Chrome. So let's switch to the demo here.
I'm going to turn on the projector over on the left, that's going to open up the source
on my right. So if I look at this simple, simple demo, this should look familiar, this
is the same thing that we saw earlier, and what Nat was showing earlier as this logo
spun around was driven by requestAnimationFrame. This is driven by CSS animation. You can see
that I mention this is only on Chrome for Android now, so for comparison's sake, if
Nat hits the sleep button, you can see that little bit of jank happening, right? Like
that little hitch in the animation that's the kind of thing that you want to be attuned
to. Whereas if I hit that same button on this, JavaScript still just spins for 180 milliseconds,
but the animation is smooth, right? This is huge. This is a big deal because it means
that you can run arbitrary JavaScript and the CSS animations are all going to run.
It's kind of like the easy mode of getting your animations to run smoothly, because you
just need to define an animation in CSS, which is fairly natural for most Web authors anyway,
then let Chrome do the rest. So this applies to both CSS transitions and
CSS key frame animations and like requestAnimationFrame you get some stuff for free. You get a lot
of benefits. You get better time, smoother looking animations, which is what we just
showed you. You also get better battery life, because
we get pause animations that are in background tabs. You get more graceful degradation because
if there are a lot of things animating on the screen, we can drop the browser's refresh
rate to 30-hertz instead of 60, for instance and keep it regular, rather than almost making
it 60 but missing frames every once in a while. Because for all of the reasons that we were
talking about earlier, missing that frame every once in a while is what your eye notices.
Right? So it's much better to be very, very regular,
but a bit slower, than it is to be variable and almost good enough. And this is the kind
of thing that the browser can handle for you. CSS animations are particularly good if you
are doing some sort of continuous animation like this silly Chrome logo spinning, if you've
got some logo like that, and you want to be doing anything on your page, like all of your
social widgets are firing timers all of the time, for instance, this is going to get in
the way of something like the requestAnimationFrame, driven animation, but it will not get in the
way of the CSS animation. It's also good for UI substitution effects,
so you can imagine whatever GML wants to sort of nicely animate the opening of their compose
window, they can do that with CSS animations, and it's much easier to do all of the heavy
lifting in the background of building up document fragments and doing DOM manipulation and parsing
the email text. All of the stuff that you have got to do to make your app run that you
don't want to have to think about in the same way that you are thinking about the animation
running. >>Nat Duca: Yeah. So we can't underscore this
enough. CSS animation is your get out of jail free card. When you have something, you can't
keep it to your 16 millisecond budget, you know, break out of that 16 millisecond jail
temporarily by throwing up a nice animation. >>Tom Wiltzius: Yeah, that's right. I also
want to -- before we go further, I should note that we talk a lot about 16 milliseconds
because that's about right. But all of this stuff about browser and screen refresh rates
still apply and I want to point out that just because you are within budget on your computer,
doesn't necessarily mean that you're going to be within budget on most people's computers
which are probably slower than your computers and doesn't mean that you're going to be within
budget on phone and tablets, and all of this stuff. All of this is very, very machine dependent.
Right? So you need to be diligent about doing the kind of measurements that we're talking
about throughout this talk to make sure that you're actually comfortably within budget
and can even withstand some variation like machine speed. So -- so now we're going to
go back to the demo we opened with. And we're going to try to fix this up. We're going to
sort of show you the process that we went through to speed up this page. On this projector's
resolution, the results aren't quite as dramatic, but you should still be able to see them,
especially if, as imploring you use devtools and actually like really note the times. I'm
going to pop up devtools here and I'm going to look around and I'm going to take a timeline
recording of this page that we say scrolls jangly. If I zoom in on some of those frames,
what do I see? I see big swaths of green, right? I see all of this paint time, which
is completely blowing the frame budget. These frames are like 45 plus milliseconds long
and they are dominated, I mean they are not dominated, the only thing going on is painting,
right? So before we were talking about JavaScript getting in the way sort of complicated interaction
between the browser painting and JavaScript running and style recalculation. None of that
is going on here. This is a static Web page, not complicated in the slightest. It still
scrolls really slowly. It scrolls slowly on this like fancy MacBook Pro. You can imagine
how well this scrolls on most people's computers which are not nearly as fast, right? So what
do we do? How do you diagnose those big, pretty, opaque big green paint blocks. When you are
diagnosing a long paint time, there are a few basic questions that you want to start
with. What element was slow or what element is causing you to be slow and what styles
are causing you to be slow? The way we answer the first question is that we do this really
dumb thing where we just turn off parts of the DOM. Right? We just get rid of elements
and say did getting rid of this element improve my paint times?
Maybe we decide we don't need that or we're going to do some sort of visual reengineering,
so it's not as big of a problem, et cetera. So we can start with something like that here.
Again, I'm going to switch to devtools, pop open the elements view, and I'm going to start
just looking for things to turn off. So I'm going to start with trying to turn off this
header, because I'm sort of suspicious of that. It's on the screen all the time. And
I'm just going to flip this to display none. This feels a little smoother to my finger
on the track pad, but it's hard to tell that from the audience. So again, be diligent,
take a recording. We switch back to timeline, we take a recording. Did we get better? Ah,
we got a little bit better. There were some that were above 45 seconds before, so I maybe
would count this a win, but it's not that significant, right? Plus there's a down side
here. I just got rid of the header. This is like pretty integral to my site, right?
[ Laughter ] >>Nat Duca: You can do it, you can go push
this, right? Sometimes that sort of a thing will be a real hit. It's not unsurprising
that we'll see websites that just lose 90% of their speed to one element. But in this
case, it's sort of marginal and it's kind of cool. Like I like that orange thing.
>>Tom Wiltzius: Right. >>Nat Duca: So we should keep it, right?
>>Tom Wiltzius: Right. So we're going to try not to make our UI designers, et cetera, angry
by telling them that their layout is too complicated. And instead we're going to move on to the
second question, which is, well, we're stuck painting everything that we're going to paint
and we're not going to worry about why it's being painted. Instead we're just going to
say what made this take so long? Like given that we can't change it.
The answer is always going to be CSS styles, right? CSS styles define what the page looks
like, it defines what an element looks like, it also defines how an element renders, right?
So when we tell an element to go draw itself, we being like WebKit, right, the amount of
time that that takes is highly variable depending on CSS styles. We wish it was the case that
all CSS styles sort of took equal cost to paint because it would make --
>>Nat Duca: I want a pony as well. >>Tom Wiltzius: Yeah, yeah. It would make
performance optimization much easier, but that's just not true. But so as much as Nat
said earlier, sometimes one element can really slow you down. Similarly sometimes just one
or two styles or like the intersection of a couple can really, really kill you when
it comes to paint times. So we're going to start doing the same dumb
trick. Right? We're just going to start turning stuff off and seeing if we can identify a
couple of things that are really causing us pain.
So again I'm going to flip open devtools, go to the elements view and I'm going to start
poking around. The first thing that I'm going to look at is maybe this background. It's
on a lot of the screen. Like the reason I'm choosing this is because it looks kind of
complicated, especially if I inspect it here. Oh, there's all of this like 20 lines of CSS
declaration for this thing. And it's all over the place. So I'm assuming maybe it's going
to take some time. >>Nat Duca: Even more amusingly on your projectors
it's showing up as gray. But when you look at it here, it's got this nice little checker-boardy
thing and it's all gorgeous and textured. >>Tom Wiltzius: Yeah, I apologize.
>>Nat Duca: And -- we're not going to see it, but maybe we're paying a lot for that,
all of that CSS. >>Tom Wiltzius: Right. So we're going to go
back to the timeline view again, we're going to take a recording, we're going to scroll
down, we're going to see what changed. Huh. A lot changed, right?
So now I've turned off that background and my frame times are now like in the high 20s.
>>Nat Duca: Tom, I think we classify that as a win.
>>Tom Wiltzius: Yeah, right. This is -- >>Nat Duca: Brush metal aside.
>>Tom Wiltzius: Right, but again there's this tradeoff between the visual effect that you've
achieved with the styles that you've used and what they are costing you. So -- and so
this process, this is only the beginning. What -- as we disable things -- and I'm going
to disable something else, too. As we disable things, like we're making the page look different.
So this is only the beginning. The next step is adding stuff back in or trying to achieve
the same visual effect via different styles that won't have the same sort of like pathologically
bad cost. So in this case, there's one more thing I
want to try. Thanks to Nat's demo earlier, I'm thinking maybe like box shadows are a
bad idea, so I'm going to turn off box shadows and maybe the backgrounds of these things,
too, for the same reason that I turned it off on the body. And looking at this, it feels
a lot smoother to my finger, but once again, I'm not going to trust it, I'm going to go
to timeline, take a recording. And like, wow, that just got way better, right?
There's one big one at the beginning. But almost all of these times like look how low
these are. We started off at like what was it?
>>Nat Duca: Janktastic. >>Tom Wiltzius: Like 50 milliseconds a frame.
>>Nat Duca: Some big number. >>Tom Wiltzius: Like i.e., five frames worth
in one frame and now these paint times they are like so small I'm having trouble clicking
on them. They are in the like few millisecond range, like one millisecond range. And again,
you are saying well, that's great but you changed the way the page looks, right? And
that's totally fair. >>Nat Duca: And I mean this is PM versus programmer,
so I'm going, I'm good with this, right? But this creates the right tension, right, between
design and technical that you can then use. >>Tom Wiltzius: And even at a technical level,
again, like you can then start building your way back up. Now that you've identified what's
causing your problems -- because again I didn't change that much here, right? I got rid of
the box shadow and the background, and that's it. And it's like that completely removed
the problem. So the question is how do I get that nice background gradient and how do I
get the nice drop shadow effect, but without all of the paint time cost. So I have this
version, oops, going to leave that open for later. I have this version that I fixed up
a little bit. And I did it exactly what I just showed you. I just started hunting around
for stuff. I went straight for the ones that I found eventually first in this -- in the
interest of time, so you didn't have to sit through anything too boring. But like you
can imagine how this process goes, right? And then I built it back up so that it visually
looks almost the same. I did this quickly so there are a few differences, but you can
imagine getting there, right? I just used images. I honestly just took screen shots
of the background and just like tiled them and that was way faster. So now you can see
that like this thing is zippy. And if I open up devtools, switch to timeline,
take a recording, like we're not at the one millisecond paint times that we were before,
but what are these costing, three milliseconds. >>Nat Duca: That's butter.
>>Tom Wiltzius: It's an order of magnitude faster than it was before and it looks the
same. Right? Like this is significant and all that I did was change two styles.
So the point is sometimes -- this was like a live website, right, like this is a live
website that Google made. [ Laughter ]
>>Tom Wiltzius: So -- so the point is there are plenty of times when just changing a few
little things is going to have a huge impact. But the hard part is how do you find those
things and that's what we're trying to impart today, right? We're trying to explain to you
the process and the tools that you can use to identify those bad, bad cases.
There is one more trick I pulled in between the good version and the bad version, which
I'm going to open back up again. And the way I found this trick, the way I
found this thing that was additionally slowing me down was through abouttracing. So devtools
is great and we recommend everyone start with devtools and the new features in timeline
are particularly compelling for this. But -- but if this is not enough for you, you
can get a lot closer to the middle by using abouttracing, which is a special tab in Chrome.
It's what we use to debug performance problems in the Web browser. And it can be really useful
for you if timeline isn't enough for you or if you are just stuck. And it will show you
a lot of stuff that's happening inside of the browser. It exposes Chrome's multi-process
model. It is a lot more complicated and not nearly as user friendly, but there is some
documentation that the two of us wrote up, we put it up on the Chromium dev site so you
can check that out from there. The trick that I discovered for this particular
page using abouttracing is something that doesn't show up inside of devtools right now,
and that's image decode costs -- so as I mentioned earlier, that green paint block, that we see
in the devtools timeline, today it's totally opaque, right?
You don't get any granularity until like what is the Web browser doing?
We're working on that. Those of you who saw Pavel's talk before with Sam, you guys know
that there is some good stuff coming from devtools that's going to expose more detailed
information. But in the meantime, like that wasn't obvious to me from devtools, but I
saw these long JPEG like decodes and resizes --
>>Nat Duca: What happens is that he'll show you the trick in a minute or maybe you can
bring up the bit. You would scroll, it felt really good, but the first time you loaded
it, just the first time, every once in a while you would see something, like what in the
heck was that, felt a little janky, right? It was in the uncanny valley territory. This
page started off as really just terrible. Right?
But there's still this uncanny valley and it was showing up as long paints, but you
couldn't tell why. So that's where you jump into -- if you care, you jump into tracing
to figure that last bit out. >>Tom Wiltzius: Yeah. And so in this case,
again, there were some JPEG decodes that were showing up, these can take upwards of like
40 to 60 milliseconds even on this fast computer. This is huge, right, because again that happens
within a frame because the Web browser is not doing anything else while it's decoding
that image at least in the renderer, right? Which means you just missed five frames, like
you just stalled, you are done. And this is bad.
So how do you avoid this? Well, in this case the reason that these scales were happening
was because the images weren't sized at the resolution that they were being displayed.
Right? So devtools will tell you this, it just doesn't show up as a component of the
paint time. So if you moused over this image in devtools, you will see that it's being
displayed at 300 by 300 pixels, but in fact it's a 512 by 512 pixel image. Again, like
that JPEG scale probably doesn't seem like a big deal, but it starts to become a big
deal when you start thinking about things on the order of milliseconds, right? Because
a 40-millisecond image resizing operation actually becomes quite painful. So from the
good version to the bad version that I was showing earlier, in addition to making those
two style changes, I also resized all the images so that they were displaying natively.
This is a simple trick any of you can pull because this has no visual impact, right?
This is just a perf point -- >>Nat Duca: But it will cause jank. Most websites,
this is a really common one, so go -- go to your websites now.
>>Tom Wiltzius: So this is the kind of thing --
>>Nat Duca: Fix it, okay? >>Tom Wiltzius: The point here, lest Nat get
too emphatic, the point here is not here are some magic bullets to go make your websites
faster. The point is the process, right? This is all
about the tools that you can use and the techniques that you can follow in order to figure out
what's slowing down your site. Browsers evolve really fast. And like -- to the people who
are like trying to evolve the browser really fast --
>>Nat Duca: To blame. >>Tom Wiltzius: Right. So all of the specifics
of what we're talking about here, the drop shadows, the background gradients, the image
resizing, like we are actually working actively working on making all of this faster, so hopefully
in six months they aren't going to be a problem. >>Nat Duca: But then there will be another
style or another new hotness and that one will be tickling the corner case in the browser
and it will make the browser sneeze or it will be fast in IE or fast in Chrome.
>>Tom Wiltzius: Right. >>Nat Duca: It's this wild world out there.
>>Tom Wiltzius: Browser variation, also huge, right? Like, as we care more and more about
performance on the Web, like it starts to become a problem that like different browsers
do things slightly differently, et cetera, et cetera.
So the point is use the tools. Like start to train your eye to notice jank. Follow the
architectural best practices that we have laid out, because these are true across browsers
and will be true across time, too. Use requestAnimationFrame, use CSS animation, make sure you don't have
like one-second long parsing JavaScript operation going on.
>>Nat Duca: Rendering. >>Tom Wiltzius: Right.
I mean, like kick stuff to worker threads, right, or like break stuff into queues and
yields, right, like anything that you can do to like not clog the main thread with all
of the other crap your other applications are doing is good, right? But again, the specifics
are all going to change. So once you start to notice Jank, you're going
to see it everywhere, and hopefully you've got a passion for making things faster, you
want to make your site faster, et cetera, et cetera, so you're going to use the devtools
timeline, you're going to use about tracing, you're going to do this funny trick we did
where we just bisecting down what's slow by turning things off and re-enabling them, and
with that, hopefully you'll be better equipped than you were before to make this stuff fast.
If you're hungry for more, these slides and other resources are off of Jankfree.com, and
we are actually going to be -- we're going to take questions in a couple of minutes,
but we're also going to be at office hours in the Chrome area, just around the corner,
I think, right after this talk. We like doing this. If you have a site that's janky, and
you want to come by, like, we'll take a crack at speeding it up. We'd love to do that, like,
for an audience, too, so if anyone wants to come by and try that, we'll give it a shot,
and with that, I think we're going to say thanks, and take questions...
[ Applause ] Anyone got anything?
>>> I have one. >>Tom Wiltzius: Yeah, please.
>>> The CSS animation transition threading, will that or does that apply to Web view?
>>Nat Duca: Talking about Android Webview? So, you know, the Web moves really fast and
there are like a zillion different ports, and CSS spec in general, the animation spec,
it allows this, so it's good to design for even if it's not working today, it will start
working everywhere within the next, you know --
>>Tom Wiltzius: Yeah. >>> Nat Duca: But this is very much our plan.
The next soon; that's a unit of time. >>Tom Wiltzius: Yeah, and like there is going to
be other stuff like this, like basically we're trying to kind of move away from the model
of everything happens on the single thread in the renderer, right, and this is kind of
the beginning of that, but there will be more things like this as well, so, yeah -- please,
yeah. >>> So one of the use cases between mobile
browsers and desktop browsers is that mobile browsers tend to zoom a lot, right? So what
can you say about that and handling that, like your image case, it's useless if it's
only 300 x 300 if you're actually zooming in, you cant actually see that extra detail.
>>Tom Wiltzius: Uh-huh, yeah, so I would say -- you might also say like for high resolution
screens like I want that image to be able to be resized at a larger resolution, right?
Like there are a lot of cases where you're going to make tradeoffs between like quality
essentially and performance, right, like these things are almost always going to be in tension.
I think in that case, you probably are going to have to decide where on that --
>>Nat Duca: You're totally right. Mobile browsers are the forefront of awesomeness in terms
of like stuff behind the scenes. >>Tom Wiltzius: Like PERF winds because the
part -- >>Nat Duca: So that will bite you in the case
of a pinch zoom, but mobile browsers have -- especially Chrome Android has some very
severe magic so that you wouldn't even notice this in the first place during a pinch zoom.
We'll probably blog about the magic at some point, but essentially, you know, when you
use Chrome Android, you can time it, you can pinch zoom, and you'll actually see that in
that case you won't get a jank and so then you won't care. That's the best answer I can
give you. >>Tom Wiltzius: We can talk more about that
at office hours. The full -- the full sort of magic explanation is really complicated.
We'll be happy to talk about it more. >>Nat Duca: Measure.
>>Tom Wiltzius: Yeah. >>> Great presentation. You hinted at some
more tools that you were going to be adding to the frame view and the profiler, can you
give us some hints as in updates on what those are going to be?
>>Nat Duca: Well, how about you tell us what you want.
>>> I would love to be able to see the element that takes the longest and just be able to
go right to it. >>Tom Wiltzius: Right, yeah. That sounds cool.
>>Nat Duca: We should totally do that. >>Tom Wiltzius: Should tell that to Pavel.
>>Nat Duca: We're on the team and we're pushing-- >>Tom Wiltzius: We bug Pavel who is standing
in the back, and just talk about devtools all the time for like -- yeah, we totally
want things like this. >>> Maybe line numbers and like function -- or
functions that take the longest time which is where you're spending the most time instead
of JavaScript functions would be awesome. >>Nat Duca: So my hope, and my boss -- my
actual boss is in this room, so I hope to be able to stand here next year and instead
of having to say, oh, look at this big green thing, and then spend -- how long did we spend,
like 20 minutes trying to explain what was slow about the -- I'll push a button and it
will be like that one, that would be great. Whether we can get there, yeah, TBD, but that
would be a nice thing. >>Tom Wiltzius: Definitely -- definitely granularity
in like paint cost is something we're looking at. I think like some of the -- some of the
JavaScript stuff may be better served by improving the profiler than improving timeline, right,
but, like it's a point well taken. >>> Great, thanks again.
>>Nat Duca: Feel free to file new.crbug.com, because we really do read all that stuff,
and so like crazy ideas are awesome, because we can tell you you're crazy, but then we'll
listen, and make a note, we'll try to do it. >>> So this trace and recording, they really
slow down the Web page? So if I disable that, will the Web page work faster?
>>Tom Wiltzius: In some cases, yeah, like so you even saw like Nat at some point during
his demo, was like, yeah, this still looks -- even though I've disabled my heavy onscroll
handler and my costly CSS styles, it's still a little janky, and as soon as you close devtools,
it got a lot smoother, so there is some instrumentation overhead especially with devtools. That's
going to be fixed. Pavel is going to fix that. >>Nat Duca: So the high level is -- we won't
-- we're trying not build things that have those corners. Right?
When you're using -- this is bleeding edge, this stuff that we showed today, it's the
-- >>Tom Wiltzius: Like this is yesterday's Canary.
>>Nat Duca: This is like the Canary. By the time this is stable, it will be totally awesome,
and you may hit a corner case, but it's very, very unlikely. Does that answer your question?
>>Tom Wiltzius: And there should be -- there should be like -- there is sufficient granularity
in the timeline already that like -- we saw some problems where like there's -- there's
some instrumentation overhead and you don't get the frame times you want, but we still
know pretty well how long the paints take, for instance, and that kind of thing shouldn't
be as dramatically affected by tool overhead. >>> I still cannot use it for stats.
>>Nat Duca: What's that? >>> I still cannot use it for stats?
>>Tom Wiltzius: You can't maybe use it for, in that case, like frame time stats, but you
can use it for like -- if you cut your paint time in half, you have cut your paint time
in half. >>> I cannot save my page when they're like
60 frames per second. >>Nat Duca: Yeah, you can.
>>Tom Wiltzius: You can see that within a frame you didn't take -- like your page only
consumed whatever, like ten milliseconds worth of stuff, right, and then if you close devtools
and it's fast and you're good, right. >>> But if it's recording then --
>>Nat Duca: It's not that -- it's not that heavy and it's not on that process, especially
like -- yes, on an Android you might get a slight, slight penalty, but to be totally
honest, by the time we're done, it should be maybe one or two percent overhead, which
one or two percent overhead on 16 milliseconds is nonzero, but it's not so much that I think
it will perturb the average Web page enough that you'll notice, okay?
>>> Yeah, thanks. >>> Awesome presentation, awesome tool, totally
stoked that we have it. My question is now we have high DPI devices, not necessarily
Chrome, I mean -- >>Tom Wiltzius: Yeah, sure.
>>> Like the iPhone. And so using background size, you need to use background size to take
these huge images so that they're high DPI in your example -- so is there any way to
measure it on -- like I know your tools only work for Chrome, but how can we force it into
a high DPI without buying the new MacBook Pro that's higher DPI?
>>Nat Duca: So probably a question for Pavel, who you could turn around and walk to --
>>Tom Wiltzius: Well, I mean, I can give you some starter hints. One, there's a way to
turn, if you've got a non-high resolution MacBook, you can flip it, if you install some
tools, you can flip it into like a fake high DPI mode, won't be as accurate because you
can't get the whole thing so you can't get like the cost of full page repaints, for instance,
because it's only a quarter of the screen, but at least you can see how things will look
and you can get a sense for some of the timing which is a start. There are ways to avoid
like using JavaScript and stuff, you can only load like -- I think this was the first part
of your question, like you can only load high resolution assets if you need them.
You can use media queries for instance, so that will sort of avoid unnecessarily taking
the hits, and as for profiling what the hit is like, you can kind of again fake it, but
to really test, yeah, you probably got to buy a new computer.
>>Nat Duca: I do have one like ignoring the image discussion. There is one caveat for
all of you, which is high DPI means that your paint times double, not exactly, but that's
your risk, right? You're painting twice -- well, four times as much, look at me doing math.
>>> Sometimes it's quadruple. >>Nat Duca: Yeah, no, this is me doing math
in a really funny way. Four is the number. I shouldn't work for Google, should I?
>>Tom Wiltzius: High DPI -- the point is high DPI stuff is going to have significant --
>>Nat Duca: So you gotta keep your base loads. So if you're like on this MacBook Pro, this
is like a two-year-old MacBook, and it's really chugging and it's hitting like fifteen millisecond
paints, then you're really, really -- this is not going to work on a good -- on one of
the new ones because the paint is only going to go up. It might be a slightly faster Intel
CPU -- >>Tom Wiltzius: About four times faster.
>>Nat Duca: -- but you got to just -- you gotta keep it small, right, and give yourself
head room for the higher end devices. And the lower end.
>>Tom Wiltzius: Yeah, and I mentioned this -- I mentioned this a little like really briefly
as an aside during the presentation, but I do want to put a plug in, too, for like most
of you are Web developers, most of you have very fast, very fancy computer, like think
about the computers your users have because they are not MacBook Pros, right? And like
we collect stats, like anonymous stats about like the common sort of like system configurations
of Chrome users, and like I'll tell you, like, the average Chrome user has like a really
crappy three-year-old laptop, right? And like this is -- this is what the internet population
is, so for some things this doesn't matter, but for like really sensitive performance
stuff, like I'm trying to make a 16 millisecond paint -- frame budget, it's huge, right?
So think about that. Like I wouldn't even recommend maybe testing on not your development
machine for instance, but that's just me. >>> Literally exactly on that point, and maybe
this for Pavel. >>Tom Wiltzius: He's not a plant.
>>> Can you guys just add a -- >>Nat Duca: Slow me down --
>>> Yeah, exactly. >>Tom Wiltzius: We talked about it. It's a
little hard to do super accurately. We've talked about like making it do something like,
ah, just like paint everything ten times, right? Because that way even small paint time
problems will be really (inaudible), I think we probably need more fine grained instrumentation
before that is going to be really useful. >>Nat Duca: That is geeky cool. We should
figure out how to make something with your intent to work.
>>Tom Wiltzius: It's a good idea. I think your intent is spot on.
>>Nat Duca: I think your intent is really key. You want to be able to, from your computer,
understand the performance of this content somewhere else, and that's hard right now,
so maybe we should figure out maybe as a community how to do better there.
>>> Yeah, I mean, you know, Pavel was saying in the previous session, you know, the devtools,
the realtime and all that kind of stuff, you know, having to right now have a bunch of
VMs or a bunch of like Chrome books, and these kind of things, it just doesn't really scale,
versus I have a slider in my devtools, that I can be like okay, I want to run at 20%,
see how this feels, oh, I can have the -- all the same timelines, all these kinds of things,
now the ability to improve my performance on, you know, substandard machines dramatically
improves. >>Nat Duca: Great point. I totally hear you.
Thank you. >>Tom Wiltzius: Yeah.
>>> I have two questions. First one was so an example you had with like drop shadow and
(indiscernible) HTML5, you said you replaced them with images to improve the performance,
is that right? >>> Yeah, but that is obviously not ideal from like a Web development.
>>Tom Wiltzius: Like the -- like the -- like the spec people are going to kill me, right,
like I'm just like -- I'm just saying don't use any of this, it's not fast enough.
>>> Right, right, so like I mean are there other techniques we can use now or is there
something browsers could do to optimize that more? Because like I would assume the browsers
would pre-render shadows and cache them and not have to re-render them all the time.
>>Tom Wiltzius: Yeah. No, there are things like that that we're doing, and this is why
we ended like with don't listen to the specifics because they're going to change, the way -- like
there are even bigger changes than that afoot in like Chrome's rendering pipeline, to some
extent, and there's going to be caching at like a much higher level, where we like stuff
on the GPU, so we don't need to repaint that anymore, and like, yeah, that's all going
to be happening, so like it may end up being that the one-time cost of like rendering those
shadows, say, actually turns out to be pretty insignificant for you, and so I guess the
short answer is, yes, the browser is going to try to take care of this for you. I don't
-- I don't want you to sweat like drop shadow too much, like this was very much a demo that
was meant to show you, like, how to find something that is taking a disproportionate amount of
time and then dealing with it right now, right? But I absolutely agree that the browser should
be solving this problem, and we're trying. >>> And the other quick question is one of
your slides you mentioned something like performance.webkitnow, but I don't think you talked about it. I was
just curious what that was. >>Nat Duca: Yeah, we slipped that in there.
You've got a good eye. You can Google it. Date.now is how we've always measured time,
and something that we slipped out there, and it's going to be pretty much everywhere including
IE, is window.performance.now. There's this whole prefix game, right? But it gives you
time at a submicrosecond resolution, it gives you the fastest that your computer can give
you, so now you can timestamp individual functions even and get reasonably good numbers out of
it. Totally use it. We used it, but, you know, we didn't want to go into too much detail,
but it's a pretty cool addition to the platform. And it's very useful for things like this,
when you're thinking on like -- like -- >>> A millisecond, six percent error.
>>Tom Wiltzius: Exactly, correct, yeah, it ends up being very important to have submillisecond
precision and so we're finally bringing that to the browser which is good. We're actually
going to even change like out of -- for any of you who already knew about request animation
frame and think like, oh, this is all old hat, like we're actually changing the request
animation frame specs slightly to use the new high resolution timer, so like you get
a time stamp with the rAF callback and it used to be measured in milliseconds, since
EPOC now it's measured in whatever the high resolution timer is which is like since page
load, so if you were using it already, check your sites.
>>Nat Duca: Did you get the answer you're looking for?
>>> Yeah. >>Nat Duca: Great. Thank you.
>>> Actually part of my question so that you could get some metrics from the field, with
this kind of stuff. It's nice as a developer, but if the device diversity is so huge, especially
with the new GL stuff, because I'm trying to make UIs in GL now, and it's really cool
to beat the 60 fps one, but it's really terrible if you have to do it in FireFox as well and
all of these other things. And so my question to you is how do you see the 60 fps domain
with browser diversity, because you guys are optimizing in ways that you have to adapt
to to get that 60 fps, and everybody else is doing something.
>>> Well, actually, so in theory, let me game something out with you, and let's hear your
feedback. Like FireFox is actually like at this minute, the Mozilla team is adjusting
their rAF implementation to do a lot better. It used to be that their rAF implementation
didn't actually hit 60, and they're changing it to actually hit 60 as we speak, so good
content that does what we think the right thing is for the platform then drives the
browser vendors to optimize -- or to make things work correctly. All of this stuff is
so new that there's a lot of diversity in the correctness of the implementations. So
my theory, may be wrong, is that this will get a lot better in about a year as people
really catch up in their implementation quality of the spec. I think the spec's about right,
plus or minus some nasty details, but we need to really polish.
>>> Right. >>Nat Duca: Is that responsive to your question?
>>> You're optimizing, right, so you're profiling and optimizing, and that means that you get
case specific for browsers to try to make things faster. I'm just wondering how you
see that evolve? Is it going to stay within the spec or --
>>Tom Wiltzius: Yeah, I mean, I think at a meta level, like you're absolutely right,
that this is -- this is a problem for the ecosystem, right, like the potential for performance
profile divergence, amongst like the browser vendors is like potentially very serious,
right, and like we actually have probably a lot more in common with FireFox than we
do with say like IE, but like you want your stuff to work on IE too, and like it's implemented
very differently. I don't -- we don't have --
>>> Are you responding to the 60 fps thing? >>Tom Wiltzius: I use usually like super key
nonperformance now. There's super key nonperformance in spec compliance, and like they don't move
as fast as we do, because they don't want to drive things forward as quickly, but like
they're -- they -- they were very support of cross animation frame from the -- this
is -- >>Nat Duca: Let me be clear, at least to my
understanding, there are two -- there's a branch here, so there's the techniques like
request animation frame, and keeping within a budget. That applies to IE as well, especially
IE that have request animation frame which is I believe nine plus. Might be ten, but
I'm sorry, you always want to keep that 6, that is not a fact of a browser, that's a
fact of these stupid display thingies that we love. The place where there is browser-to-browser
divergence is which CSS effects get you in trouble or which DOM manipulations? Or to
a certain extent GLL, but that is usually just because of GPUs.
>>> I missed it. Is that going to go into IE at some point?
>>Tom Wiltzius: Ask them. >>Nat Duca: That's way above my pay grade.
>>> I mean, if we're optimizing we have to sort of look at what we're targeting, right?
>>Tom Wiltzius: Yeah, totally, I -- I mean, it is my sincere hope that IE adopts Web GL,
they're the only browser who hasn't so far, and I say this as the like the Chrome graphics
PM. Obviously that's what I want. >>> Well, same here but --
>>Tom Wiltzius: It is unclear what they're going to do in like the 3D on the Web space.
I think they will do something pretty soon is my suspicion, but what it is, they're pretty
quiet. I don't know. >>> Good stuff, guys.
>>Nat Duca: Yeah, feel free to reach out. >>Tom Wiltzius: We're happy to talk more about
that kind of thing afterwards. Any other questions? Otherwise we'll wrap up.
>>Nat Duca: Thank you, and we'll be out in the -- in the area where Chrome is if you
want to bring us over a slow website.