You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by fs...@apache.org on 2017/02/18 14:31:45 UTC

svn commit: r1783558 - /jmeter/trunk/src/components/org/apache/jmeter/visualizers/StatVisualizer.java

Author: fschumacher
Date: Sat Feb 18 14:31:45 2017
New Revision: 1783558

URL: http://svn.apache.org/viewvc?rev=1783558&view=rev
Log:
Make GUI more responsive when it gets a lot of events.
Convert Aggregate Report to use a queue, when new rows are to be inserted.
Update the model (or at least notify the gui) only periodically.
That way we get the update of the model out of the busy path of the swing
event loop.

Bugzilla Id: 60687

Modified:
    jmeter/trunk/src/components/org/apache/jmeter/visualizers/StatVisualizer.java

Modified: jmeter/trunk/src/components/org/apache/jmeter/visualizers/StatVisualizer.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/visualizers/StatVisualizer.java?rev=1783558&r1=1783557&r2=1783558&view=diff
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/visualizers/StatVisualizer.java (original)
+++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/StatVisualizer.java Sat Feb 18 14:31:45 2017
@@ -26,8 +26,10 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.nio.charset.Charset;
+import java.util.Deque;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedDeque;
 
 import javax.swing.BoxLayout;
 import javax.swing.JButton;
@@ -36,6 +38,7 @@ import javax.swing.JFileChooser;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.JTable;
+import javax.swing.Timer;
 import javax.swing.border.Border;
 import javax.swing.border.EmptyBorder;
 
@@ -92,6 +95,8 @@ public class StatVisualizer extends Abst
 
     private final Map<String, SamplingStatCalculator> tableRows = new ConcurrentHashMap<>();
 
+    private Deque<SamplingStatCalculator> newRows = new ConcurrentLinkedDeque<>();
+
     public StatVisualizer() {
         super();
         model = StatGraphVisualizer.createObjectTableModel();
@@ -116,32 +121,21 @@ public class StatVisualizer extends Abst
 
     @Override
     public void add(final SampleResult res) {
-        JMeterUtils.runSafe(false, new Runnable() {
-            @Override
-            public void run() {
-                SamplingStatCalculator row;
-                final String sampleLabel = res.getSampleLabel(useGroupName.isSelected());
-                synchronized (lock) {
-                    row = tableRows.get(sampleLabel);
-                    if (row == null) {
-                        row = new SamplingStatCalculator(sampleLabel);
-                        tableRows.put(row.getLabel(), row);
-                        model.insertRow(row, model.getRowCount() - 1);
-                    }
-                }
-                /*
-                 * Synch is needed because multiple threads can update the counts.
-                 */
-                synchronized(row) {
-                    row.addSample(res);
-                }
-                SamplingStatCalculator tot = tableRows.get(TOTAL_ROW_LABEL);
-                synchronized(tot) {
-                    tot.addSample(res);
-                }
-                model.fireTableDataChanged();
-            }
+        SamplingStatCalculator row = tableRows.computeIfAbsent(res.getSampleLabel(useGroupName.isSelected()), label -> {
+           SamplingStatCalculator newRow = new SamplingStatCalculator(label);
+           newRows.add(newRow);
+           return newRow;
         });
+        synchronized(row) {
+            /*
+             * Synch is needed because multiple threads can update the counts.
+             */
+            row.addSample(res);
+        }
+        SamplingStatCalculator tot = tableRows.get(TOTAL_ROW_LABEL);
+        synchronized(lock) {
+            tot.addSample(res);
+        }
     }
 
     /**
@@ -152,6 +146,7 @@ public class StatVisualizer extends Abst
         synchronized (lock) {
             model.clearData();
             tableRows.clear();
+            newRows.clear();
             tableRows.put(TOTAL_ROW_LABEL, new SamplingStatCalculator(TOTAL_ROW_LABEL));
             model.addRow(tableRows.get(TOTAL_ROW_LABEL));
         }
@@ -187,6 +182,15 @@ public class StatVisualizer extends Abst
         opts.add(saveTable, BorderLayout.CENTER);
         opts.add(saveHeaders, BorderLayout.EAST);
         this.add(opts,BorderLayout.SOUTH);
+        
+        new Timer(500, e -> {
+            synchronized (lock) {
+                while (!newRows.isEmpty()) {
+                    model.insertRow(newRows.pop(), model.getRowCount() - 1);
+                }
+            }
+            model.fireTableDataChanged();
+        }).start();
     }
 
     @Override