GWT code split is awesome

For the past few days, I’ve been working on code splitting our existing GWT application. The application is fairly big with about 20k loc (excluding javadoc, comments and tests). The download size (with obfuscated mode) is about 1.5M, and with pretty mode, is a whooping 10+M. Obviously this is not acceptable.

GWT2 provides developer guided code splitting feature. It sounds complicated and under the hood, it may very well be (involves a lot of graph theories to figure out dependencies and so on) but from the user’s point of view, it’s very easy. You just have to wrap your potentially big operations in a GWT.runAsync() call.

However, since our application is using GWT best practices (dependency injection, MVP pattern), it’s not as straightforward as GWT doc describes. A bit of digging on the internet leads me to this page http://code.google.com/p/google-gin/issues/detail?id=61

Gin patch

Someone contributed a patch to gin, which made split points transparent to the user of gin. The presenters that aren’t needed initially can be wrapped in an AsyncProvider<T> instance – which by the blessing of deferred binding, translates into a GWT.runAsync call in the generated code. The patch hasn’t been accepted into gin’s trunk yet, but it’s fairly easy to apply the patch and rebuild. A huge thanks to fazal.asim who hacked and contributed this patch.

Results

The result of code splitting is encouraging – with very little structural change, we’re able to reduce the initial download size to 29% of the total size:

Changes

I mentioned we needed very little structural change, but we did have to change something around. This is because with code splitting, the presenters that are split out from the initial download are not instantiated until they’re used/downloaded. This means you cannot put logic in their constructors, and responding to place change has to be initiated by the container presenters.

Improvements

Code splitting is awesome. However, if I’m allowed to voice a complaint, the report compiling time is just excruciating! For our application, it usually takes about 10 minutes to compile SOYC report – maybe a few minutes too long given the specs of my machine isn’t too bad (Quad Core, 3G memory). Also, the compiled SOYC report takes up 600M of hard disk space! Ouch! Maybe instead of emitting HTML pages, they can make SOYC report a JS application, with data being encoded in JSON format?

Anyway, this doesn’t take anything away from the awesome job GWT team has done for developers.

Follow-up

Thanks to AsyncProxy, which provides a blocking (synchronous) interface while utilizing GWT.runAsync. This way, I’m able to build a view proxy that implements the same interface while keeping the real view components out of the initial call graph. The result of this, is a further reduction of the initial download size.

The initial download size is 13.77% of the total code size! Sweet!

About these ads
Leave a comment

4 Comments

  1. jaz

     /  April 13, 2010

    This was very interesting, are you still using gwt-presenter with the AsyncProxy? I’ve been struggling with this myself and would love to see what you have done, any chance you can post some samples?

    Reply
    • I’m not using gwt-presenter, but I wrote a mvp framework that’s modeled after gwt-presenter and share the same principles but better suited the needs of our project. Anyway, I need to put an AsyncProxy around the view of my MainPresenter. My MainPresenter “knows” the async modules (presenters that are created by gin’s AsyncProvider) but my MainView is responsible for the creation of the structure of the UI, therefore, MainView needs to instantiate a bunch of widgets. Because MainPresenter/MainView isn’t async, they’re visible via the initial call graph and the dependency for the widgets need to be pulled in.

      So I stumbled upon AsyncProxy in GWT’s doc, which is exactly what I needed. Basically, you don’t need to do anything fancy – AsyncProxy generates the code needed to defer the instantiation of the view object, hence the widget library.

      Here’s an example:

      @ConcreteType(MainView.MainView.Impl.class)
      @AllowNonVoid
      public interface MainView extends MainPresenter.Display, AsyncProxy<MainPresenter.Display> {
        public static final class MainViewImpl extends Composite implements MainPresenter.Display {
          [...]
        }
      }
      

      And that’s it! The magic here is async proxy will generate an implementation of MainPresenter.Display, and delegate the calls to the concrete subject (MainViewImpl) when the methods are actually called. Notice the real subject class *has* to be a public static inner class of the proxy.

      If you’re interested in how GWT turns a synchronous call into asynchronous, you can take a look at the code generated by AsyncProxy.

      Hope it helps.

      Reply
  2. jaz

     /  April 13, 2010

    Thanks for the fast reply! This is exactly what I needed, looks great! I’m using gwt-presenter and had all the presenters that the main presenter will display injected into the constructor. Each of these child presenters used the place manager to reveal themselves, so I removed them from the main presenter and implemented a AsyncProvidedPresenterPlace that uses gin’s AsyncProvider instead of Provider (gwt-presenter 1.1.x-replace). After this, I noticed no change at all and couldn’t figure out what was wrong.

    I just figured it out, I had the -draftCompile option enabled and sure enough that bypasses all code splitting. So, if anyone else ever runs into this issue, be sure to check this.

    Cheers!

    Reply
  1. TapaGeuR » ITGIF – “IT-God” It’s Friday #15

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: