I noticed a pretty bad performance hole in our AWT event dispatching. In
the method EventQueue.isShutdown() (which is called once for each
dispatched event) we are calling Frame.getFrames() to iterate over every
active frame. The problem with that is that this method itself iterates
twice over the whole list, and even worse, it creates a new array on
each call. I changed this by making this list package private and let
the EventQueue.isShutdown() method iterate itself over this list and
abort as soon as possible.
2007-03-27 Roman Kennke <[EMAIL PROTECTED]>
* java/awt/Frame.java
(weakFrames): Make this generic and package private.
(noteFrame): Use generic WeakReference.
* java/awt/EventQueue.java
(isShutdown): Iterate over the weakFrames directly, rather than
using Frame.getFrames(). The latter iterates several times over
weakFrames completely and creates a new array on each call. The
former iterates only once and aborts when it finds a frame which
is displayable.
/Roman
--
aicas Allerton Interworks Computer Automated Systems GmbH
Haid-und-Neu-Straße 18 * D-76131 Karlsruhe * Germany
http://www.aicas.com * Tel: +49-721-663 968-0
USt-Id: DE216375633, Handelsregister HRB 109481, AG Karlsruhe
Geschäftsführer: Dr. James J. Hunt
Index: java/awt/EventQueue.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/EventQueue.java,v
retrieving revision 1.32
diff -u -1 -5 -r1.32 EventQueue.java
--- java/awt/EventQueue.java 25 Nov 2006 15:10:55 -0000 1.32
+++ java/awt/EventQueue.java 27 Mar 2007 09:34:16 -0000
@@ -36,30 +36,31 @@
exception statement from your version. */
package java.awt;
import gnu.java.awt.LowPriorityEvent;
import gnu.java.awt.peer.NativeEventLoopRunningEvent;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.InputMethodEvent;
import java.awt.event.InvocationEvent;
import java.awt.event.PaintEvent;
import java.awt.peer.ComponentPeer;
import java.awt.peer.LightweightPeer;
+import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.util.EmptyStackException;
/* Written using on-line Java 2 Platform Standard Edition v1.3 API
* Specification, as well as "The Java Class Libraries", 2nd edition
* (Addison-Wesley, 1998).
* Status: Believed complete, but untested.
*/
/**
* This class manages a queue of <code>AWTEvent</code> objects that
* are posted to it. The AWT system uses only one event queue for all
* events.
*
* @author Bryce McKinlay
@@ -116,34 +117,39 @@
private EventDispatchThread dispatchThread = new EventDispatchThread(this);
private boolean nativeLoopRunning = false;
private boolean isShutdown ()
{
// This is the exact self-shutdown condition specified in J2SE:
// http://java.sun.com/j2se/1.4.2/docs/api/java/awt/doc-files/AWTThreadIssues.html
if (nativeLoopRunning)
return false;
if (peekEvent() != null)
return false;
- Frame[] frames = Frame.getFrames();
- for (int i = 0; i < frames.length; ++i)
- if (frames[i].isDisplayable())
- return false;
+ synchronized (Frame.weakFrames)
+ {
+ for (WeakReference<Frame> r : Frame.weakFrames)
+ {
+ Frame f = (Frame) r.get();
+ if (f != null && f.isDisplayable())
+ return false;
+ }
+ }
return true;
}
/**
* Initializes a new instance of <code>EventQueue</code>.
*/
public EventQueue()
{
queues = new Queue[2];
queues[NORM_PRIORITY] = new Queue();
queues[LOW_PRIORITY] = new Queue();
}
/**
Index: java/awt/Frame.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/Frame.java,v
retrieving revision 1.41
diff -u -1 -5 -r1.41 Frame.java
--- java/awt/Frame.java 23 Oct 2006 19:12:36 -0000 1.41
+++ java/awt/Frame.java 27 Mar 2007 09:34:16 -0000
@@ -472,37 +472,42 @@
break;
case MAXIMIZED_BOTH:
state = ",maximized-both";
break;
case MAXIMIZED_HORIZ:
state = ",maximized-horiz";
break;
case MAXIMIZED_VERT:
state = ",maximized-vert";
break;
}
return super.paramString () + ",title=" + title + resizable + state;
}
- private static ArrayList weakFrames = new ArrayList();
+ /**
+ * This is static private because we need to access this efficiently from
+ * the EventQueue.
+ */
+ static ArrayList<WeakReference<Frame>> weakFrames =
+ new ArrayList<WeakReference<Frame>>();
private static void noteFrame(Frame f)
{
synchronized (weakFrames)
{
- weakFrames.add(new WeakReference(f));
+ weakFrames.add(new WeakReference<Frame>(f));
}
}
public static Frame[] getFrames()
{
int n = 0;
synchronized (weakFrames)
{
Iterator i = weakFrames.iterator();
while (i.hasNext())
{
WeakReference wr = (WeakReference) i.next();
if (wr.get() != null)
++n;
}