04.25.06

OpenLaszlo and Dojo

Posted on April 25th, 2006 in General, Announcements by jgrandy

Yesterday we announced a strategic partnership with the Dojo Foundation: OpenLaszlo will not only be licensing the Dojo Toolkit for use within our next major release, we will also make substantial code contributions back to Dojo for use by the entire Ajax/DHTML community.

I’d like to write a little bit about why Dojo is a good choice for us and where we see it fitting into our platform architecture.

The Dojo connection came about as part of our current project to bring OpenLaszlo to multiple runtimes, and to DHTML. We are building separate kernels for each of our runtimes. These are small pieces of code, written in the native dialect of the target (ActionScript 2.0 for Flash 7 and 8, cross-browser JavaScript 1.4 for DHTML, and so on), and providing the runtime abstraction layer upon which the rest of the platform will rest. As we approached the design of the DHTML kernel, it seemed to us that the more we could leverage work being done in the Ajax/DHTML world the better that kernel would turn out.

Dojo quickly stood out as a toolkit with a mature design philosophy, committed and smart collaborators, and (crucially) a package system that would allow us to pick and choose features without adopting the entire toolkit. Our needs are specific, and low level: leak-free event handling, robust media loading, cross-browser DOM APIs, and so on. Dojo is able to provide many of these, so we decided to license it for use within the OpenLaszlo/DHTML kernel.

But Dojo doesn’t provide everything we would want in a DHTML kernel. For example, our kernel exports the concept of a sprite—basically an interactive display primitive, implemented as a MovieClip in Flash 7 and 8, and as a DIV in DHTML. Our thought was: why not contribute these pieces back to Dojo? We’re both open source, with compatible licenses, so a contribution like this repackages code we would write anyway in a form that can be re-used by the broadest possible audience. OpenLaszlo benefits from more smart engineers using and improving the kernel of our DHTML runtime, and the Ajax community gains new libraries within a mainstream toolkit.

Where are we now? The OpenLaszlo platform team is currently in the process of refactoring the LFC (Laszlo Foundation Classes) along a kernel API boundary, and has begun incorporating Dojo libraries into our rapidly-evolving DHTML kernel. We’ve also already benefited from the Dojo unit test infrastructure: we hope to support Rhino as a server-side unit test environment, and Dojo’s support for that VM has helped us to bootstrap ourselves into Rhino. Once our kernel APIs and DHTML kernel stabilize we will be looking at what we can contribute back to Dojo.

These are exciting times! Dojo and OpenLaszlo are both participants in the birth of a new web-centric application technology, and it’s great to be working with them so closely to make that happen.

Technorati Tags:
, , , ,

04.18.06

Optimizing Laszlo Explorer: Laziness is good

Posted on April 18th, 2006 in Development by jgrandy

One of the big changes in the recently released OpenLaszlo 3.2 is that we removed KRANK. KRANK was an optimization that sped up application launch by effectively executing part of the launch process at compile time. Unfortunately, KRANK was a fragile solution that only really worked with targeting Flash 6. It was expensive to maintain and wasn’t going to survive the transition to multiple runtimes. So we made the decision to remove it.

One side effect was that with the absence of KRANK several OpenLaszlo applications no longer launched in an acceptable amount of time. The most prominent of these was Laszlo Explorer, the main way new Laszlo developers explore the capabilities of the language. Without KRANK, Laszlo Explorer took almost 20 seconds to launch on my 1.6Mhz PowerBook. Clearly too slow.

So what to do? I decided to take a look at why this application took so long to launch. If we weren’t going to support KRANK, we would need to dig in and understand where the time was really going. I ended up improving launch speed by just about 90%, and learned some important lessons about OpenLaszlo and the tree component.

I started with the sort of optimizations I’ve heard our Studios folks discuss. For example, I centralized a number of similar XPath constraint expressions into a single ondata method, reducing the number of delegates and the number of XPath evaluations done during setup. These relatively simple changes brought me a 3% speedup: nice for an hours’ work, but not nearly enough.

Next, I noticed that each tree node in the Explorer menu contained a relatively large number of subviews and subnodes. For example, there were two complementary state nodes, used to control the size and position of the node label depending on its depth in the tree. Each of these states costs a node allocation, so converting that code to a single function called from the oninit handler saved time.

There were also animatorgroups that were active only when a tree node was opening or closing. By turning the animator groups into classes and instantiating them only when needed I was able to save the cost of allocation of two deeply nested animator groups.

By reducing the subnode count by 50%, I saved another 5% on launch, for a total savings of 8%. Still not enough.

At this point, I started experimenting with OpenLaszlo’s built-in profiler. I’ll write a separate post about this useful tool, so for now let me just describe the breakthrough finding: even though only nine tree nodes are visible when the Explorer launches, something like 280 tree node instances were being allocated!

A bit of code inspection quickly revealed the problem. It was in the LZX code declaring the tree structure itself:

   <basetree name='menu' datapath='navdata:/menu'>
     <navbutton width='160' level='0'>
        <navbutton width='160' level='1'>
          <navbutton width='160' level='2'>
            <navbutton width='160' level='3'>
            </navbutton>
          </navbutton>
        </navbutton>
      </navbutton>
   </basetree>

To understand why this is slow, you need to understand a bit about how node allocation interacts with node replication. Replication acts by replacing a single child node (usually a view) with multiple nodes, one for each data element returned by the original node’s datapath XPath expression. This replacement process only occurs after the original node has been allocated and initialized, and—crucially—constructed its own subnodes.

With hindsight, one problem is clear: at the first level, a nav button is constructed, including three nested subviews. This nav button is then replicated seven times, each with three nested subviews. The second level nav buttons are then data bound and replicated, each initially having two nested subviews. And so on for the third and fourth nested subviews. If a given node in the XML data doesn’t have subnodes, nested nav buttons are still allocated to level four in a single chain. The result is that the tree is balanced to level four: there are always four nav buttons allocated along each branch of the tree, regardless of XML data structure. So even though there are only 170 nodes in the XML structure, we allocate 280 tree nodes.

But the bigger problem is that we are allocating anything but the initially visible nodes in the first place! Why aren’t we just allocating the seven topmost tree nodes, plus the two visible in the one open topmost node? Saving 40% by only allocating nodes that will be data bound is one thing, but why not save over 90% by only allocating nodes when they become visible?

I was able to quickly engineer a change to the navbutton class such that it would only allocate subnodes when it was opened. This change required dynamically allocating the initial subnode on open and then letting it be replicated. There were a few subtleties: deferring the ‘open’ animation until replication was complete (solution thanks to work done by the community on the laszlo-user mailing list), and continuing to support the ability to deep link into the Explorer menu structure. But the change turned out to be surprisingly compact and generic. And Laszlo Explorer now launches in about two seconds on my laptop!

We’re exploring the possibility of making a similar change to future versions of the basetree so that everyone can share in this optimization. Lazy allocation of subnodes requires a more data-driven usage model, so this would not be a transparent change.

I’ll note in closing that before doing this work I had gone along with the conventional wisdom that the recursive design of basetree makes it slow. I no longer agree with this assessment: with properly lazy allocation of subnodes, there’s no inherent slowness to keep us from enjoying this elegant component.

Technorati Tags:
, ,