views:

167

answers:

2

In my Swing application I have the problem that when creating a new instance of a Swing form for the first time, it takes several hundreds of milliseconds. That's not really long but the subjective impression of getting slowed down is really annoying.

It happens with all forms, even a JOptionPane message or other trivial forms. (Of course larger forms need longer because of the more complex constructor)

Now I noticed that the second time creating a new form instance is significantly faster.

Since the initial startup time doesn't matter, I'm planning to create invisible instances of all important forms at startup, but that looks like a dirty hack to me. (And I'm not sure it'll even work)

My questions:

  • Is there a more elegant way to speed up the creation and display of forms?
  • What happens the first time a form is shown, that doesn't happen the second time?
+3  A: 

See this article for some performance tips. Essentially you want to keep to a bare minimum the work done in the UI thread as this impacts the rendering of components and makes it feel slow.

Swing applications have three types of threads:

  • An initial thread
  • A UI event dispatch thread (EDT)
  • Worker threads

Every application must have a main method that represents its starting point. This method runs on an initial or startup thread. The initial thread might read program arguments and initiate a few other objects, but in many Swing applications, this thread's primary purpose is to start the application's graphical user interface (GUI). Once the GUI starts for most event-driven desktop applications, the initial thread's work is done.

Swing applications have a single EDT for the UI. This thread draws GUI components, updates them, and responds to user interactions by calling the application's event handlers. All event handlers run on the EDT, and you should programmatically interact with your UI components and their basic data models only on the EDT. Any tasks running on the EDT should finish quickly so that your UI is responsive to user input. Accessing your UI components or their event handlers from other threads will cause update and drawing errors in the UI. Performing long-running tasks on the EDT will cause your application to become unresponsive because GUI events will accumulate in the event dispatch queue.

Update based on the comment, here are a couple of other things to check:

Do you have a virus scanner running? On my work machine the virus scanner checks the contents of all jar files on load, this has a huge impact on startup times. If possible try turning the Virus scanner off or disabling it for that folder.

Are you loading extra classes on startup? Ideally you should have lightweight delegates loaded that only load the implementation when first invoked (this is common practice in sWT where each menu item is associated with a lightweight delegate that instantiates the type that does the actual processing when needed). You could try profiling the application to see what is being created on startup and add in some indirection accordingly.

Rich Seller
Yes, all that is very good advice and I follow it religiously in my application(s), but in this case the only work I want to do is show a form. I don't think I would gain something if I put parts of the form creation in a thread, except perhaps many threading issues.
DR
I've updated my answer with a few more options
Rich Seller
+1 Thank you, I'll check that.
DR
+5  A: 

Since you describe the problem happening with JOptionPane, it sounds like slowness in class-loading. Are you loading over a network by any chance? It could also be garbage collection, as older windows are disposed to make room for new ones.

I'd start with garbage collection, as it's easy to test and rectify: use the -verbose:gc argument when starting Java (have to do this from a console), and note whether the GC is running during these pauses. If yes, increase the memory allotment using -Xmx, and perhaps adjust the heap sections as described here.

If it's a case of a slow network connection (and a tool like strace can help diagnose this), then you'll need to preload classes (not instantiate them). You can do this on a background thread, using Class.forName().

Other than those two obvious things, you'll need to run a profiler to get an idea of what's going on.

kdgregory
Yes, you were right about the Garbage Collection. I set the minimum heap size to 100 MB and the (subjective) speed increase was amazing.
DR