Tuesday, April 26, 2011

Introduction to Mind-Maps

Gigantt draws lots of inspiration from Mind-Maps. They're terribly useful things, not just for brainstorming but also for managing projects. Just though I'd share a great introduction to mind-maps I've read today on InstantShift. Go read it - it's well written.

I've written about mind-maps way back when I started this blog. 

Nothing beats their ability to capture ideas quickly and to manipulate a tree of ideas visually with drag-and-drop. I do like to think of Gigantt is a work-plan oriented collaborative mind-map with support for more complex plan topologies. I think any project management tool that's slower to operate than a mind-map is a waste of time.

Monday, April 11, 2011

Smooth Rendering in Flex

What do you do if the amount of interactive items you give Flex to render makes it choke and drop the frame rate to 0.3? This is something we encountered recently at Gigantt, and I thought I'd share our solution to the problem.

The Problem

So let's say you have a few hundred complex interactive items that you want to add to the stage. In our case we sometimes need to fit a very large number of "task" objects into the screen by scaling them down, because that's part of Gigantt's infinite-zoom approach.
Giving Flex too many items to render at once just chokes it. Flex tries to render them all at the next frame and just doesn't make it. It tries to do something called phased instantiation, but most of the time this seems to do more harm than good. You can end up with a Flex application that, instead of rendering at a smooth - let's say, 25 FPS - pauses every once in a while to render a bunch of items, which results in a really choppy UI experience. This becomes especially clear if you use lots of animation.
To be sure, if you constantly need to render more than Flex can do in 1/25th of a second then you're out of luck. But in many cases rendering happens in bursts. This is because one of the more costlier operations you can do with interactive objects in Flex is to add them to the stage. Once they're staged moving them around and even transforming and scaling them is much quicker.
To top that all off, you never know just how much free CPU your customer's machine is going to have. Maybe they're running a bunch of stuff already and there just isn't enough juice left for Flex. So you can't really decide in advance how many items per second you feel comfortable rendering, because this number will vary between machines.

The Solution

What we need is a way to make sure our application never drops below 25 FPS so that everything feels snappy. In the current development version of Gigantt we ended up implementing something we call an idle rendering queue. In essence what we do is divide all our rendering operations into reasonably sized chunks that are rather small. We then measure the application's actual frame rateAs soon as we detect a high enough frame rate we know that Flex is done rendering whatever it worked hard to render and that the engine is free to handle more work. We then take another chunk out from the queue and feed it to Flex. Our application's declared frame rate is 60 FPS, but it never really reaches that number unless your have a strong CPU or you're not rendering a lot of new items. By throttling our rendering jobs according to what the user's machine is able to handle at each point in time we make sure our application is never too heavy for whatever machine is running it. The frame rate remains the same - a minimum of 25 FPS - it might just take it more time to actually show every interactive object. If you implement a ZUI like Google Maps (or Gigantt) you can naturally allow "farther away" elements to render in the background, so to speak. 

This isn't ideal. An ideal solution would be something that's able to render as many items as can be discerned on screen, so that if you zoom in you get a continuous impression of the items already "being there". But that's an extraordinarily large number of polygons to render (in the trillions, really). Our approach does the best with what we have by providing a seamless zoom-in effect that takes advantage of the fact that it takes the eye a few hundred milliseconds to actually see what's being rendered on screen before the user can make a conscious decision where next to zoom-in to. This optimization is neat trick that we thought we'd share with the world. You can expect to enjoy it in the next release of Gigantt in a few weeks.