Following up on my [earlier post|2010/04/26/GI Build Tools - Introduction and Set Up] 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.
h3. 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.
h3. Load Performance
Load performance in a web application running over HTTP comes down to a few simple principles:
# Load as little as possible
# Load what you need in as few HTTP requests as possible
# 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.
h3. 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:
# 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.
# Open your application in Builder running on Firefox with the Firebug extension installed, IE8 or Safari 4.
# Make sure that your logger.xml contains the following lines:
{code:language=xml}<handler name="console" class="jsx3.util.Logger.ConsoleHandler"/>
...
<logger name="bench.jsx3.lang.ClassLoader" level="TRACE"/>{code}
# Launch your application from Builder
# 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.
# 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
{code}2010-04-27 14:18:11.778 bench.jsx3.lang.ClassLoader (INFO) - JSX/js/jsx3/gui/Button.js : js.eval : 10ms{code}
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.
h3. Configuring and Running the Build
Make sure you are set up to make custom builds of GI as described in my [earlier post|2010/04/26/GI Build Tools - Introduction and Set Up]. 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:
{code}build.gi.includes.jsx = default,jsx3.gui.Button,jsx3.gui.CheckBox{code}
Since you don't need to build Builder or the documentation you can add these lines to speed up the build.
{code}build.gi.includes.jsx = default,jsx3.gui.Button,jsx3.gui.CheckBox
build.gi.docs = false
build.gi.docs.html = false
build.gi.ide = false{code}
To create the build run the following commands.
{code}$ cd GIHOME/build
$ ant clean; ant -propertyfile app1-build.properties{code}
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.
h3. Additional Deployment Parameters Affecting Load Time
Here are a few more things you can do to speed up the loading of your application.
h4. 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.
{code:language=xml}<script src="gi/JSX/js/JSX30.js" jsx_logger_config=""></script>{code}
h4. 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.
{code:language=xml}<script src="gi/JSX/js/JSX30.js" jsx_no_messages="true"></script>{code}
h4. 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.
{code:language=xml}<script src="gi/JSX/js/JSX30.js" jsx_no_locale="true"></script>{code}
h3. 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.
h3. Load Performance
Load performance in a web application running over HTTP comes down to a few simple principles:
# Load as little as possible
# Load what you need in as few HTTP requests as possible
# 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.
h3. 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:
# 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.
# Open your application in Builder running on Firefox with the Firebug extension installed, IE8 or Safari 4.
# Make sure that your logger.xml contains the following lines:
{code:language=xml}<handler name="console" class="jsx3.util.Logger.ConsoleHandler"/>
...
<logger name="bench.jsx3.lang.ClassLoader" level="TRACE"/>{code}
# Launch your application from Builder
# 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.
# 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
{code}2010-04-27 14:18:11.778 bench.jsx3.lang.ClassLoader (INFO) - JSX/js/jsx3/gui/Button.js : js.eval : 10ms{code}
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.
h3. Configuring and Running the Build
Make sure you are set up to make custom builds of GI as described in my [earlier post|2010/04/26/GI Build Tools - Introduction and Set Up]. 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:
{code}build.gi.includes.jsx = default,jsx3.gui.Button,jsx3.gui.CheckBox{code}
Since you don't need to build Builder or the documentation you can add these lines to speed up the build.
{code}build.gi.includes.jsx = default,jsx3.gui.Button,jsx3.gui.CheckBox
build.gi.docs = false
build.gi.docs.html = false
build.gi.ide = false{code}
To create the build run the following commands.
{code}$ cd GIHOME/build
$ ant clean; ant -propertyfile app1-build.properties{code}
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.
h3. Additional Deployment Parameters Affecting Load Time
Here are a few more things you can do to speed up the loading of your application.
h4. 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.
{code:language=xml}<script src="gi/JSX/js/JSX30.js" jsx_logger_config=""></script>{code}
h4. 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.
{code:language=xml}<script src="gi/JSX/js/JSX30.js" jsx_no_messages="true"></script>{code}
h4. 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.
{code:language=xml}<script src="gi/JSX/js/JSX30.js" jsx_no_locale="true"></script>{code}