ETech - AJAX Unplugged Slides

Posted in Open Source, Zimbra Desktop by Kevin Henrikson on the March 28th, 2007

Slides for today’s AJAX Unplugged session covering various techniques in offline AJAX can be found here: eTech_2007_AJAX_Unplugged_Henrikson.pdf (2.6 MB)




Zimbra Lite: Inline Day View

Posted in Zimbra Web Client by Kevin Henrikson on the March 26th, 2007

Three posts in the same day may be a Zimbra Blog record. Just had to post this. Ignoring all the buzz of Zimbra Desktop over the past 24hrs, Roland has been heads down adding calendar support to the Zimbra Lite client (JSP/HTML based for old computers, slow networks, and ancient browsers). He owes us a post on the Zimbra Lite architecture so I won’t steal his thunder. However he sent this screen shot.

Here you see a meeting invite, and on the right column you get a day view of your calendar for the day. In the Zimbra AJAX Client you can hover of a date thanks to Zimlets

Zimbra Lite: Meeting Invite with inline Day View:
zimbra_lite_invite_line_day_view.jpg

Zimbra Ajax: Meeting Invite with Zimlet Hover of Day View:
zimbra_ajax_invite_date_zimlet.jpg




Lazy Loading

Posted in Zimbra Server, Zimbra Web Client by Conrad Daemon on the March 26th, 2007

The ZCS web client recently underwent a significant amount of change in order to load Javascript code as needed, rather than loading all of it on initial login. Those changes included the development of a package system, and a lot of shuffling around of client code over the course of about two months. The results have been worth it: the client has seen its initial load time cut
roughly in half.

From the outset, the code for the Ajax client has been well-separated in terms of responsibility (following the model-view-controller paradigm), but poorly separated along the lines of function. Applications knew each other’s details, and classes accessed each other’s properties and functions freely. There is no real privacy control in Javascript, and we weren’t enforcing any. Since the entire pile of client code was being loaded at login, there was no real incentive to maintain boundaries if they slowed development. But that pile had become a mountain and we started to hear back from customers that initial load time was a problem.

When a user logs in, she wants to see her Inbox. But we were making her wait first for the entire client code base to be downloaded and parsed - all sorts of calendar, contacts, notebook, etc code that she may never use, and even worse, she may not even have enabled. Obviously, much of that initial load is a big waste of her time. So we decided to run a simple test: Remove any code from the client that wasn’t needed to display the Inbox, and compare load times. The result, as expected, was dramatic: a 40-50% reduction in initial load time. The “Lazy Loading” project was on.

Ross’s characterization of me at the beginning of the project was apt: standing at the edge of a high dive, staring down at water that looked very cold and very far away. I knew that it would require a fair amount of client re-architecting, and that we would need to find or develop a package system to load Javascript on demand. Since the project would involve a significant rewrite of the client, touching nearly the entire code base, it was also a chance to sweep through and clean up other miscellaneous ugliness. After a couple weeks of thinking and poking at things, it was time to start the rebuilding. I recruited Andy Clark to write the package system while I started tearing apart the client. Once started, the work went pretty fast. Of course, the deeper I got the more I realized there was to do (small pieces still remain). The quiet times during the winter holidays were a good time to crank out code, and the new client was ready for testing in mid-January.

Below are some numbers comparing the LAZY version of the client with the previously released version FRANK.


  FRANK LAZY
Footprint (uncompressed) 2744K 1658K
Footprint (compressed) 596K 374K
Lines of code 87053 54454


Footprint is related to download speed, and lines of code is related to parse time. Bear in mind that these measurements were done in late January, so they have likely changed slightly since then.

Below are some average load times in seconds.


  FRANK LAZY gain
IE7 8.3 5.1 39%
FF2 10.6 4.7 55%


Following are remarks of a more technical nature on the implementation of Lazy Loading.

Packages

The obvious way to load code on demand is through a package system, since the most efficient way to load code on demand is to gather related code into packages. Loading each individual file as it’s needed is possible, but the network cost of all those requests is prohibitive. The first thing we needed was a package system that could track which packages and files had already been loaded, so that a package is not loaded until the client asks for it, and it’s only loaded once.

There are two common mechanisms for loading JavaScript dynamically: XHR and script tag insertion. With XHR, the contents of a .js file are retrieved as a string and eval’ed. With script tag insertion, a <script> tag with a “src” attribute pointing to the .js file is added to the DOM, and the contents are parsed automatically. XHR has the advantage that it can be done synchronously, which leads to a simpler programming model. The calling code simply blocks until the package has been loaded, then continues with code that depends on files in the package. Script tag insertion leads to an asynchronous programming model because you must listen for an event to tell you when the script has finished loading into the DOM so that the classes it defines are available. Script tag insertion appears to be slightly faster, probably due to the creation and handling of large strings that the XHR method requires. But the difference isn’t significant.

We considered importing the Dojo packaging system, but for several reasons we decided to write our own. Of course, the overriding reason is that we had a good idea of what we wanted, and after a quick look at the Dojo system, we decided it would be easier and quicker to write our own rather than adapt to Dojo’s. We admittedly didn’t take a thorough look at Dojo, so apologies for any mischaracterizations. We wanted our underlying package system to support loading code through either XHR or script tag insertion, and the Dojo package system only does XHR. We also wanted it to be aware of the notion of packages as collections of files, and in Dojo a package appears to be a single file (normally of related functions). Our code is partitioned along object-oriented lines into sets of classes, where a file normally defines a single class, so we have a much greater need to bundle files into packages.

Andy created two new classes to handle package loading. The smaller, AjxLoader, is a barebones wrapper around XHR and does not provide the additional support that the web client uses for SOAP requests (AjxRpc, AjxXmlDoc, etc). AjxPackage does the real work of managing packages: mapping package names to the file system, knowing which packages/files have been loaded, loading packages, and evaluating loaded code when necessary. Sitting on top of AjxPackage is AjxDispatcher, a class I wrote to provide some package-related infrastructure to the client. It provides methods to register and run API methods (which know which packages they depend on), and a mechanism for calling functions before and after a package loads, for example to display and then clear a “Loading…” screen. The client interacts with the package system via AjxDispatcher and doesn’t call AjxPackage methods directly.

Apps

Most of the packages we’ve created map to applications such as Mail, Contacts, or Calendar. Packages can be arbitrarily granular, so we have created specialized packages based on need, such as ContactsCore, which is loaded to parse the background load of contacts that happens on login. It doesn’t contain any of the UI code needed to display contacts, but that isn’t needed yet. Many apps have “*Core” subpackages which provide limited functionality, normally to handle app-related data without having to display it.

During a production build, the files in a package are concatenated together, then the resulting aggregate file is minimized (white space, debug statements, and comments are removed) and compressed. Due to that aggregation, packages are additive so that code is not parsed more than once. For example, the package Contacts does not contain any files that are in ContactsCore. Normally, ContactsCore will be loaded during login, and Contacts only when the user goes to that application. Any file that appears in both packages will be loaded and parsed twice, which is unnecessary. The package system can’t do anything about it due to the aggregation, so we make sure that the Contacts package simply adds the files needed beyond the ContactsCore package. Any client code that needs the contacts application must load both packages.

A similar concept is at work in loading what we consider to be our base packages. Since the user has already visited the login page, and the browser will have cached those files, we separate some of the base packages into what is loaded to display the login page, and what additional code is needed to launch the client. The result is that we have a pair of packages to load our Ajax framework: AjaxLogin and AjaxZCS. Remember, there is no restriction on creating packages to fit your needs.

Debugging

One unfortunate consequence of loading files via XHR is that they are not recognized as Javascript files, and the code is not accessible from within a debugger. Any break hit in that code will show up as being within the package system. The author of Firebug is working on a way to handle that. Until then, the way to pre-load packages via JSP files is to pass package names to the query string argument “packages” (assuming it’s not the package system you’re trying to debug). To load all packages, set the value of that argument to “dev”:

http://localhost:7070/zimbra/mail?debug=1&packages=dev

App Classes

Before the re-organization of the web client to support lazy loading, apps, though divided into subdirectories, were freely available to each other. Even if an app wasn’t enabled, all of its code and constants were available. Now that app code is within a package that may not be loaded, formerly public methods and constants are not available. Each app has been isolated. Still, we need the ability for apps to invoke methods of other apps, and we need to be able to look up their constants. The solution we’ve chosen for this is a registration mechanism - each app class (eg ZmMailApp), which used to do minimal work (mostly return references to its controllers), is now responsible for defining its public interface. It does that by defining a number of public constants and methods, and by overriding some abstract public functions defined in its parent class, ZmApp.

ZmApp provides storage for app-related info, a set of abstract registration functions to be used during app construction, and functionality that is common to all apps. Much code that was formerly app-specific has been converted into generic code that checks constants created during app construction.

In general, an app class takes the following steps to set itself up for lazy loading:

1. Define some needed constants in static code.
2. During client startup, any enabled app will have an instance created through a call to its constructor. The parent constructor in ZmApp calls the following functions, which an app overrides as necessary:

this._defineAPI();
this._registerSettings();
this._registerOperations();
this._registerItems();
this._registerOrganizers();
this._setupSearchToolbar();
this._registerApp();

Any data that is relevant to a single app will be defined by that app. Data that is common to many or all apps (for example, the operation “tag” or the organizer “folder”) is defined in common code. The functions above are wrappers around calls to functions that do the actual setup.




Zimbra Desktop Launched

Posted in Open Source, Zimbra Desktop by Kevin Henrikson on the March 26th, 2007

Last night we launched Zimbra Desktop. Same AJAX interface you’ve been using on the web you can now take with you on a trip be it plane, train or auto. It’s even nice for those times your trusty network fails you. Today it supports Mail and Contacts, but Calendar, Documents, and other collaboration features will be coming soon.

This week at E-tech Satish will giving a keynote centered around offline webapps on Tuesday. The following day I’ll be digging in deeper to the architecture of Zimbra Desktop with this talk. Some of our arch decisions were covered in the comments of the Zimbra Offline post. As always you can comment or discuss Zimbra and our new Desktop release on the Zimbra Forums.




Feeds moved to Feedburner

Posted in /etc by Kevin Henrikson on the March 22nd, 2007

We just moved our blog feed to use Feedburner this morning. Depending on your feed reader you may get some duplicate posts. Think of it as a blast from the past. :)

Our new feed URL is:

http://feeds.feedburner.com/zimbra




Top 150 I-Technology heroes and their teams

Posted in Open Source by Scott Dietzen on the March 9th, 2007

A couple of buddies pointed me toward Sys-Con Media’s Top 150 Information Technology Heroes, and I have to admit it was fun (once you click past the obstructing ad anyway). While my first reaction was to want to point out omissions (see below), what’s not to like about a list that mixes Dennis Ritchie, Luca Cardelli, Edsger Dijkstra, and Charles Babbage?

However, you have to get a bit cranky with the fact that Jim Gray was left out. (His omission is even more surprising given recent events should have kept him on the authors’ mind.) Jim’s work on transactions was foundational for both relational databases and transaction processing (TP) monitors. Moreover, the whole web/Java application server category (WebLogic, WebSphere, .NET, …) is really just a TP monitor rearchitected for web processing. (By the way, the reason it was not called a web/Java TP monitor in the first place is that the venture capitalists would not fund start-ups to build a next-generation TP monitor. But a Web application server? Well, that sounds like a whole new category.)

And if you are going to recognize both James Gosling and Josh Bloch for their Java contributions (here here), then Arthur van Hoff probably ought to be included too. I think the list could also have used some more distributed systems contributors (data/file sharing, function shipping such as via messaging or remote procedure call), but as an old programming languages hand, it was great to see that category well represented. The quibbles could go on.

Instead, let me make a different and perhaps more important observation: one of the most intriguing aspects of the information technology industry is the way that it is both an individual and a team “sport.” One of the things that is striking about the list is how different are the contributions of, say, a Steve Jobs versus those of an extraordinary architect/programmer (there are many on the list) versus those of a Turing award winner whose thinking transcends products and technologies. Many of the IT heroes on the list have the ability to look at complex problems, and find simple, elegant solutions (think spreadsheets or hyperlinks) that change the industry. Teams often grow up around such leaders, leaders that can supply the one or two elusive insights that make the difference in delivering an extraordinary technology.

At the same time, most innovations come out of a team rather than an individual. Java and WebLogic were, for example, staunchly team efforts (although Bob Pasker is definitely the right choice for recognizing a WebLogic team member, given his contributions in architecture, innovation, coding, and in helping recruit the rest of the team). After all, it takes a team to deliver an information technology product. Through the frequently ad hoc collaboration of gifted talents, the whole really does become greater than the sum of the parts. Magic can result. Getting to be a part of that process makes all of the long days and hard work worthwhile.

So best to check your ego at the door, I think, and find a really smart team to work with. (To reuse an old joke, I think I may have lowered the average IQ by joining Zimbra.) Ronald Reagan had a plaque sitting on his desk that said “There is no limit to what a man can accomplish if he doesn’t mind who gets the credit.”




Software appliances, virtualization, and Zimbra

Posted in Open Source, Zimbra Server by Scott Dietzen on the March 1st, 2007

Sorry to have been dark for the last couple of months. Things have been very busy indeed for the Zimbra team, but it is gratifying to have some of our longer-term engineering efforts baring fruit: in addition to the release of 4.5 (more info here) and opening up our product management portal for your input, we have now posted the beta release of our software appliance distribution for ZCS!

Software appliances promise to augment Software as a Service (SaaS) as an easier, cheaper way to use third-party software, especially by lowering the cost of managing independently changing subcomponents of a software “stack”—application logic, database, web application server, virtual machine, operating system, and so on. For our 1.0 software appliance, Zimbra has teamed up with rPath (think Linux distribution for software appliances), and for virualized deployment thereof, VMware. For a more detailed discussion of our thoughts on software appliances as well as our technical collaboration to date with rPath and VMware, please see our recently posted whitepaper. And for those that would much rather try out our initial bootable ISO or VMware appliance images, they are now posted on Zimbra’s standard download pages for the Network Edition, and shortly, for the Open Source Edition as well. Feedback most welcome, either on the paper or, better yet, on the software appliance itself.

Thanks for listening, and more soon.




Subscribe


Subscribe by Email



Categories


Archives

  • June 2009
  • May 2009
  • April 2009
  • March 2009
  • February 2009
  • January 2009
  • December 2008
  • November 2008
  • October 2008
  • September 2008
  • August 2008
  • July 2008