Digital Media Web Blogs > Web

How to make a desktop application in Java that doesn't suck


Related link: http://www.topologi.com

My company, Topologi
is releasing our new product line next week. This isn't really a pitch for the products (repeat after me "I will try! I will buy!") but more about the particular solutions I have come up with to making a large desktop application with Java that has just as good performance as a native Windows application.

Suckitude

Now, let me start off by saying I don't mean good performance in the benchmarking sense: Java programs have, if well written, just as good performance as C++ programs when they are up and running. Indeed, as Java uses SSE instructions now, benchmark performances may exceed typical C++ binaries compiled without SSE.


But a real desktop application is competitive with other resources: in particular with other applications and with the Windows virtual memory system. Users have multiple applications running, they minimise them, or quickly switch between them. Lets call poor performance in these areas suckitude.

We faced two sets of problems. The first were issues with Windows and Java:

  • Slow start-up times: our application uses a ton of libraries, and even though we did lazy initialization, start-up time was just too much. The initial prototypes of the product had used custom class loaders to reduce the problem, but we abandoned them because they didn't fit. Instead we had tried a little reflection, lazy intitialization, and invoking many methods through BeanShell scripts.
  • Java didn't know how much memory was optimally available. It just tries to reserve as much as it can up to some limit.
  • Java GC does not interact particularly happily with paging. You don't want too multiple JVMs running unless they have quite small heaps, but if they have small heaps they are useless for decent-sized work.
  • Java scheduling and memory management does not have any idea of foreground/background. They don't have any way to act differently when the Java application is not the foreground application or when the application is minimised. Consequently, it has no built-in way to be a good citizen.

The second came from issues relating to the size of our application. The Professional Editions contained a ton of functionality, but

  • Download times were becoming too long because of the large file size. We had found we had to include our own JRE because we couldn't be sure what JRE the user's had on their systems.
  • Users often bought the system for specific funtionality
  • Large WIMP applications are only "intuitive" for habituated power-users (sometimes called "the Adobe syndrome" unfairly: Adobe's interfaces are exemplorary for reducing this problem that any—and everyone's—large application faces, in particular by moving beyond WIMP to using floating pallettes and differentiated products, backed up by their training programs). Users wouldn't look more than one menu deep to find anything, and wouldn't look things up in help files even when the help was there.


Inductive, Task-Oriented GUI Design

It is that last issue that caused the lightbulb. A few years back the practicality boffins at MicroSoft, in particular, started espousing inductive user interfaces. Jan Miksovsky says " I think its most significant contribution is ... that tight constraints around the clarity of a page title can drive an interface's design." and "The answer proposed by the inductive UI model is that a single task is something that can be stated (ideally, directly on the screen) in a single concise question or statement in natural language.".

MicroSoft since have since moved on to personas, see this blog conversation: Who are you? Mort, Elvis or Einstein Inductive vs Productive UIs, and a response. This is probably a logical step: when you need to elaborate tasks, you have to ask "who" before "what." The cynic in me wonders whether inductive interfaces are too thin-client friendly for MS, IYKWIM? (An check out this great article to see why personas won't work for tomato sauce.)

Inductive interfaces, wizards, typical multi-stage web-based interfaces are all task-based.


Task-Orientedness as an Architecture


The issue I set myself was
Is there a way to re-factor our existing functionality
to reduce suckitude to the same limits as native Windows
applications?

The solution I came up with was to refactor our application as a suite of independent utilities. Rather than kick against the pricks of Java's applet/servlet focus, why not accept it and love it: use it as the impetus for a more task-oriented user interface?

The utilities each group together three to six related tasks. The utilities are independent in the sense that they each can be downloaded independently, but each utility can launch another in the same JVM, using a pulldown menu on the toolbar. They are virtual utilities: they look like independent programs but they run in the same Windows process.

The exemplar was WinZIP: a simple interface with a small number of toolbar buttons. Each button would be an inductive-style verb+type statement. We threw out menus, though the toolbars ended up a little menu like.

Each utility launches with its own class-loader. Each utility has a "Lauch Utility" button that invokes whichever other Topologi utilities have been installed: if it is the first launch of that utility in the current JVM, the utility is launched by its own class loader. Closing the window of a utility does not cause the destruction of the utility's Java object: instead it acts like a smart window-minimization. The utility frees up as many objects as possible (trees, files, etc) and hides the utility window. Next time the utility is launched from another utility, it comes up almost instantly.

Results

So here is how the problems fared:

  • Slow start-up times: The initial start-up time is less, because only the libraries needed for the utility need to be loaded. The time to launch a new utility from an existing one is smaller, because there is no need to launch a new JVM. Indeed, if the utility was previously launched then closed but there was always some utility keeping the JVM alive, it may open instantly.
  • Java didn't know how much memory was optimally available. I blogged last year about this: the utilities are invoked through a executable which calculates the optimal heap.
  • Java GC does not interact particularly happily with paging. Using the same JVM rather than launching others reduces the pressure that active pages will be paged out.
  • Java scheduling and memory management does not have any idea of foreground/background. Again, by keeping everything in one JVM, we reduce the liklihood of
  • Download times:
    Each utility is substantially smaller:
    often less than 20% of the size of the Professional
    Edition. Just as helpfully,
    we figured that by now most people have upgraded
    to JRE 1.4.2 or JRE 1.5, so we didn't need to
    rebundle the JRE.

  • Users often bought the system for specific funtionality:
    Obviously the utility idea caters for this well.

  • Large WIMP applications are not "intuitive"
    Removing the menus, and giving a clear, small set
    of tasks on the buttons makes the interface easier
    to figure out.
    We also simplified the help files and made them
    available in the first tab.

In our performance goals from three years before, we had a launch limits of 4 seconds to get a splash screen, 4 second to get the application frame and main menu, and 4 seconds to get the main GUI items functional (4:4:4), on our target PC. We had gone pretty well, but load times were hindering us, and one prototypes of a recent product we had degraded closer to 8:8:16, which represented high suckitude. The utilities are each about 1:3:2 for the first one launched, 0:2:2 for the initial fast lauch of one utility from another, and 0:0:0 for subsequent fast launch times. Yahoo.


It is a good architecture: it matches Java's and Window's
natures quite well. To actually spit up the Topologi
Professional Edition completely along these lines would
take at least 20 utilities, so we started off with 5
and enabled fast launch to the simpler Mark Editor
product,
and with several more utilities in the pipeline.

In one sense, what we are doing is moving the top-level menus to the Windows Start menu. This in effect moves up all the underlying interace objects up one level. Users select the utility (which groups related tasks) and then have the tasks staring them in the face, rather then hidden under one or two layers of menus. Similarly when switching to help files the user sees the help belonging to the tasks, rather than amalgamated help for all functionality, which requires searching and head-scratching.

The limitation currently is that fast-launching only works from inside a utility. If you have one utility open and launch another from the Start menu, say, you get two JVMs. I may look at having our custom launchers find an existing JVM before launching a utility in a new one, and there may be some way to use the JDIC Windows Quicklaunch Toolbar to keep the JVM alive, but that is down the road.

I don't know whether moving to a task-oriented, utility/mini-program approach will work on your application, but I certain commend it. It makes Java applications feel like different beasts.

Java experts often recommend custom class loaders as the way to reduce initial loadtime. What no-one (who I have read, at least) suggested was what I found: that to use class-loaders successfully you have to design your program so that the user interacts in chunks of related tasks, rather than the WIMP approach of having most functions theoretically available at the same time (which can happen as a result of removing modality from a WIMP interface, for example, in HCI jargon).

Grouped Tasks -> Virtual Utilities -> Fast Loading & smaller size -> good suckitude

Categories





AddThis Social Bookmark Button



Comments (2)
Read More Entries by Rick Jelliffe.

2 Comments

soulguru said:

Interesting Design
I came to the conclusion back in 2000 at a internet startup company I was working for. I have noticed most heavy weight Swing App I develop take on a specific design every single time. It usually takes on a pluggable interface design with a common subsystem which can load on demand and manager the plugin components. Yeah, I have also noticed most people tell you to create your own classloaders and tweak them. I think that is the common one that works for most people, but there are always other solutions.

rjelliffe said:

The Not-Adobe Syndrome
Update: I have slightly updated this blog from its original version to clarify that in mentioning the so-called "Adobe syndrome" I wasn't meaning any slur on their current interfaces or suggesting that Adobe products would necessarily suffer from this syndrome any more or less than any other large desktop application! (They did not contact me about this, by the way.)

In fact, the Adobe solution to the deficiencies of large WIMP interfaces is pretty much the same as what I suggest for Java applications: instead of a single omnibus application they have moved to differentiated products (e.g. ImageReady and PhotoShop) which can be fast called from each other directly; and instead of high fanout menus as the primary interaction method they have moved to tabs and toolbars (in their case, their "http://swpat.ffii.org/patents/effects/palette/index.en.html"
>US patented
>tabbed palettes")).

MicroSoft's recent interfaces have similarly moved away from WIMP, though towards a task-based, more web-browsery interface.

Topics of Interest

Related Books

Archives


 
 


Or, visit our complete archive.  

Stay Connected