You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jmeter-dev@jakarta.apache.org by se...@apache.org on 2006/05/15 00:41:30 UTC

svn commit: r406460 - in /jakarta/jmeter/branches/rel-2-1: src/components/org/apache/jmeter/visualizers/ src/core/org/apache/jmeter/resources/ src/jorphan/org/apache/jorphan/math/ xdocs/ xdocs/images/screenshots/ xdocs/usermanual/

Author: sebb
Date: Sun May 14 15:41:29 2006
New Revision: 406460

URL: http://svn.apache.org/viewcvs?rev=406460&view=rev
Log:
Create Summary Report visualiser

Added:
    jakarta/jmeter/branches/rel-2-1/src/components/org/apache/jmeter/visualizers/SummaryReport.java   (with props)
    jakarta/jmeter/branches/rel-2-1/xdocs/images/screenshots/summary_report.png   (with props)
Modified:
    jakarta/jmeter/branches/rel-2-1/src/core/org/apache/jmeter/resources/messages.properties
    jakarta/jmeter/branches/rel-2-1/src/jorphan/org/apache/jorphan/math/Calculator.java
    jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml
    jakarta/jmeter/branches/rel-2-1/xdocs/images/screenshots/aggregate_report.png
    jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/component_reference.xml

Added: jakarta/jmeter/branches/rel-2-1/src/components/org/apache/jmeter/visualizers/SummaryReport.java
URL: http://svn.apache.org/viewcvs/jakarta/jmeter/branches/rel-2-1/src/components/org/apache/jmeter/visualizers/SummaryReport.java?rev=406460&view=auto
==============================================================================
--- jakarta/jmeter/branches/rel-2-1/src/components/org/apache/jmeter/visualizers/SummaryReport.java (added)
+++ jakarta/jmeter/branches/rel-2-1/src/components/org/apache/jmeter/visualizers/SummaryReport.java Sun May 14 15:41:29 2006
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *  
+ */
+
+package org.apache.jmeter.visualizers;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.swing.BoxLayout;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.border.Border;
+import javax.swing.border.EmptyBorder;
+
+import org.apache.jmeter.samplers.Clearable;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.testelement.TestElement;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jmeter.visualizers.gui.AbstractVisualizer;
+import org.apache.jorphan.gui.ObjectTableModel;
+import org.apache.jorphan.math.Calculator;
+import org.apache.jorphan.reflect.Functor;
+
+/**
+ * Simpler (lower memory) version of Aggregate Report (StatVisualizer).
+ * Excludes the Median and 90% columns, which are expensive in memory terms
+ */
+public class SummaryReport extends AbstractVisualizer implements Clearable {
+	private final String[] COLUMNS = { 
+            JMeterUtils.getResString("sampler_label"),               //$NON-NLS-1$
+			JMeterUtils.getResString("aggregate_report_count"),      //$NON-NLS-1$
+            JMeterUtils.getResString("average"),                     //$NON-NLS-1$
+			JMeterUtils.getResString("aggregate_report_min"),        //$NON-NLS-1$
+            JMeterUtils.getResString("aggregate_report_max"),        //$NON-NLS-1$
+			JMeterUtils.getResString("aggregate_report_error%"),     //$NON-NLS-1$
+            JMeterUtils.getResString("aggregate_report_rate"),       //$NON-NLS-1$
+			JMeterUtils.getResString("aggregate_report_bandwidth"),  //$NON-NLS-1$
+            JMeterUtils.getResString("average_bytes"),               //$NON-NLS-1$
+            };
+
+	private final String TOTAL_ROW_LABEL 
+        = JMeterUtils.getResString("aggregate_report_total_label");  //$NON-NLS-1$
+
+	protected JTable myJTable;
+
+	protected JScrollPane myScrollPane;
+
+	transient private ObjectTableModel model;
+
+	Map tableRows = Collections.synchronizedMap(new HashMap());
+
+	public SummaryReport() {
+		super();
+		model = new ObjectTableModel(COLUMNS, 
+                new Functor[] { 
+                    new Functor("getLabel"),   //$NON-NLS-1$
+                    new Functor("getCount"),  //$NON-NLS-1$
+    				new Functor("getMeanAsNumber"),   //$NON-NLS-1$
+                    new Functor("getMin"),  //$NON-NLS-1$
+                    new Functor("getMax"),   //$NON-NLS-1$
+                    new Functor("getErrorPercentageString"),   //$NON-NLS-1$
+                    new Functor("getRateString"),  //$NON-NLS-1$
+    				new Functor("getKBPerSecondString"),   //$NON-NLS-1$
+                    new Functor("getPageSizeString"),   //$NON-NLS-1$
+                },
+                new Functor[] { null, null, null, null, null, null, null, null , null }, 
+                new Class[] { String.class, Long.class, Long.class, Long.class,
+                              Long.class, String.class, String.class, String.class, String.class });
+		clear();
+		init();
+	}
+
+	public String getLabelResource() {
+		return "summary_report";  //$NON-NLS-1$
+	}
+
+	public void add(SampleResult res) {
+		Calculator row = null;
+		synchronized (tableRows) {
+			row = (Calculator) tableRows.get(res.getSampleLabel());
+			if (row == null) {
+				row = new Calculator(res.getSampleLabel());
+				tableRows.put(row.getLabel(), row);
+				model.insertRow(row, model.getRowCount() - 1);
+			}
+		}
+		row.addSample(res);
+		((Calculator) tableRows.get(TOTAL_ROW_LABEL)).addSample(res);
+		model.fireTableDataChanged();
+	}
+
+	/**
+	 * Clears this visualizer and its model, and forces a repaint of the table.
+	 */
+	public void clear() {
+		model.clearData();
+		tableRows.clear();
+		tableRows.put(TOTAL_ROW_LABEL, new Calculator(TOTAL_ROW_LABEL));
+		model.addRow(tableRows.get(TOTAL_ROW_LABEL));
+	}
+
+	// overrides AbstractVisualizer
+	// forces GUI update after sample file has been read
+	public TestElement createTestElement() {
+		TestElement t = super.createTestElement();
+
+		// sleepTill = 0;
+		return t;
+	}
+
+	/**
+	 * Main visualizer setup.
+	 */
+	private void init() {
+		this.setLayout(new BorderLayout());
+
+		// MAIN PANEL
+		JPanel mainPanel = new JPanel();
+		Border margin = new EmptyBorder(10, 10, 5, 10);
+
+		mainPanel.setBorder(margin);
+		mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
+
+		mainPanel.add(makeTitlePanel());
+
+		myJTable = new JTable(model);
+		myJTable.setPreferredScrollableViewportSize(new Dimension(500, 70));
+		myScrollPane = new JScrollPane(myJTable);
+		this.add(mainPanel, BorderLayout.NORTH);
+		this.add(myScrollPane, BorderLayout.CENTER);
+	}
+}

Propchange: jakarta/jmeter/branches/rel-2-1/src/components/org/apache/jmeter/visualizers/SummaryReport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/jmeter/branches/rel-2-1/src/components/org/apache/jmeter/visualizers/SummaryReport.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision

Propchange: jakarta/jmeter/branches/rel-2-1/src/components/org/apache/jmeter/visualizers/SummaryReport.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jakarta/jmeter/branches/rel-2-1/src/core/org/apache/jmeter/resources/messages.properties
URL: http://svn.apache.org/viewcvs/jakarta/jmeter/branches/rel-2-1/src/core/org/apache/jmeter/resources/messages.properties?rev=406460&r1=406459&r2=406460&view=diff
==============================================================================
--- jakarta/jmeter/branches/rel-2-1/src/core/org/apache/jmeter/resources/messages.properties (original)
+++ jakarta/jmeter/branches/rel-2-1/src/core/org/apache/jmeter/resources/messages.properties Sun May 14 15:41:29 2006
@@ -61,6 +61,7 @@
 auth_manager_title=HTTP Authorization Manager
 auths_stored=Authorizations Stored in the Authorization Manager
 average=Average
+average_bytes=Avg. Bytes
 bind=Thread Bind
 browse=Browse...
 bsf_sampler_title=BSF Sampler

Modified: jakarta/jmeter/branches/rel-2-1/src/jorphan/org/apache/jorphan/math/Calculator.java
URL: http://svn.apache.org/viewcvs/jakarta/jmeter/branches/rel-2-1/src/jorphan/org/apache/jorphan/math/Calculator.java?rev=406460&r1=406459&r2=406460&view=diff
==============================================================================
--- jakarta/jmeter/branches/rel-2-1/src/jorphan/org/apache/jorphan/math/Calculator.java (original)
+++ jakarta/jmeter/branches/rel-2-1/src/jorphan/org/apache/jorphan/math/Calculator.java Sun May 14 15:41:29 2006
@@ -17,6 +17,10 @@
 
 package org.apache.jorphan.math;
 
+import java.text.DecimalFormat;
+
+import org.apache.jmeter.samplers.SampleResult;
+
 /**
  * Class to calculate various items that don't require all previous results to be saved:
  * - mean = average
@@ -26,6 +30,12 @@
  */
 public class Calculator {
 
+    private static DecimalFormat rateFormatter = new DecimalFormat("#.0");
+
+    private static DecimalFormat errorFormatter = new DecimalFormat("#0.00%");
+
+    private static DecimalFormat kbFormatter = new DecimalFormat("#0.00");
+
 	private double sum = 0;
 
 	private double sumOfSquares = 0;
@@ -41,8 +51,20 @@
 	private long maximum = Long.MIN_VALUE;
 	
 	private long minimum = Long.MAX_VALUE;
+    
+    private int errors = 0;
 	
-	public void clear() {
+    private final String label;
+    
+    public Calculator() {
+        this.label = "";
+    }
+
+	public Calculator(String label) {
+        this.label = label;
+    }
+
+    public void clear() {
 		maximum = Long.MIN_VALUE;
 		minimum = Long.MAX_VALUE;
 		sum = 0;
@@ -78,6 +100,10 @@
 		return mean;
 	}
 
+    public Number getMeanAsNumber() {
+        return new Long((long) mean);
+    }
+
 	public double getStandardDeviation() {
 		return deviation;
 	}
@@ -93,4 +119,148 @@
 	public int getCount() {
 		return count;
 	}
+
+    public String getLabel() {
+        return label;
+    }
+
+    private long startTime = 0;
+    private long elapsedTime = 0;
+    
+    public void addSample(SampleResult res) {
+        addBytes(res.getBytes());
+        addValue(res.getTime());
+        if (!res.isSuccessful()) errors++;
+        if (startTime == 0){
+            startTime=res.getStartTime();
+        }
+        elapsedTime=res.getEndTime()-startTime;
+    }
+
+    /**
+     * Returns the raw double value of the percentage of samples with errors
+     * that were recorded. (Between 0.0 and 1.0) If you want a nicer return
+     * format, see {@link #getErrorPercentageString()}.
+     * 
+     * @return the raw double value of the percentage of samples with errors
+     *         that were recorded.
+     */
+    public double getErrorPercentage() {
+        double rval = 0.0;
+
+        if (count == 0) {
+            return (rval);
+        }
+        rval = (double) errors / (double) count;
+        return (rval);
+    }
+
+    /**
+     * Returns a String which represents the percentage of sample errors that
+     * have occurred. ("0.00%" through "100.00%")
+     * 
+     * @return a String which represents the percentage of sample errors that
+     *         have occurred.
+     */
+    public String getErrorPercentageString() {
+        double myErrorPercentage = this.getErrorPercentage();
+        if (myErrorPercentage < 0) {
+            myErrorPercentage = 0.0;
+        }
+
+        return (errorFormatter.format(myErrorPercentage));
+    }
+
+    /**
+     * Returns the throughput associated to this sampler in requests per second.
+     * May be slightly skewed because it takes the timestamps of the first and
+     * last samples as the total time passed, and the test may actually have
+     * started before that start time and ended after that end time.
+     */
+    public double getRate() {
+        if (elapsedTime == 0)
+            return 0.0;
+
+        return ((double) count / (double) elapsedTime ) * 1000;
+    }
+
+    /**
+     * Returns a String that represents the throughput associated for this
+     * sampler, in units appropriate to its dimension:
+     * <p>
+     * The number is represented in requests/second or requests/minute or
+     * requests/hour.
+     * <p>
+     * Examples: "34.2/sec" "0.1/sec" "43.0/hour" "15.9/min"
+     * 
+     * @return a String representation of the rate the samples are being taken
+     *         at.
+     */
+    public String getRateString() {
+        double rate = getRate();
+
+        if (rate == Double.MAX_VALUE) {
+            return "N/A";
+        }
+
+        String unit = "sec";
+
+        if (rate < 1.0) {
+            rate *= 60.0;
+            unit = "min";
+        }
+        if (rate < 1.0) {
+            rate *= 60.0;
+            unit = "hour";
+        }
+
+        String rval = rateFormatter.format(rate) + "/" + unit;
+
+        return (rval);
+    }
+
+    /**
+     * calculates the average page size, which means divide the bytes by number
+     * of samples.
+     * 
+     * @return
+     */
+    public double getPageSize() {
+        if (count > 0 && bytes > 0) {
+            return bytes / count;
+        }
+        return 0.0;
+    }
+
+    /**
+     * formats the rate
+     * 
+     * @return
+     */
+    public String getPageSizeString() {
+        double rate = getPageSize() / 1024;
+        return kbFormatter.format(rate);
+    }
+
+    /**
+     * Throughput in bytes / second
+     * 
+     * @return
+     */
+    public double getBytesPerSecond() {
+        if (elapsedTime > 0) {
+            return bytes / ((double) elapsedTime / 1000);
+        }
+        return 0.0;
+    }
+
+    /**
+     * formats the Page Size
+     * 
+     * @return
+     */
+    public String getKBPerSecondString() {
+        double rate = getBytesPerSecond() / 1024;
+        return kbFormatter.format(rate);
+    }
 }

Modified: jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml
URL: http://svn.apache.org/viewcvs/jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml?rev=406460&r1=406459&r2=406460&view=diff
==============================================================================
--- jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml (original)
+++ jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml Sun May 14 15:41:29 2006
@@ -99,6 +99,7 @@
 <li>Add Thread Name to Tree and Table Views</li>
 <li>Add debug functions: What class, debug on, debug off</li>
 <li>Non-caching Calculator - used by Table Visualiser to reduce memory footprint</li>
+<li>Summary Report - similar to Aggregate Report, but uses less memory</li>
 </ul>
 
 <h4>Bug fixes:</h4>

Modified: jakarta/jmeter/branches/rel-2-1/xdocs/images/screenshots/aggregate_report.png
URL: http://svn.apache.org/viewcvs/jakarta/jmeter/branches/rel-2-1/xdocs/images/screenshots/aggregate_report.png?rev=406460&r1=406459&r2=406460&view=diff
==============================================================================
Binary files - no diff available.

Added: jakarta/jmeter/branches/rel-2-1/xdocs/images/screenshots/summary_report.png
URL: http://svn.apache.org/viewcvs/jakarta/jmeter/branches/rel-2-1/xdocs/images/screenshots/summary_report.png?rev=406460&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jakarta/jmeter/branches/rel-2-1/xdocs/images/screenshots/summary_report.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Modified: jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/component_reference.xml
URL: http://svn.apache.org/viewcvs/jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/component_reference.xml?rev=406460&r1=406459&r2=406460&view=diff
==============================================================================
--- jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/component_reference.xml (original)
+++ jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/component_reference.xml Sun May 14 15:41:29 2006
@@ -1587,16 +1587,22 @@
 It is important to choose the sampler names correctly to get the best results from
 the Aggregate Report.
 </p>
-<p>URL - The URL of the sample.</p>
-<p># Samples - The number of samples for the URL</p>
-<p>Average - The average time of a set of results</p>
-<p>Median - The median is the time in the middle of a set of results.</p>
-<p>90% Line - 90% of the results finished faster than the line.</p>
-<p>Min - The lowest time for the samples of the given URL</p>
-<p>Max - The longest time for the samples of the given URL</p>
-<p>Error % - Percent of requests with errors</p>
-<p>Throughput - Throughput measured in requests per second/minute/hour</p>
-<p>Kb/sec - The throughput measured in Kilobytes per second</p>
+<note>
+Calculation of the Median and 90% Line values requires a lot of memory as details of every Sample have to be saved.
+See the <complink name="Summary Report"/> for a similar Listener that does not need so much memory.
+</note>
+<ul>
+<li>Label - The label of the sample.</li>
+<li># Samples - The number of samples for the URL</li>
+<li>Average - The average time of a set of results</li>
+<li>Median - The median is the time in the middle of a set of results.</li>
+<li>90% Line - 90% of the results finished faster than the line.</li>
+<li>Min - The lowest time for the samples of the given URL</li>
+<li>Max - The longest time for the samples of the given URL</li>
+<li>Error % - Percent of requests with errors</li>
+<li>Throughput - Throughput measured in requests per second/minute/hour</li>
+<li>Kb/sec - The throughput measured in Kilobytes per second</li>
+</ul>
 </description>
 </component>
 
@@ -1703,6 +1709,33 @@
 </ul>
 <p>For details of all the methods available on each of the above variables, please check the Javadoc</p>
 <p>If the property <b>beanshell.listener.init</b> is defined, this is used to load an initialisation file, which can be used to define methods etc for use in the BeanShell script.</p>
+</component>
+
+<component name="Summary Report" index="&sect-num;.3.15" screenshot="summary_report.png">
+<description>The summary report creates a table row for each differently named request in your
+test. This is similar to the <complink name="Aggregate Report"/> , except that it uses less memory.
+<p>
+The thoughput is calculated from the point of view of the sampler target 
+(e.g. the remote server in the case of HTTP samples).
+JMeter takes into account the total time over which the requests have been generated.
+If other samplers and timers are in the same thread, these will increase the total time,
+and therefore reduce the throughput value. 
+So two identical samplers with different names will have half the throughput of two samplers with the same name.
+It is important to choose the sampler labels correctly to get the best results from
+the Report.
+</p>
+<ul>
+<li>Label - The label of the sample.</li>
+<li># Samples - The number of samples for the URL</li>
+<li>Average - The average time of a set of results</li>
+<li>Min - The lowest time for the samples of the given URL</li>
+<li>Max - The longest time for the samples of the given URL</li>
+<li>Error % - Percent of requests with errors</li>
+<li>Throughput - Throughput measured in requests per second/minute/hour</li>
+<li>Kb/sec - The throughput measured in Kilobytes per second</li>
+<li>Avg. Bytes - average size of the sample response in bytes.</li>
+</ul>
+</description>
 </component>
 
 



---------------------------------------------------------------------
To unsubscribe, e-mail: jmeter-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-help@jakarta.apache.org