Gliffy is now public
Monday, May 22nd, 2006It’s been a long time coming, and now Gliffy is out the door ready for the world to see.
It’s been a long time coming, and now Gliffy is out the door ready for the world to see.
Gliffy was noticeably slowing down when used for an extended period of time, and we suspected a memory leak was the cause. Fortunately, the fine folks at Laszlo have built some excellent tools into the debugger which make tracking down such issues a heck of a lot easier.
Our adventure begins with a look at the docs which discuss hunting down memory leaks. Using the procedure described in the docs, I discovered that the objects which represent undo were not being picked up by the garbage collector. Objects will not be picked up by the garbage collector if any references to those objects exist.

Another interesting thing I noticed was that the class definition of undo did not explicitly extend another class. When a class definition does not extend another class, it is implied that the class extends <view>, NOT <node> as you might expect. In this case, our undo object does not have a visual component to it, and as such what we really want is to extend <node>.
If you’ve instantiated Laszlo objects at run time before, you know that the first argument of the constructor is the parent node of the constructed object. In our case, it didn’t really make sense for the undo object to have a parent, and thusly none was defined. If you take a look at the source code for LaszloView.as (in the source distribution) you’ll see that when a parent is not defined in the constructor, the canvas is assumed to be the parent.
Ah-hah! We’ve found where the reference to our undo objects were coming from. Simply checking the contents of canvas.subviews in the debugger offered verification. Further investigation revealed that constructing a <node> without an explicit parent does not cause the canvas to be defined as the parent. Thusly, by simply having our undo class extend <node>, I was able to fix the memory leak. Yay!
Lessons learned:
If you follow OpenLaszlo news closely, you may have noticed that a new event syntax is available in OpenLaszlo 3.2 which makes specifying and handing your own events more straightforward. I think the folks at Laszlo Systems made a smart move in adopting the new syntax as it is more intuitive, and will reduce confusion for new developers.
Curiously, the only documentation I found describing the new syntax was in this feature proposal, and in the nightly builds of the reference guide and the developers guide. Somehow the new syntax is missing from the shipping 3.2 docs.
In a nutshell the syntax is:
<event name="onMyEvent"/> - Declare an event<handler name="onMyEvent">
//some code here to handle event
</handler>onMyEvent.sendEvent() - notify event listeners that the event firedKudos to the OpenLaszlo folks for continuing to evolve the language.
Clint and I presented Gliffy at the OpenLaszlo meetup last night. I wrote up a quick summary over on the Gliffy Blog.
Here’s the scenario: I want to display 500 items in a scrolling list, but using regular replication causes 500 views to become instantiated, which can take a loooong time. Lazy & resize replication helps out by only instantiating the views that the users can see. Lazy replication then manages copying the relevant data to views that scroll into the clipped area. The dev guide explains the purpose quite well:
“The lazy replication manager creates only enough replicated views necessary to display the data, so there is not a view for each data node. This enables the display of very large datasets.”
This is great because instantiating views is expensive, and we don’t want to make any more of them than we need to. This efficiency gain comes with a price of added complexity however. Here are some tips to hopefully make your experience with lazy & resize replication a little less painful:
Here’s some example code that covers most of what I’ve talked about above:
<canvas>
<!-- Let's say this is my real dataset. It could be
loaded from the server, but we'll make it local
for this example -->
<dataset name="people">
<people>
<person name="chrisk" sex="m"/>
<person name="lyla" sex="f"/>
<person name="clint" sex="m"/>
<person name="renais" sex="f"/>
<person name="ron" sex="m"/>
<person name="terry" sex="f"/>
<person name="debi" sex="f"/>
<person name="luke" sex="m"/>
<person name="jason" sex="m"/>
<person name="eileen" sex="f"/>
<person name="henry" sex="m"/>
<person name="nik nik" sex="f"/>
<person name="kel" sex="m"/>
<person name="hu?" sex="f"/>
</people>
</dataset>
<button text="Replcte views!">
<method event="onclick">
replicatedParent.datapath.setXPath('people:/people');
</method>
</button>
<view width="100" height="100" clip="true">
<!-- use this dataset to ensure a
replciation manager is created, and also
create some views on applciation startup
so that the user doesn't have to
wait when they request the data -->
<dataset name="fakeData">
<people>
<person/> <person/> <person/> <person/> <person/> <person/>
</people>
</dataset>
<view id="replicatedParent"
datapath="local:parent.fakeData:/pepople">
<text>
<datapath xpath="person/@name"
replication="lazy"/>
<!-- Is called when a user scrolls the data into view -->
<method name="applyData" args="_d">
super.applyData(_d);
if( this.datapath.getNodeAttribute('sex') == 'm' ) {
this.setBGColor(0xCACAFF);
} else {
this.setBGColor(0xFFCACA);
}
</method>
</text>
</view>
<scrollbar/>
</view>
<simplelayout axis="y"/>
</canvas>
A customer recently asked if I had a list of Laszlo coding, performance, & style tips. I didn’t, so I thought I’d start by creating a list of performance tips. Anyway, here’s my list (in no particular order)
Did I miss anything? Feel free to clue me in, and I’ll add to the list here.
If you’re developing an OpenLaszlo application, and you’re worried about performance, like we are, you’ll be happy to know that Macromedia’s Flash Player 8 offers significant performance improvements. Click here to download the public beta.
I’m not sure if Laszlo Systems would approve of this, but I found something that improves the speed of rendering views that are changing their dimensions or positions rapidly. In our application, we need to resize and move many views all at the same time, repeatedly. During all this, we also need to adjust xoffset and yoffset since these views might be rotated. All this view morphing puts a heavy strain on the system, and performance noticeably suffers as a result. I was poking around in the OpenLaszlo source code, and discovered that when you set the xoffset or yoffset attributes using setAttribute(), setX() and setY() are invoked internally.
Our code looked something like this:
while( aBunchOfTimes ) {
//setX() and setY() invoked internally by LzView
someView.setAttribute('xoffset', someView.width/2 );
//setX() and setY() invoked internally by LzView
someView.setAttribute('yoffset', someView.height/2 );
someView.setX( anewx );
someView.setY( anewy );
}
In the above case, setX() and setY() are being invoked a total of 6 times. It turns out that setX() and setY() and costly enough operations that this is worth optimizing. How do we speed things up? I went ahead and changed the above code to look something like this:
while( aBunchOfTimes ) {
someView.xoffset = someView.width/2;
someView.yoffset = someView.height/2;
someView.setX( anewx );
someView.setY( anewy );
}
What’s going on here? setAttribute(’xoffset’) and setAttribute(’yoffset’) cause internal functions to be invoked which in turn invoke setX() and setY(). If you assign a value to xoffset and yoffset directly, as I’ve shown in this last example, the internal functions are not invoked. When I finally do invoke setX() and setY() on my own, the OpenLaszlo view system does whatever it needs to do with xoffset and yoffset to keep everything in order. It turns out this simple change made a very noticeable performance improvement in our application. (Clint said, “It’s smooth like butter!”)
Yay for open source!
It’s important to note that this optimization now depends on specific internal behavior of the OpenLaszlo view system. Obviously, this goes against the rules of code abstraction, and we run the risk that our application might break if the internal workings of the OpenLaszlo view system change significantly. In our first round of user testing, we found that performance was a significant factor in making happy users, so we think this risk is worth it.
Get ready folks, Rich Internet Applications (RIA’s) will soon have you doing things on the web which you thought were only possible with desktop applications. These new web based applications will soon have you collaborating in ways you never thought possible, increasing the overall efficiency of companies in many ways. Here are a few interesting reads which all point in this general direction:
What could this all mean? I have a few predictions:
What do you think?
In previous start-up companies I’ve worked at, it’s been implied that the official development process was something along the lines of Extreme Programming (XP) . In the book Extreme Programming Explained by Kent Beck, it is suggested that Pair Programming is an essential element to effective development with XP. So why is it that none of my managers encouraged pair programming as a regular development practice? I think one reason is that it seems counter-intuitive that a pair of developers can produce more code with higher quality on a single computer than that same pair working on two different machines.
One great thing about starting your own company is that you have more flexibility to experiment, so Clint and I have taken the opportunity to try some pair programming. Our most recent adventure into pair programming was an effort to build a new feature into our top secret project which would enhance usability greatly. The feature (which I’ll likely discuss in a future post) is really hard to implement…. so much so that of our three main competitors, all of whom who have had commercial products for over 5 years, only one of them supports this feature fully. Through careful collaboration in the design process, and then pair programing to turn our design into reality, we were able to get this feature working fairly well in a matter of several days. When I tried to build this feature out on my own previously, I probably spent 5-6 days implementing it and debugging it, with an unacceptable result.
Why is pair programming better?
I’m sure pair programming isn’t for everyone, but I think we’ve been able to solve hard problems that we wouldn’t have been able to otherwise. While we haven’t decided to make pair programming something we do 100% of the time, I think that whenever we face a difficult problem in the future, pair programming will be the natural choice.