General Interface is an open source project hosted by the Dojo Foundation

GI Contributor Blog Blog from Apr 26, 2010

  2010/04/26
GI Build Tools - Introduction and Set Up
Last Changed by Jesse Costello-Good, Apr 26, 2010 15:31

Introduction

GI developers who want to create high performance GI deployments should take the time to understand and use the suite of build tools that are part of the open source GI project. Only by leveraging the GI build tools will you be able to create applications with the shortest load times and fastest code.

With the source distribution and the build tools you can:

  • Create a build of GI with a load profile optimized for a specific GI application
  • Compile your own API documentation
  • Create an un-obfuscated build of GI for easier debugging
  • Obfuscate, merge and optimize the JavaScript code in your own application
  • Create a build of GI or your own application with a default locale other than English
  • Conditionally include or exclude blocks of JavaScript code
  • Optimize your AMP based application
  • Create a completely automated build and deployment work flow

I'll try to cover most of these use cases in subsequent posts. First, we need to get set up with the GI source code and build tools.

Set up

GI has an Ant-based build process so you need to have a few things installed on your computer to use the build tools:

Ant works on pretty much any operating system. I use Mac OS X Terminal so my examples will look like a Linux prompt. If you are using Windows I recommend installing Cygwin.

Once you have Java and Ant installed you need to get a source distribution of GI. You can download the source distribution of the latest release or grab the code from SVN.

If you are using the latest release ZIP, unzip the contents of the archive. I'll refer to this directory as GIHOME (GIHOME contains logger.xml, JSX/ and several other files).

Your first GI build

The build tools, scripts and configuration files are all contained in the build/ directory. To make your first build, go to that directory.

$ cd GIHOME/build

To make a build of GI with all of the default settings simply invoke Ant.

$ ant
If you see many warnings like "Warning: The encoding 'UTF-8' is not supported by the Java runtime" your Java set up has a XML library that conflicts with the library that GI uses. As a work around always invoke Ant as ant -lib tools/lib/xml/xalan-serializer-2.7.jar.
You may get an out of memory error with Ant's default Java settings. You will probably need to increase Ant's maximum heap size to 512 MB. On most systems you can do this by setting the ANT_OPTS environment variable to -Xmx512m.

The full build process takes about 90 seconds on my machine with the default settings. Later, I'll describe some ways of making the build even faster.

Now, if you look in GIHome/dist/gi you'll see the build of GI that you just created. Open GI_Builder.html in a browser to verify that the build was successful.

Modifying the default build settings

All build settings are contained in the file GIHome/build/build.properties. There are two recommended ways of overriding these default settings. The first is on the command line and the second is with the user.properties file.

To modify a property on the command line when you invoke Ant, add -DpropName=propValue to the command invocation. See the Ant documentation for more information.

To modify a property semi-permanently so that you don't have to add it to the command line each time you invoke Ant, create a file GIHome/build/user.properties. Any properties defined in this file take precedence over those in build.properties.

Don't modify build.properties yourself as this file is owned and maintained by the GI distribution and often changes between GI releases.

As a first example, let's make a build of GI where the jsx3.gui.Matrix class is included in the load profile. Including Matrix in the load profile will speed up the load time of applications that use Matrix. First, invoke the clean target in Ant. This step is usually necessary to prevent errors.

$ ant clean

Next, invoke the default target while overriding the build.gi.includes.jsx build property.

$ ant -Dbuild.gi.includes.jsx=jsx3.gui.Matrix

(To include multiple classes format them as a comma-delimited list.) If you check the build you will see that the Matrix.js file does not exist, meaning that it has been baked into jsx.js, which defines the load profile.

$ ls -la ../dist/gi/JSX/js/jsx3/gui
...
-rw-r--r--   1 jesse  staff  28495 Apr 26 13:55 List.js
-rw-r--r--   1 jesse  staff  28144 Apr 26 13:55 Menu.js
...

Making the build process faster

You can make the build process faster by having it do less. Often when creating a custom build of GI you do not need to compile the API documentation or Builder documentation. To remove these steps from the build process add the following to your user.properties.

build.gi.docs = false
build.gi.docs.html = false

If you don't need to create an internationalized version of GI add the following, which excludes all locales other than en_US.

build.locales.jsx = en, en_US

If you are creating a build of GI for deployment only and not for running Builder, you can exclude Builder from the build by adding the following.

build.gi.ide = false

If I include all these overrides I can get the build time down to about 20 seconds.

More to come

I plan to go into much more detail describing all the advanced things you can accomplish with the GI build tools. Watch this blog for updates.

Posted at 26 Apr @ 1:06 PM by Jesse Costello-Good | 0 Comments
GI Build Tools - Creating a Build Optimized for Your App
Last Changed by Jesse Costello-Good, Apr 27, 2010 15:23

Following up on my earlier post I want to go into much more detail on creating a build of GI that is optimized for a particular GI application. We highly recommend that you create an optimized build of GI for your critical applications. Creating an optimized build can dramatically shorten the initial load time of your application. I've seen 20 second load times reduced to 6 seconds just by deploying an optimized build.

Background

In the directory on your computer where you installed GI you have several things. The "GI runtime" consists of JSX/, jsx3.gui.window.* and logger.xml. The GI runtime is the platform that a GI application runs on. GI Builder is one such application that runs on the GI runtime. GI Builder consists of the files GI_Builder/, GI_Builder.* and shell.* from the GI installation directory.

When you deploy an application you copy the GI runtime and your application resources to a server. Your application runs on this copy of the GI runtime. If you copy the runtime from the GI installation directory then your application is running on the same runtime as is GI Builder when you run GI Builder on your computer.

There's no reason that GI Builder and your application have to run on the exact same runtime. In fact there are many reasons why you would want to have them running on different runtimes. For example, you probably want to run GI Builder on the "debug"
runtime so that you can see more warnings while you are developing your application. But when you deploy your application you want it to run on a runtime that is as small and fast as possible.

This article will show you how to compile the best runtime for your deployed application. This is the runtime that you will want to upload with your application when you deploy it on a public HTTP server.

Load Performance

Load performance in a web application running over HTTP comes down to a few simple principles:

  1. Load as little as possible
  2. Load what you need in as few HTTP requests as possible
  3. If requesting multiple resources, load them in parallel as much as possible

Recent versions of GI are good at loading runtime and application resources in parallel so you don't have to worry too much about the third point. Creating an optimized runtime build will take care of the first two points.

Sometimes points one and two conflict with each other. For example, part of your application might use jsx3.gui.Matrix but that part is not commonly used. Should you reduce the number of requests by merging jsx3.gui.Matrix with the set of required classes? Or should you load as little as possible up front and load Matrix as needed? There is some art as well as science to resolving these decisions. My usual suggestion is to merge all resources that must load for your application to reach its first interactive state, and nothing else.

Determining What Classes to Load

The GI runtime consists of a number of required classes (e.g. jsx3.lang.*, jsx3.app.*) and many optional classes (e.g. most of jsx3.gui.*). To create the optimal build for your application you need to determine which optional classes are used by your application. To do this, follow these steps:

  1. Make sure you are running Builder on either the source distribution of GI or the standard or debug packages. Running on the max build won't work for these instructions.
  2. Open your application in Builder running on Firefox with the Firebug extension installed, IE8 or Safari 4.
  3. Make sure that your logger.xml contains the following lines:
    <handler name="console" class="jsx3.util.Logger.ConsoleHandler"/>
    ...
    <logger name="bench.jsx3.lang.ClassLoader" level="TRACE"/>
  4. Launch your application from Builder
  5. Open your browser's JavaScript console for the window that contains your running application. You may have to reload your application after you open the console.
  6. Wait for your application to reach its first interactive state, such as the home page or login screen.

At this point you should see a bunch of log messages in the JavaScript console like

2010-04-27 14:18:11.778 bench.jsx3.lang.ClassLoader (INFO) - JSX/js/jsx3/gui/Button.js : js.eval : 10ms

These are the optional GI classes that your application is loading before it reaches its first interactive state. All of these classes should be included in the build of GI optimized for your application. Make a note of the full list of classes. We'll use this list in the next step.

Configuring and Running the Build

Make sure you are set up to make custom builds of GI as described in my earlier post. Create a new properties file in GIHOME/build and call it something like app1-build.properties. This file will contain the parameters for the build optimized for your "app1" application.

Into this properties file add the list of classes you saw in the JavaScript console. So if the entire list of classes was jsx3.gui.Button and jsx3.gui.CheckBox your properties file would like like:

build.gi.includes.jsx = default,jsx3.gui.Button,jsx3.gui.CheckBox

Since you don't need to build Builder or the documentation you can add these lines to speed up the build.

build.gi.includes.jsx = default,jsx3.gui.Button,jsx3.gui.CheckBox

build.gi.docs = false
build.gi.docs.html = false
build.gi.ide = false

To create the build run the following commands.

$ cd GIHOME/build
$ ant clean; ant -propertyfile app1-build.properties

Once you have the build you should run your application on this build. To do this create a launch page with Builder and then hand edit it so that it points to the JSX30.js from your custom build. Make sure to copy the logger.xml file from your Builder installation to the new runtime.

This time when you run your application you should not see any logging messages with subject bench.jsx3.lang.ClassLoader. Repeat the steps in Determining What Classes to Load to make sure that all optional classes that your application uses are included in the optimized build. It may take your several iterations to finalize the list.

Once you have a fully optimized build simply deploy it along with your application to your web host. All the optional classes that your application uses will be baked into jsx.js, meaning that many fewer JavaScript resources must load when your application loads.

Congratulations, you have created an optimized runtime build for your GI application. Remember that every GI application has a unique load profile. You may want to create an optimized build for each of your applications or, if they are similar enough, create just one optimized build. The advantage of having just one build for multiple GI applications is that the runtime will be in the browser cache when the user visits the second and subsequent applications.

Additional Deployment Parameters Affecting Load Time

Here are a few more things you can do to speed up the loading of your application.

Don't load logger.xml

If you are not going to be monitoring the runtime logs of your application you can opt not to load logger.xml. It's just one small file but when your application is loading over HTTP every resource counts. Modify your launch page as follows.

<script src="gi/JSX/js/JSX30.js" jsx_logger_config=""></script>

Don't load messages.xml

The file messages.xml contains the English translations of all system error messages. If you do not load messages.xml you still see errors in the logs but instead of a nice English message you just see a string key. Again, it saves you just one file.

<script src="gi/JSX/js/JSX30.js" jsx_no_messages="true"></script>

Don't load locale.xml

The file locale.xml is required if you are using DateFormat, NumberFormat, DatePicker, TimePicker, Select or any of the Cacheable controls with XML Async = true. If you use none of these you can safely prevent locale.xml from being loaded.

<script src="gi/JSX/js/JSX30.js" jsx_no_locale="true"></script>
Posted at 26 Apr @ 3:42 PM by Jesse Costello-Good | 0 Comments