Skip to main content

Poor performance on Panel.Add() method in 1.6.0 when using null layout mgr.

2 replies [Last post]
bbettke
Offline
Joined: 2009-02-06
Points: 0

Hi, I have an older applet that uses AWT. When using 1.4.2 Plug-in performance is great. When we use the 1.5.0 (1.5.0.16 shows much worse performance) and 1.6.0 plug-in performance goes down tubes. Performance decreases as we add components to a panel container. Each successive Add() gets increasingly longer.

Timings of add() method:

Plug-in 1.4.2 (Times in ms)

31,15,0,16,16,0,0,16,16,15,16,16,16,15,16,16,16,16,93,15,0,15,16,16,15,16,15,15,15,15,16,15,15,15,15,15,16,16,16,15,15,16,16,31,16,16,31,16,16,15,15,16,16,16,16,31,32,31,15,31,16,16,15,16,31,15,16,31,16,31,31,16,16,32,32,63,15,15,31,31,16,31,31,16,32,16,16,15,32,32,15,15,31,31,31,31,16,16,31,16

Plug-in 1.6.0 (Times in ms)

31,31,15,31,31,31,31,31,32,47,46,31,47,47,63,47,62,62,62,62,79,78,78,78,78,94,93,94,93,110,110,109,109,125,125,125,141,141,140,141,156,157,172,156,171,187,188,203,219,218,203,203,234,219,218,219,235,234,266,250,266,265,265,297,281,281,296,313,313,328,328,328,328,344,344,375,375,390,375,407,375,391,390,406,390,422,407,422,422,437,469,469,469,469,485,516,484,500,515,532

These timings are considerably different and are unacceptable. I need a fix or a workaround that will address this problem. Moving to Swing at this point will involve a great deal of effort and money of which there are neither.

The above timings were generated from the following code applet.

SAMPLE CODE: (Sorry for the indent issues)

import java.applet.Applet;
import java.awt.Button;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TestApplet extends Applet implements ActionListener {
int i = 0;
TreeView tv = null;

public void init() {
setLayout(new java.awt.BorderLayout());
tv = new TreeView();
Button b1 = new Button("Add label");
b1.addActionListener(this);
add(b1,java.awt.BorderLayout.WEST);
add(tv, java.awt.BorderLayout.CENTER);
}
public void actionPerformed(ActionEvent event)
{
long addElapsed = 0;

tv.setVisible(false);
for(int j=1; j<21; j++)
addElapsed += tv.addLabel(i++);

tv.setVisible(true);
System.out.println("Add Label Elapsed = " + addElapsed + "ms.");
}
public class TreeView extends Panel {
public TreeView()
{
setLayout(null);
this.setSize(600,400);
}
public long addLabel(int i)
{
Label l = new Label("Label" + i);
l.setBounds(10, i*15, 50, 10);
l.setLocation(10, i*15);
long currentTime = System.currentTimeMillis();
add(l);
long elapsedTime = System.currentTimeMillis() - currentTime;
return elapsedTime;
}
}
}

I used the profiler in Netbeans and inclulde the AWT package and came up with the following:

TreeView.addLabel
--->java.awt.Container.add(java.awt.Component)
-------->java.awt.Container.addImpl(java.awt.Component, Object, int)
------------>java.awt.Label.addNotify()
---------------->java.awt.Component.addNotify()
-------------------->sun.awt.windows.WPanelPeer.restack() (615 ms, 91.1%)
------------------------>self time (376ms, 55%)
------------------------>java.awt.windows.WPanelPeer.restack(java.awt.Container, java.util.Vector) (230ms, 33%) Invoked 20 times
---------------------------->java.awtContainer.getComponent(int) Invoked 12210 times
---------------------------->java.awtContainer.getComponentCount() invoked 12230 times
---------------------------->java.utl.Vector.add(Object) invoked 12210 times
---------------------------->java.awt.Component.isLightWeight() invoked 24420 times.

There were 600 components already in the container and 20 were being added when the snapshot was taken. The problem seems to be in the restack() method of the java.awt.windows.WPanelPeer class. Not knowing the code, I would assume the there is SOME reordering going on for the zorder of the components. As you can see there are a large number of iterations for the getComponent(), getComponentCount(), add() for the vector and isLightWeght(). Maybe this algorithm needs to be looked at and re-optimized.

I looked at the sun.awt.windows.WPanelPeer.restack(Container, Vector) method which I got the source from openJDK. It pretty much maps to the trace above. I am assuming, since I'm not set up to debug through the code that the large number of iterations is coming from some recursion that is being done, it appears that the code goes through each component in the container, checks to see if the container is a lightweight and a container iteself, and if so calls itself with the component as the container. There is just one thing I don't understand. Why would it be doing that. As far as I understood java.awt.Label components are not containers. So why would the recursion be taking place, unless somewhere down the line they are being wrapped by a container. If that's the case than perhaps thats the problem.

This is really going to be a mahor problem for us. If someone could help take a look at this it would be greatly appreciated.

Thanks.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
bbettke
Offline
Joined: 2009-02-06
Points: 0

Looking at the code for the java.awt.windows.WPanelPeer.restack(java.awt.Container, java.util.Vector) method perhaps some changes can be made to increase performance slightly.

1. In the for loop, the condition is a call to java.awtContainer.getComponentCount(). This in turn is being called, 12,230 times. If it is not necessary to keep getting the count while processing each element, than it can be moved before the loop and it will only be called 20 times, in the above example, or once for each add().

2. There are two calls to isLightweight() method for a total of 24,420 invocations. If the return value is stored from the first call and used where the second one is called than that would reduce the number of calls by half.

Granted these would only add up to roughly 5% improvement, but it's something.

bbettke
Offline
Joined: 2009-02-06
Points: 0

Re-looking at the numbers I don't think the recursion has anything to do with. If there are 600 components in the container already and 20 more are added than for each add it will look at each of the 600 existing components giving a number like around 12,000. So that sounds reasonable given the algorithm.