Tip:
Highlight text to annotate it
X
>> ANDREW BOWERS: So as you've seen, we've--these are just few of the ways that we've evolved the
development cycle in Google Web toolkit and the productivity side of the equation. So
first, we have to declare to view the UIBinder increasing the speed in which you can iterate
the plug-in for Eclipse error checking earlier on and also, you know, we can be a little
lazier by typing less code, and then third, the developer plug-in allowing that multi-browser
debugging during that development cycle. So, I think--I actually think I got the development
side of the presentation because I like demos and being able to show multi-browser debugging.
But if you've ever been stuck in the car with Bruce Johnson, you know that he's very fascinated
with optimizations. And so, luckily, you're all stuck with me tonight as well. So we're
going to spend--the next part we're going to talk about is the development time--excuse
me--deployment time, and the optimizations that go on with Google Web toolkit and performance,
making apps faster. So with that, I'd like to invite up Bruce Johnson, the co-creator
and tech lead of Google Web toolkit. >> JOHNSON: Thank you, Andrew. And now you're
stuck with me. Well, I'll try to make it interesting, anyway. Again, to reiterate back in terms
of this big picture diagram. Andrew showed you the development process, faster refresh
cycle; I'm going to be talking about what happens when it's actually time to think about
deploying your app and running compiler, and so on. So, it's really often the case that
people call GWT a compiler, but it is important to note that really the compiler is only one
small tool within the larger toolkit. As a matter of fact, one thing you haven't seen
of all the demos that you've been shown so far is you have not seen the compiler run.
What you saw again was the development mode. The whole point is to not have to run the
compiler. If you stay in development mode during most of your development cycle, most
of your time is spent making edits to your Java code and refreshing the browser. That's
a really productive way to work, and a slow compiler doesn't slow you down at all. But
at some point, it is time to start compiling into the JavaScript and seeing what it's like
to, you know, start to think about deploying your application. Well, I should mention too
that JavaScript that gets produced by the compiler is just a standard, stand alone static
JavaScript files that you can serve up over any HTTP web server. But anyway, at this point
when you compile we've added some things that are really interesting from a performance
perspective. So, if we move to the next slide, I'm going to drill down into that even more.
First to understand that the GWT compiler is not a simple Java to JavaScript source
transliterator. Okay? It's a whole program optimizing compiler, I say whole program because
it literally sees every single line of source code in your project when it goes to optimizing
compiler. Because it can see every line of code that means it can trace all the connections
between. It's all the dependencies, where methods are called and what fields are referenced
and so on. In that kind of environment, it can do really, really aggressive and effective
thorough optimizations to make sure that the JavaScript that is produced and as small and
as fast as possible. I'll walk you through the pipeline, at least the simplified version
of it in this diagram here. So starting at the left, the first thing the compiler does
is it prunes out dead code. The way it does that is it starts with the entry point, which
is the first method that runs when your web application can load, and it is able to see
all the methods that could be called transitively from that entry point methods. It can determine
that certain methods would never be called. In large libraries, that's often the case
that you only use a subset of the code, right. So, it trims all the methods that are not
called in your project and completely discards that code, it never runs up in your JavaScript.
But it's not just methods it's, you know, fields that never get read or if you'd declare
local variables or parameters that never get referenced, it trims those out as well. Even
entire classes, no matter how much code you write, if the classes never instantiated and
are never used, it goes away. It's kind of an interesting contrast to the way that you
normally think about JavaScript development where there's a library that you include on
the page, right, and it's got a certain size and that's just the price of entry. This works
exactly the opposite. You only pay for the code that you actually use, no matter how
large the set of libraries that you compile against, only the code that you actually need
is included. Okay, so that's dead code removal. Moving on to devirtualization, so what does
that mean? In large code bases of the sort that we're talking about tonight, you need
to use object-oriented design patterns and that involves multiple levels of abstraction,
class hierarchies and so on. Well, that's great from a maintainability standpoint and
a design standpoint. But those concepts, those abstractions have some runtime costs, but
not if you're using the GWT compiler, well because it can go through and tighten the
types of things. So you declare a variable as a shape but the compiler sees, it's ever
only assigned a circle object. So it tightens the type from shape to circle and therefore
methods that are called on that object are not polymorphic, they're actually known to
be calling a particular implementation of that method. And as a result, we can move
on to the next box which is inlining. Many of these methods typically getters and setters
or other small confrontational methods are small enough that it's actually very effective
to simply inline the bodies of those methods with the call sites. Sometimes that even means
the JavaScript is smaller because very small function bodies when you inline them, it saves
you the actual characters of the word function. Where you know, in JavaScript every character
that you include in your script actually costs you download time, right. So sometimes inline,
you can actually make the code smaller too, and of course it makes it faster. Then, once
you've inlined all these call sites, you end up with expressions like two plus two, it
really happens a lot, or a string concatenation were you're appending a string literal to
another string literal. In which case the compiler can do static expression evaluation.
So, if it sees two plus two for example, it simply replaces that with the literal four.
And you can easily see why that's a good thing, four is less JavaScript to download, it's
less operation that needs to be done at runtime. So it's just basically nothing but a total
win as far as you're concerned. And that's not all, as we moved through this pipeline
once, we've unlocked additional optimizations, so we go, start at the beginning again and
we go back to the pipeline. And at typical project, the large project like, again, like
the ones we're talking about tonight may go through this cycle seven to ten times, after
which there's just nothing else that you can improve from a logical standpoint, and it's
time to generate JavaScript. And of course, when we generate the JavaScript, we eke out
every little bit of size improvement that we can, so you have minified JavaScript which
means you don't have comments in the output, you don't have extraneous spaces, you can
even read the JavaScript spec which I do not advise. But if you read it, you'll se there's
things you can leave out semicolons in certain places and so on, and we try to do all of
that so that you don't download, your users don't download a single byte that they don't
have to. And then we can obfuscate the identifiers, shorten names, again smaller script, downloads
faster and actually connect to the faster [INDISTINCT]. So, that's what it's like to
be locked in the car with me. But, thank you for your patience, so we'll take a step back,
I'll be geekified for a second. And this is the one I want you to actually remember, the
compiler smushes the heck out of your code. So the diagram, the diagram shows on the left
the complete source for a java project that you can compile [INDISTINCT] 2 point font.
On the right side is the JavaScript code that was produced by the compiler, also 2 point
font. The main thing to remember is, it's okay for your java source to be bigger because
the compiler will make it smaller. And actually this has pretty big implications for how you
work to develop a large sophisticated application, right? You want to be able to write the java
code that you want, you've got a whole team working on this, you need design patterns,
you need to be able to have, you know, modular code, maintainable code, testable code. You
don't want to have to be sweating performance with every single line of code that you write.
And you can work that way with GWT, you can know that the compiler has your back because
it's going to take all that java source that you write and because it's going to take all
that Java source that you write and smush it down as small as they can go. Another exciting,
and Matt alluded to this earlier and GWT existing users have always been excited about this
as the team. When you have a GWT project and you upgrade to the new version, we add new
compiler optimizations every time. You simply upgrade, recompile and your application gets
smaller and faster. So, we've already talked to teams who have used the release candidate
of 2.0 and they've reported 3% of reduction and size all the way to 20% reductions and
even more in some cases. Again, you heard Matt say they got a 20% size reduction. So
if we're doing our job right, you never have to think about any of this stuff ever again
after tonight. You just write the code that you want and you can be sure the compiler
is going to optimize it well for you. But as you continue to build larger and larger
applications, you know, it just takes a lot of code, right? Lots of features, it means
lots of code. Even the best compiler optimizations can't make that free although we will try.
But you know, eventually the JavaScript gets big and the initial download starts take too
long and that's not what we want. We do not want users using web applications to feel
as if they are having to install something in order to install your application. Right,
these are web applications, you should click a hyperlink and they should start immediately.
So there's obviously some tension here. You want rich full-featured applications but you
want them to start immediately so what do you do. I'm happy to say that in GWT 2.0,
we have a solution to this. You can get incremental app downloads using a technology we call Developer
Guided Code Splitting. It's available in GWT 2.0. We think about it like watching a movie
online. You obviously don't want to have to download the entire movie before you can start
watching the first bit of it, right? You want the movie to start immediately and download
the rest as you go, that's the idea of behind code splitting. A real world example just
came from Google Wave who last October, got in touch with us to say, "Hey guys, you know,
we love GWT but you know, we have an awful lot of functionality planned for Wave." And
this is what our—the size of our initial download looks like as we continue developing.
Don't know if you can see this in the back of Y-axis has this curve starting to approach
one and a half megabytes of uncompressed JavaScript. Well, that starts to get to a size that is
really too large to download quickly and that would really harm the user experience and
that is no good. So, I admit I kind of laughed nervously as the tech lead, Adam Shook mentioned
something about having to ship Wave on a CD rom. And, which I use that joke every opportunity
I get because actually, it's kind of an interesting reminder that the world has really changed
in the last few years, right? When shipping software on a CD ROM is literally a joke,
anyway, this is how it works. You have the entry point method in your project which I
discussed earlier. That's the top of this tree, okay. The entry point method calls other
methods which in turn call yet other methods. It's not important that you read the names
of these methods, but I just wanted to make the point that it is shaped like a tree, in
other words like, sort of a triangle. Now, we can zoom out and the point is the size
of the initial download is proportional to the area of this triangle essentially. So
the more code that is reachable from your entry point, the bigger your initial download.
What we want to do is find portions of code within this triangle, sub-triangles if you
will, that we can chop out, that we can defer so that we don't have to load them immediately.
So, in this example, the triangle I'm showing you is the mail sample application. And I
think a good thing to chop out is that silly, about dialogue box that Andrew showed you
earlier. I mean, you know, it's nice to have it but, how often do you click on the about
dialogue box, right. Why would you make the initial download take longer just to have
this kind of low value feature at the (red)--it'd be better if you can defer the dialogue box
code until you actually have someone click on the about link. So, I'm going to show you
what that looks like in eclipse. All right. So, the first thing you do is you find the
place in the code that you think you'd like to do some chopping. So, in my case, it's
the spot at which we have an event handler here. Okay. This is one of those UI handler
base event handlers that Andrew showed you earlier. It's nice and succinct, and it's
really clear. That, if this method could be deferred then everything it depends on could
also be deferred. In other words, the compiler would have an opportunity to cleave out that
subtree that I showed you in the diagram. Really, a point of this demo is just to show
you how few lines of code it takes to pull that off. There's a new magic method in GWT
2.0 called runAsync. And you just turn--what was a method call into a callback. Okay. So,
what happens is, one of two things when this--what we call split point occurs. The necessary
additional code is fetched successfully in which case execution continues. All right.
That's--that was the original method or it is possible, that if the network has a problem
of some sort then, you know, the code might fail to work, in which case you want to do
some really world class error handling, and that's it. I'm done. I'm not even going to
show you the, the thing in action because the point is, it's exactly the same. It'll
feel exactly the same. But, if we go back to the slides, I'll show you what I did. That
smaller triangle, I dropped it out with, I guess, when you exclude braces and blank lines
in the sample code I showed you. that's maybe three or four lines of code. Three or four
lines of code, I reduced the startup by 13 percent, and I did that in about a minute.
So, now imagine what happened when we gave code splitting to the Wave team. Okay, which
we did, and moving on to the next slide. This is what happened to the startup size a few
weeks after we gave it to them. So, in several weeks, they were able to--in preparation for
the launch at IO this, earlier this year. They reduced their startup size by a factor
of seven. And so, went from 1400K uncompressed to 200K uncompressed. You actually serve this
JavaScript, of course, you compress it, right? So, 200K Gzip is about 80K which is about
the size of a typical graphic, you know, a jpeg that you would include into any old HTML
page without thinking twice about it. In other words, this is, you know, very rich functionality,
and a very small download. That is what I call a bargain. So, that's the Wave example.