diff -aur jdksrc/java/awt/EventQueue.java jdksrc_hack/java/awt/EventQueue.java --- jdksrc/java/awt/EventQueue.java Tue Jan 29 23:16:02 2002 +++ jdksrc_hack/java/awt/EventQueue.java Wed Oct 16 15:02:35 2002 @@ -136,6 +136,331 @@ private final String name = "AWT-EventQueue-" + nextThreadNum(); + // (\) responsiveness monitoring and profiling + public static long firstEventTime; + public static long userEventTime; + public static boolean paintOccurred; + private static int ncount; + + static boolean profilingEnabled = true; + private static boolean profilingInProgress; + static int startKey = java.awt.event.KeyEvent.VK_ENTER; + static int requiredPaintCount = 1; + private static int paintCount; + static int threadGroupLevel = -1; + private static java.util.List threadGroups; + static boolean generateSnapshot; + + private static Class auditClass; + private static java.lang.reflect.Method startWithThreadGroupMethod; + private static java.lang.reflect.Method simpleStartMethod; + private static java.lang.reflect.Method endWithThreadGroupMethod; + private static java.lang.reflect.Method simpleEndMethod; + private static java.lang.reflect.Method generateSnapshotMethod; + + public static void startProfiling() { + try { + java.lang.reflect.Method startMethod = getStartMethod(); + if (startMethod != null) { + System.out.println("Starting profiling ("+requiredPaintCount+" paint)..."); + if (threadGroupLevel != 0) { + int i = 0; + ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); + do { + if (threadGroups == null) + threadGroups = new java.util.ArrayList(); + threadGroups.add(threadGroup); + + startMethod.invoke(null, new Object[] { threadGroup }); + + threadGroup = threadGroup.getParent(); + } + while (threadGroup != null + && (threadGroupLevel < 0 || ++i < threadGroupLevel)); + } + else { + if (threadGroups != null) + threadGroups.clear(); + startMethod.invoke(null, new Object[] {}); + } + profilingInProgress = true; + return; + } + } + catch (Exception ex) { + ex.printStackTrace(); + } + catch (LinkageError ex) { + ex.printStackTrace(); + } + System.out.println("Profiling failed."); + profilingEnabled = false; + } + + public static void stopProfiling() { + try { + java.lang.reflect.Method endMethod = getEndMethod(); + if (endMethod != null) { + profilingInProgress = false; + if (threadGroups != null) { + int i = threadGroups.size(); + while (--i >= 0) { + ThreadGroup threadGroup = (ThreadGroup) threadGroups.get(i); + endMethod.invoke(null, new Object[] { threadGroup }); + } + threadGroups.clear(); + } + else { + endMethod.invoke(null, new Object[] {}); + } + + if (generateSnapshot) { + if (generateSnapshotMethod == null) + generateSnapshotMethod = getAuditClass().getMethod( + "generateSnapshot", + new Class[] { Integer.TYPE }); + generateSnapshotMethod.invoke(null, new Object[] { new Integer(11) }); + // 11 == Audit.DEFAULT_SNAPSHOT_OPTIONS + } + + System.out.println("...profiling stopped"); + return; + } + } + catch (Exception ex) { + ex.printStackTrace(); + } + catch (LinkageError ex) { + ex.printStackTrace(); + } + System.out.println("Profiling failed."); + } + + private static java.lang.reflect.Method getStartMethod() throws Exception { + if (threadGroupLevel != 0) { + if (startWithThreadGroupMethod == null) + startWithThreadGroupMethod = getAuditClass().getMethod( + "enableCPUProfiler", + new Class[] { ThreadGroup.class }); + return startWithThreadGroupMethod; + } + else { + if (simpleStartMethod == null) + simpleStartMethod = getAuditClass().getMethod( + "enableCPUProfiler", new Class[] {}); + return simpleStartMethod; + } + } + + private static java.lang.reflect.Method getEndMethod() throws Exception { + if (threadGroupLevel != 0) { + if (endWithThreadGroupMethod == null) + endWithThreadGroupMethod = getAuditClass().getMethod( + "disableCPUProfiler", + new Class[] { ThreadGroup.class }); + return endWithThreadGroupMethod; + } + else { + if (simpleEndMethod == null) + simpleEndMethod = getAuditClass().getMethod( + "disableCPUProfiler", new Class[] {}); + return simpleEndMethod; + } + } + + private static Class getAuditClass() throws Exception { + if (auditClass == null) + auditClass = ClassLoader.getSystemClassLoader() + .loadClass("intuitive.audit.Audit"); + return auditClass; + } + + private static void configureProfiling() { + if (enableCheck != null) + return; + + invokeLater(new Runnable() { + public void run() { + if (javax.swing.JOptionPane.showOptionDialog( + null, + getConfigPanel(), + "Profiling Configuration", + javax.swing.JOptionPane.OK_CANCEL_OPTION, + javax.swing.JOptionPane.PLAIN_MESSAGE, + null, + null, + null) == javax.swing.JOptionPane.OK_OPTION) + { + profilingEnabled = enableCheck.isSelected(); + try { + startKey = ((javax.swing.KeyStroke)keyStrokeEditor.getValue()).getKeyCode(); + } + catch (RuntimeException ex) { + ex.printStackTrace(); + } + try { + requiredPaintCount = Integer.parseInt(paintCountTextField.getText()); + } + catch (RuntimeException ex) { + ex.printStackTrace(); + } + try { + threadGroupLevel = Integer.parseInt(threadGroupTextField.getText()); + } + catch (RuntimeException ex) { + ex.printStackTrace(); + } + generateSnapshot = snapshotCheck.isSelected(); + } + + // clean + paintCountTextField = null; + threadGroupTextField = null; + snapshotCheck = null; + enableCheck = null; + keyStrokeEditor = null; + } + }); + } + + private static javax.swing.JComponent getConfigPanel() { + javax.swing.JPanel panel = new javax.swing.JPanel(); + + java.awt.GridBagConstraints gridBagConstraints; + + enableCheck = new javax.swing.JCheckBox(); + javax.swing.JLabel paintCountLabel1 = new javax.swing.JLabel(); + javax.swing.JLabel paintCountLabel2 = new javax.swing.JLabel(); + paintCountTextField = new javax.swing.JTextField(); + javax.swing.JLabel threadGroupLabel1 = new javax.swing.JLabel(); + javax.swing.JLabel threadGroupLabel2 = new javax.swing.JLabel(); + threadGroupTextField = new javax.swing.JTextField(); + snapshotCheck = new javax.swing.JCheckBox(); + + panel.setLayout(new java.awt.GridBagLayout()); + + enableCheck.setMnemonic('E'); + enableCheck.setText("Enable Profiling"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0); + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + panel.add(enableCheck, gridBagConstraints); + + keyStrokeEditor = getKeyStrokeEditor(); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0); + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + javax.swing.JComponent keyStrokePanel = (javax.swing.JComponent) + keyStrokeEditor.getCustomEditor(); + keyStrokePanel.setBorder( + new javax.swing.border.CompoundBorder( + javax.swing.BorderFactory.createTitledBorder("Start/Stop Key"), + javax.swing.BorderFactory.createEmptyBorder(0,0,6,0))); + panel.add(keyStrokePanel, gridBagConstraints); + + paintCountLabel1.setDisplayedMnemonic('P'); + paintCountLabel1.setLabelFor(paintCountTextField); + paintCountLabel1.setText("Paint Count Profiled: "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0); + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + panel.add(paintCountLabel1, gridBagConstraints); + + paintCountTextField.setColumns(3); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0); + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + panel.add(paintCountTextField, gridBagConstraints); + + paintCountLabel2.setText("(0 ignore paints, stop on the Stop key)"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 2; + gridBagConstraints.insets = new java.awt.Insets(0, 6, 6, 0); + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + panel.add(paintCountLabel2, gridBagConstraints); + + threadGroupLabel1.setDisplayedMnemonic('T'); + threadGroupLabel1.setLabelFor(threadGroupTextField); + threadGroupLabel1.setText("Thread Level Monitoring: "); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 3; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0); + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + panel.add(threadGroupLabel1, gridBagConstraints); + + threadGroupTextField.setColumns(3); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0); + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + panel.add(threadGroupTextField, gridBagConstraints); + + threadGroupLabel2.setText("(0 AWT only, -1 all)"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 3; + gridBagConstraints.insets = new java.awt.Insets(0, 6, 6, 0); + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + panel.add(threadGroupLabel2, gridBagConstraints); + + snapshotCheck.setMnemonic('S'); + snapshotCheck.setText("Generate Snapshot"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 4; + gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 10, 0); + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + panel.add(snapshotCheck, gridBagConstraints); + + enableCheck.setSelected(profilingEnabled); + paintCountTextField.setText(Integer.toString(requiredPaintCount)); + threadGroupTextField.setText(Integer.toString(threadGroupLevel)); + snapshotCheck.setSelected(generateSnapshot); + + return panel; + } + + private static java.beans.PropertyEditor getKeyStrokeEditor() { + try { + if (keyStrokeEditorClass == null) + keyStrokeEditorClass = Thread.currentThread().getContextClassLoader() + .loadClass("org.netbeans.modules.form.editors.KeyStrokeEditor"); + + keyStrokeEditor = (java.beans.PropertyEditor) + keyStrokeEditorClass.newInstance(); + keyStrokeEditor.setValue(javax.swing.KeyStroke.getKeyStroke(startKey, 0)); + return keyStrokeEditor; + } + catch (Exception ex) { + ex.printStackTrace(); + } + catch (LinkageError ex) { + ex.printStackTrace(); + } + return null; + } + + private static javax.swing.JTextField paintCountTextField; + private static javax.swing.JTextField threadGroupTextField; + private static javax.swing.JCheckBox snapshotCheck; + private static javax.swing.JCheckBox enableCheck; + + private static java.beans.PropertyEditor keyStrokeEditor; + private static Class keyStrokeEditorClass; + // (/) + public EventQueue() { for (int i = 0; i < NUM_PRIORITIES; i++) { queues[i] = new Queue(); @@ -322,11 +647,55 @@ if (eqi.next == null) { queues[i].tail = null; } + // (\) + int id = eqi.event.getID(); + if (id == 501 || id == 502 || id == 401) { + userEventTime = firstEventTime; + if (!profilingInProgress) { + System.out.println("-> user event ["+id+"]"); + if (id == 401) { + java.awt.event.KeyEvent k = + (java.awt.event.KeyEvent) eqi.event; + if (profilingEnabled && k.getKeyCode() == startKey) { + paintCount = 0; + startProfiling(); + } + else if (k.getKeyChar() == '`') + configureProfiling(); + } + } + else if (id == 401) { + java.awt.event.KeyEvent k = + (java.awt.event.KeyEvent) eqi.event; + if (k.getKeyCode() == startKey) + stopProfiling(); + } + } + // (/) return eqi.event; } } AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread); + // (\) no more events in the queue + if (paintOccurred && userEventTime > 0) { + paintOccurred = false; + ncount++; + if (profilingInProgress && ++paintCount == requiredPaintCount) + stopProfiling(); + if (!profilingInProgress) { // do not influence profiled process + long time = System.currentTimeMillis(); + long diff = time - userEventTime; + if (diff > 40000) + userEventTime = 0; + else + System.out.println(Integer.toString(ncount)+". paint done "+diff); + } + } + // (/) wait(); + // (\) queue awakened, new events arrived + firstEventTime = System.currentTimeMillis(); + // (/) } } while(true); } diff -aur jdksrc/javax/swing/JComponent.java jdksrc_hack/javax/swing/JComponent.java --- jdksrc/javax/swing/JComponent.java Tue Jan 29 23:18:56 2002 +++ jdksrc_hack/javax/swing/JComponent.java Thu Oct 17 14:31:36 2002 @@ -130,6 +130,10 @@ */ public abstract class JComponent extends Container implements Serializable { + // (\) + transient private boolean painted; + // (/) + /** * @see #getUIClassID * @see #writeObject @@ -780,6 +784,13 @@ if(clipH > getHeight()) { clipH = getHeight(); } + + // (\) + java.awt.EventQueue.paintOccurred = + !painted || clipW > 10 || clipH > 17 + || !(this instanceof javax.swing.text.JTextComponent); + painted = true; + // (/) if(getParent() != null && !(getParent() instanceof JComponent)) { adjustPaintFlags(); diff -aur jdksrc/javax/swing/JMenu.java jdksrc_hack/javax/swing/JMenu.java --- jdksrc/javax/swing/JMenu.java Tue Jan 29 23:18:58 2002 +++ jdksrc_hack/javax/swing/JMenu.java Mon Sep 23 14:08:30 2002 @@ -1230,6 +1230,12 @@ * it is not */ public void menuSelectionChanged(boolean isIncluded) { + // (\) + if (java.awt.EventQueue.firstEventTime > java.awt.EventQueue.userEventTime) { + java.awt.EventQueue.userEventTime = java.awt.EventQueue.firstEventTime; + System.out.println("-> user event [menu]"); + } + // (/) if (DEBUG) { System.out.println("In JMenu.menuSelectionChanged to " + isIncluded); } diff -aur jdksrc/javax/swing/JMenuItem.java jdksrc_hack/javax/swing/JMenuItem.java --- jdksrc/javax/swing/JMenuItem.java Tue Jan 29 23:18:58 2002 +++ jdksrc_hack/javax/swing/JMenuItem.java Mon Sep 23 14:08:19 2002 @@ -667,6 +667,12 @@ * @see MenuSelectionManager#setSelectedPath(MenuElement[]) */ public void menuSelectionChanged(boolean isIncluded) { + // (\) + if (java.awt.EventQueue.firstEventTime > java.awt.EventQueue.userEventTime) { + java.awt.EventQueue.userEventTime = java.awt.EventQueue.firstEventTime; + System.out.println("-> user event [menu]"); + } + // (/) setArmed(isIncluded); }