JDK-5031147 : REGRESSION: Panel.add(Component C) is slow with large number of Components
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.2,5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000,windows_xp
  • CPU: x86
  • Submitted: 2004-04-13
  • Updated: 2010-12-29
  • Resolved: 2010-12-29
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4-poolResolved
Related Reports
Duplicate :  
Description

Name: jl125535			Date: 04/13/2004


FULL PRODUCT VERSION :
java version "1.5.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b32c)
Java HotSpot(TM) Client VM (build 1.5.0-beta-b32c, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
We have a Web Application that uses a Java Applet to displays the Table of Contents for online documentation for IBMs z/OS line of servers .  The documents have anywhere from 20 to 2000+ topics in them depending on the book.   When trying to navigate the Table of Contents for larger books with lots of topics we are experiencing large performance delays when running Internet Explorer with the JRE1.5.1-beta plug-in.  We also experience performance delays with the JRE 1.3.1_06 plug-in, but not quite as bad.    We gave up trying to use JRE 1.4.x due to massive performance delays on all sized documents.  We experience NO DELAY AT ALL when running Internet Explorer with it's native Java support.

You will find a simple applet below that demonstrates this problem.  It includes some timing statements that can be seen in the Java Console when running the Applet.  The most recent timing data we have is shown here:

IE with JRE 1.5.1-beta:
Time to expand node:  42531 ns
Time to contract node: 11357 ns

IE with JRE 1.4.2_04:
Time to expand node:  4086ns
Time to collapse node: 1002 ns

IE with JRE 1.3.1_06:
Time to expand node:  16113 ns
Time to contract node: 7150 ns

IE without any plugins:
Time to expand node:  130 ns
Time to contract node: 40 ns

With JRE 1.4.2_04, the performance was pretty good.  I would be satisfied if whatever was changed in 1.4.2_04 was also changed in future releases of 1.5.
I believe 1.4.2_04 performance would be acceptable to our users. 

We would really appreciate a quick resolution to this problem, as it causes our users a lot of difficulty and frustration.  So much so that we now have the following statment in our User's Guide:  "For performance reasons, we recomend using Internet Explorer without a Java Plug-in."  and we give instruction on how to disable the various plug-ins.    Thanks for your time and effort.

REGRESSION.  Last worked in version tiger-beta

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1.  Copy the source code below to the files specified.

2.  Compile the applet.  Command we used:
c:\jdk1.3.1_06\bin\javac panelTest.java

3.  Build the jar file. Command we used:
c:\jdk1.3.1_06\bin\jar -cfm panelTest.jar manifest.mft *.class

4.  Be sure that the JRE 1.5.1-beta plug-in is configured to run for IE.

5.  Open the file panelTest.html in Internet Explorer.

6.  Click on the node that says "Click Here" to expand the tree.

7.  After the tree has succesfully expanded, click once more on the node that says "Click Here" to collapse the tree.

8.  Repeat steps 5 - 7 with Internet Explorer without a plug-in configured to see the performance comparison.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
When performing step 6 from above, we expect to see the tree expand, adding some 500 sub nodes, in a short interval of time.

When performing step 7 from above, we expect to see the tree collapse, removing some 500 sub nodes, in a short interval of time.
ACTUAL -
When performing step 6 from above with IE running with the JRE 1.5.1-beta plug-in there is approximately a 4 - 10 second realtime delay before the resulting expanded tree is displayed.  With IE and no plug-in there is no discerable delay.

When performing  step 7 from above with IE running with the JRE 1.5.1-beta plug-in there is approximately a 2-6 second realtime delay before the resulting collapsed tree is displayed.  With IE and no plug-in there is no discernable delay.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
No error messges recieved.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
Copy the code for the 3 files below to the file names specified.

*************************************
File name:  panelTest.html

<HTML><body>
<APPLET  ARCHIVE = "panelTest.jar" CODE = "panelTest.class" CODEBASE = "." WIDTH = "250" HEIGHT = "100%" NAME = "panelTest">
</body></HTML>


*************************************
File name:  manifest.mft

Main-Class: panelTest


*************************************
File name:   panelTest.java


import java.awt.*;
import java.lang.*;
import java.applet.*;
import java.io.*;
import java.util.*;
import java.awt.event.*;
import java.net.*;

public class panelTest extends Applet { 
    // applet constructor
    public void init() { 
        try{
            ephTree tree = new ephTree(this);
            this.add("Center", tree);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    public void start()
    {
        try{
                System.out.println("start called");
            this.setVisible(true);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
    //  ephTree class - maintains tree structure
    public class ephTree extends ScrollPane { 
                 // panel contains the tree structure
                 public Panel treePanel;
                 // maintains a list of visible nodes in display order
                 Vector nodes = new Vector(20,1);
                 // constructor
                 public ephTree(Applet applet){
                     super();
                     this.getHAdjustable().setUnitIncrement(10);
                     this.getVAdjustable().setUnitIncrement(20);
                     treePanel = new Panel(null);
                     treePanel.setBackground(Color.white);
                     treePanel.setSize(200, 1000*20);
                     this.setSize(applet.getSize());
                     this.setBackground(Color.white);
                     this.add(treePanel);
                     for(int i = 0; i < 1000; i++)
                     {
                                 ephNode node = new ephNode("Node " 
                                     + String.valueOf(i), this, (i==4));
                                 node.setLocation(0, 20*i);
                                 this.treePanel.add(node);
                                 nodes.addElement(node);
                                 node.repaint();
                     }
                 }
                 // performs the expand function
                 private void showNodes()
                 {
                 treePanel.setSize(200, 1500*20);
                     for(int i=0; i < 500; i++)
                     {
                                 ephNode node = 
                                     new ephNode("    Sub Node " 
                                         + String.valueOf(i), this, false);
                                 long t1 = System.currentTimeMillis();
                                 /*****  PROBLEM METHOD 
**********************/
                                 this.treePanel.add(node);
                                 long t2 = System.currentTimeMillis();
                                 System.out.println("Panel.add took " 
                                     + String.valueOf(t2-t1) + "ns");
                                 nodes.insertElementAt(node, 5+i);
                     }
                     repositionNodes();
                 } 
                 // performs the collapse function
                 private void hideNodes()
                 {
                 treePanel.setSize(200, 1000*20);
                     for(int i=500; i > 0; i--)
                     {
                                 ephNode node = 
                                    (ephNode)nodes.elementAt(4+i);
                                 this.treePanel.remove(node);  
                                 nodes.removeElementAt(4+i);
                     }
                     repositionNodes();
                 }
                 // repositions nodes after an expansion or contraction event
                 private void repositionNodes()
                 {
                     int size = nodes.size();
                     ephNode node;
                     for(int i = size-1; i >= 0; i--)
                     {
                                 node = (ephNode)nodes.elementAt(i);
                                 node.setLocation(0, 20*i);
                     }
                     treePanel.validate();
                     this.validate();
                 }
    }
    // ephNode class - represents an indifidual node
    public class ephNode extends Panel{
                 // convenience reference to this node, needed in 
                 // in-line classes
                 private final ephNode treeNode = this; 
                 //handle to ephTree class
                 private ephTree tree;
                 private NodeLabel label;
                 // Constructor
                 //
                 // Initializes node
                 //
                 public ephNode(String text, ephTree tree,
                                boolean expandable){
                     super(null); 
                     this.tree = tree; 
                     createNode(text, expandable);
                 }
                 // initializes the GUI components for a node
                 private void createNode(String text, boolean expandable){ 
 
                     this.setBackground(Color.white); 
                     label = new NodeLabel(text, expandable);
                     label.setLocation(0,0);
                     this.add(label);
                     this.setSize(label.getSize().width, 20);
                 }
                 // draws the tree lines on the right portion of this node
                 // if necessary
                 // tells the nodes image and sign to draw themselves
                 // if necessary
                 public void paint (Graphics g){
                     label.repaint();
                 }
                 // class NodeLabel - builds label for this node
                 private class NodeLabel extends Canvas implements 
MouseListener { 
                     private String text = "";
                     private boolean expandable = false;
                     private boolean expanded = false;
                     public NodeLabel(String labelText, boolean 
expandable){ 
                                 super();
                                 this.text = labelText;
                                 this.expandable = expandable;
                                 if(expandable)
                                     this.text += " Click Here";
                                 this.setSize(150, 20);  
                                 if(expandable)
                                     this.addMouseListener(this);
                     }
                     public void paint(Graphics g)
                     {
                                 Dimension size = this.getSize();   
                                 g.setColor(Color.white);  
                                 g.fillRect(0,0, size.width, size.height); 
 
                                 if(expandable)
                                     g.setColor(Color.blue);
                                 else
                                     g.setColor(Color.black);  
                                 g.drawString(text, 0, 15);  
                     }
                     public void mouseClicked(MouseEvent me) {  
                                 long t1 = System.currentTimeMillis();
                                 tree.setCursor(new 
Cursor(Cursor.WAIT_CURSOR)); 
                                 if(expanded)
                                 {
                                    expanded = false;
                                    tree.hideNodes();
                                 }
                                 else{
                                    expanded = true;
                                    tree.showNodes();
                                 }
                                 tree.setCursor(
                                     new Cursor(Cursor.DEFAULT_CURSOR));
                                 long t2 = System.currentTimeMillis();
                                 System.out.println(
                                    "Total time to process event: " 
                                    + String.valueOf(t2-t1) + "ns\n");
                     }
                     public void mouseEntered(MouseEvent me) {} 
                     public void mouseExited(MouseEvent me) {} 
                     public void mousePressed(MouseEvent me) {} 
                     public void mouseReleased(MouseEvent me) {}
                 }
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
We recommend in our documentation that users of our product use Internet Explorer without any Java plug-ins enabled.  We also provide instructions on how to disable the plug-ins.

Release Regression From : 1.4.2_04
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.

(Incident Review ID: 245017) 
======================================================================

Comments
WORK AROUND Name: dfR10261 Date: 04/30/2004 I propose some workaround for this bug. I set EPHTree invisible before adding nodes in method showNodes() and I set visible EPHTree when all nodes was added. After that, I have noticed 60% performance improvement. It is possibly twinkle of the container, but I did not catch sight of that in my tests. ###@###.### 2004-04-30 ======================================================================
30-04-2004

EVALUATION This seems to be an AWT issue, assigning it to AWT team for evaluation ###@###.### 2004-04-13 Name: dfR10261 Date: 04/30/2004 One of the plausible reason of the performance decrease is a new functionality adding in 1.5. This functionality in addNotify() method allows to place component in correct z-order. Another reason is creating peer separately for each Component. The best way is to add all components in the container and then create peers. However, we do not provide API for this functionality. In Workaround section, I propose some mechanism for evasion of the problem with peers. Moreover, I am looking for decision with improvement in performance for z-order recalculating. ###@###.### 2004-04-30 ======================================================================
30-04-2004