From 19da79cbf332a76757b22576b2b406722a66f3c8 Mon Sep 17 00:00:00 2001 From: Philippe M Date: Sun, 3 Apr 2016 14:34:49 +0200 Subject: [PATCH 1/7] BUG_59258 --- .../jmeter/visualizers/TableVisualizer.java | 66 ++++++++++++++++++- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/src/components/org/apache/jmeter/visualizers/TableVisualizer.java b/src/components/org/apache/jmeter/visualizers/TableVisualizer.java index 1bf071eadbb..84d556e7147 100644 --- a/src/components/org/apache/jmeter/visualizers/TableVisualizer.java +++ b/src/components/org/apache/jmeter/visualizers/TableVisualizer.java @@ -20,9 +20,12 @@ import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Container; import java.awt.FlowLayout; +import java.awt.Font; import java.text.Format; import java.text.SimpleDateFormat; +import java.util.concurrent.atomic.AtomicLong; import javax.swing.BorderFactory; import javax.swing.ImageIcon; @@ -32,6 +35,7 @@ import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; +import javax.swing.SwingConstants; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.table.TableCellRenderer; @@ -48,19 +52,26 @@ import org.apache.jorphan.gui.RendererUtils; import org.apache.jorphan.gui.RightAlignRenderer; import org.apache.jorphan.gui.layout.VerticalLayout; +import org.apache.jorphan.logging.LoggingManager; import org.apache.jorphan.reflect.Functor; +import org.apache.log.Logger; /** * This class implements a statistical analyser that calculates both the average * and the standard deviation of the sampling process. The samples are displayed * in a JTable, and the statistics are displayed at the bottom of the table. * - * created March 10, 2002 - * */ public class TableVisualizer extends AbstractVisualizer implements Clearable { - private static final long serialVersionUID = 240L; + private static final long serialVersionUID = 241L; + /** Logging. */ + private static final Logger log = LoggingManager.getLoggerForClass(); + + private static final int MAX_MEMORY_OCCUPATION = + JMeterUtils.getPropDefault("view.results.table.max_memory_occupation", + // 100 mb + 100 * 1024 * 1024); //$NON-NLS-1$ private static final String iconSize = JMeterUtils.getPropDefault(JMeter.TREE_ICON_SIZE, JMeter.DEFAULT_TREE_ICON_SIZE); @@ -109,6 +120,11 @@ public class TableVisualizer extends AbstractVisualizer implements Clearable { private Format format = new SimpleDateFormat("HH:mm:ss.SSS"); //$NON-NLS-1$ + private JLabel warningLabel; + + private AtomicLong currentSizeApproximation = new AtomicLong(0l); + + // Column renderers private static final TableCellRenderer[] RENDERERS = new TableCellRenderer[]{ @@ -169,6 +185,9 @@ protected synchronized void updateTextFields(SampleResult res) { @Override public void add(final SampleResult res) { + if(applyOOMProtection()) { + return; + } JMeterUtils.runSafe(false, new Runnable() { @Override public void run() { @@ -183,6 +202,7 @@ public void run() { } synchronized (calc) { calc.addSample(res); + int count = calc.getCount(); TableSample newS = new TableSample( count, @@ -197,6 +217,7 @@ public void run() { res.getConnectTime() ); model.addRow(newS); + currentSizeApproximation.addAndGet(newS.getEstimatedSize()); } updateTextFields(res); if (autoscroll.isSelected()) { @@ -205,6 +226,26 @@ public void run() { } }); } + + /** + * When the limit is reached, JMeter will not {@link SampleResult} anymore + * Setting to 0 disables the protection + */ + private boolean applyOOMProtection() { + // Protection already in place + if(warningLabel.isVisible()) { + return true; + } + if(MAX_MEMORY_OCCUPATION > 0 && + // We reached the limit + currentSizeApproximation.get() > MAX_MEMORY_OCCUPATION) { + log.warn(getName()+":applying OUTOFMEMORY PROTECTION, SampleResults are not added anymore, use NON-GUI mode" + + " or configure property 'view.results.table.max_memory_occupation'"); + warningLabel.setVisible(true); + return true; + } + return false; + } @Override public synchronized void clearData() { @@ -214,6 +255,8 @@ public synchronized void clearData() { dataField.setText("0"); // $NON-NLS-1$ averageField.setText("0"); // $NON-NLS-1$ deviationField.setText("0"); // $NON-NLS-1$ + warningLabel.setVisible(false); + currentSizeApproximation.set(0); repaint(); } @@ -343,4 +386,21 @@ public Object invoke(Object pInvokee) { } } } + + /* (non-Javadoc) + * @see org.apache.jmeter.gui.AbstractJMeterGuiComponent#getNamePanel() + */ + @Override + protected Container makeTitlePanel() { + Container container = super.makeTitlePanel(); + ImageIcon image = JMeterUtils.getImage("warning.png"); //$NON-NLS-1$ + warningLabel = new JLabel("", image, SwingConstants.LEFT); // $NON-NLS-1$ + warningLabel.setForeground(Color.RED); + Font font = warningLabel.getFont(); + warningLabel.setFont(new Font(font.getFontName(), Font.BOLD, (int)(font.getSize()*1.1))); + warningLabel.setVisible(false); + container.add(warningLabel); + warningLabel.setText(JMeterUtils.getResString("view_results_table_oom")); //$NON-NLS-1$ + return container; + } } From 700eec86029530ba73b79bf792c0f6863b2305ee Mon Sep 17 00:00:00 2001 From: Philippe M Date: Sun, 3 Apr 2016 14:35:22 +0200 Subject: [PATCH 2/7] BUG_59258 --- .../ViewResultsFullVisualizer.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/components/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java b/src/components/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java index 0a775dbc3e9..a26b523b4d2 100644 --- a/src/components/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java +++ b/src/components/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java @@ -25,7 +25,9 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; +import java.awt.Container; import java.awt.Dimension; +import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; @@ -35,6 +37,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; import javax.swing.BorderFactory; import javax.swing.ComboBoxModel; @@ -42,10 +45,12 @@ import javax.swing.ImageIcon; import javax.swing.JCheckBox; import javax.swing.JComboBox; +import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTree; +import javax.swing.SwingConstants; import javax.swing.border.Border; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; @@ -102,6 +107,8 @@ public class ViewResultsFullVisualizer extends AbstractVisualizer private JComboBox selectRenderPanel; private int selectedTab; + + private AtomicLong currentSizeApproximation = new AtomicLong(0l); protected static final String COMBO_CHANGE_COMMAND = "change_combo"; // $NON-NLS-1$ @@ -124,12 +131,22 @@ public class ViewResultsFullVisualizer extends AbstractVisualizer private static final String VIEWERS_ORDER = JMeterUtils.getPropDefault("view.results.tree.renderers_order", ""); // $NON-NLS-1$ //$NON-NLS-2$ + /** + * Max memory used by SampleResults + */ + private static final int MAX_MEMORY_OCCUPATION = + JMeterUtils.getPropDefault("view.results.tree.max_memory_occupation", + // 100 mb + 100 * 1024 * 1024); //$NON-NLS-1$ + private ResultRenderer resultsRender = null; private TreeSelectionEvent lastSelectionEvent; private JCheckBox autoScrollCB; + private JLabel warningLabel; + /** * Constructor */ @@ -153,6 +170,10 @@ public void run() { * Update the visualizer with new data. */ private synchronized void updateGui(SampleResult res) { + if(applyOOMProtection()) { + return; + } + currentSizeApproximation.addAndGet(res.getEstimatedSize()); // Add sample DefaultMutableTreeNode currNode = new SearchableTreeNode(res, treeModel); treeModel.insertNodeInto(currNode, root, root.getChildCount()); @@ -176,6 +197,27 @@ private synchronized void updateGui(SampleResult res) { } } + /** + * When the limit is reached, JMeter will not {@link SampleResult} anymore + * Setting to 0 disables the protection + */ + private boolean applyOOMProtection() { + // Protection already in place + if(warningLabel.isVisible()) { + return true; + } + + if(MAX_MEMORY_OCCUPATION > 0 && + // We reached the limit + currentSizeApproximation.get() > MAX_MEMORY_OCCUPATION) { + log.warn(getName()+":applying OUTOFMEMORY PROTECTION, SampleResults are not added anymore, use NON-GUI mode" + + " or configure property 'view.results.tree.max_memory_occupation'"); + warningLabel.setVisible(true); + return true; + } + return false; + } + private void addSubResults(DefaultMutableTreeNode currNode, SampleResult res) { SampleResult[] subResults = res.getSubResults(); @@ -210,6 +252,8 @@ public synchronized void clearData() { treeModel.removeNodeFromParent((DefaultMutableTreeNode) root.getChildAt(0)); } resultsRender.clearData(); + currentSizeApproximation.set(0); + warningLabel.setVisible(false); } /** {@inheritDoc} */ @@ -467,4 +511,21 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, public void itemStateChanged(ItemEvent e) { // NOOP state is held by component } + + /* (non-Javadoc) + * @see org.apache.jmeter.gui.AbstractJMeterGuiComponent#getNamePanel() + */ + @Override + protected Container makeTitlePanel() { + Container container = super.makeTitlePanel(); + ImageIcon image = JMeterUtils.getImage("warning.png"); //$NON-NLS-1$ + warningLabel = new JLabel("", image, SwingConstants.LEFT); // $NON-NLS-1$ + warningLabel.setForeground(Color.RED); + Font font = warningLabel.getFont(); + warningLabel.setFont(new Font(font.getFontName(), Font.BOLD, (int)(font.getSize()*1.1))); + warningLabel.setVisible(false); + container.add(warningLabel); + warningLabel.setText(JMeterUtils.getResString("view_results_tree_oom")); //$NON-NLS-1$ + return container; + } } From cdc88957cebe76b76eaead7a13bf4f9f3d31e8f0 Mon Sep 17 00:00:00 2001 From: Philippe M Date: Sun, 3 Apr 2016 14:36:02 +0200 Subject: [PATCH 3/7] BUG_59258 --- .../apache/jmeter/samplers/SampleResult.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/core/org/apache/jmeter/samplers/SampleResult.java b/src/core/org/apache/jmeter/samplers/SampleResult.java index 344ea5601e9..c423457655c 100644 --- a/src/core/org/apache/jmeter/samplers/SampleResult.java +++ b/src/core/org/apache/jmeter/samplers/SampleResult.java @@ -1444,4 +1444,23 @@ public List getSearchableTokens() throws Exception { datasToSearch.add(getResponseHeaders()); return datasToSearch; } + + /** + * Beta API + * Not to be used by extensions + * @return long an estimation of the size in memory + */ + public long getEstimatedSize() { + long estimatedSize = getBytes(); + for (AssertionResult assertionResult : getAssertionResults()) { + estimatedSize += 2* assertionResult.getName().length() + + 2 * assertionResult.getFailureMessage().length(); + } + if(subResults != null) { + for (SampleResult subResult : subResults) { + estimatedSize += subResult.getEstimatedSize(); + } + } + return estimatedSize; + } } From c7c87379c8e34522d81ec232c2234dc79f10be5d Mon Sep 17 00:00:00 2001 From: Philippe M Date: Sun, 3 Apr 2016 14:36:57 +0200 Subject: [PATCH 4/7] BUG_59258 --- .../org/apache/jmeter/visualizers/TableSample.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/core/org/apache/jmeter/visualizers/TableSample.java b/src/core/org/apache/jmeter/visualizers/TableSample.java index fac3e817613..51e7db1a946 100644 --- a/src/core/org/apache/jmeter/visualizers/TableSample.java +++ b/src/core/org/apache/jmeter/visualizers/TableSample.java @@ -48,6 +48,18 @@ public class TableSample implements Serializable, Comparable { private final long connect; + /** + * Beta API + * Not to be used by extensions + * @return long estimation of object size in memory + */ + public long getEstimatedSize() { + return 48 + // 6 long + 1 + // 1 boolean + 4 + // 1 int + (label != null ? label.length() : 0) * 2 + + (threadName != null ? threadName.length() : 0)*2; + } /** * @deprecated for unit test code only */ @@ -151,4 +163,5 @@ public long getLatency() { public long getConnectTime() { return connect; } + } From 7e6a515b57621a9ff4ff5d89b3b1f0bcf025fbdb Mon Sep 17 00:00:00 2001 From: Philippe M Date: Sun, 3 Apr 2016 14:37:35 +0200 Subject: [PATCH 5/7] BUG_59258 --- src/core/org/apache/jmeter/resources/messages.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/org/apache/jmeter/resources/messages.properties b/src/core/org/apache/jmeter/resources/messages.properties index 74fd3c2ace6..eee585dbab0 100644 --- a/src/core/org/apache/jmeter/resources/messages.properties +++ b/src/core/org/apache/jmeter/resources/messages.properties @@ -1235,6 +1235,8 @@ view_results_in_table=View Results in Table view_results_latency=Latency: view_results_connect_time=Connect Time: view_results_load_time=Load time: +view_results_table_oom=To avoid OutOfMemory, component is not adding anymore sample results to the table anymore, use NON GUI mode for load testing +view_results_tree_oom=To avoid OutOfMemory, component is not adding anymore sample results to the tree anymore, use NON GUI mode for load testing view_results_render=Render: view_results_render_document=Document view_results_render_html=HTML From 9d279583007cedf7cf1b8b8f77e9b607d91d3a4b Mon Sep 17 00:00:00 2001 From: Philippe M Date: Sun, 3 Apr 2016 14:38:03 +0200 Subject: [PATCH 6/7] BUG_59258 --- src/core/org/apache/jmeter/resources/messages_fr.properties | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/org/apache/jmeter/resources/messages_fr.properties b/src/core/org/apache/jmeter/resources/messages_fr.properties index 9af48f7beb0..89186fc09f8 100644 --- a/src/core/org/apache/jmeter/resources/messages_fr.properties +++ b/src/core/org/apache/jmeter/resources/messages_fr.properties @@ -1203,7 +1203,7 @@ username=Nom d'utilisateur \: userpw=Mot de passe validate_threadgroup=Valider value=Valeur \: -value_to_quote_meta=Valeur \u00E0 \u00E9chapper des caract\u00E8res sp\u00E9ciaux utilis\u00E8s par ORO Regexp +value_to_quote_meta=Valeur \u00E0 \u00E9chapper des caract\u00E8res sp\u00E9ciaux utilis\u00E9s par ORO Regexp var_name=Nom de r\u00E9f\u00E9rence \: variable_name_param=Nom de variable (peut inclure une r\u00E9f\u00E9rence de variable ou fonction) view_graph_tree_title=Voir le graphique en arbre @@ -1220,6 +1220,8 @@ view_results_fields=champs \: view_results_in_table=Tableau de r\u00E9sultats view_results_latency=Latence \: view_results_load_time=Temps de r\u00E9ponse \: +view_results_table_oom=Afin d'\u00E9viter un probl\u00E8me m\u00E9moire, les Sample Results ne sont plus ajout\u00E9s, utilisez le mode NON-GUI pour les tests de charge +view_results_tree_oom=Afin d'\u00E9viter un probl\u00E8me m\u00E9moire, les Sample Results ne sont plus ajout\u00E9s, utilisez le mode NON-GUI pour les tests de charge view_results_render=Rendu \: view_results_render_document=Document view_results_render_html=HTML From 298bbd72e59987d1eec07d5aea611399d62e3e35 Mon Sep 17 00:00:00 2001 From: Philippe M Date: Sun, 3 Apr 2016 14:38:31 +0200 Subject: [PATCH 7/7] BUG_59258 --- bin/jmeter.properties | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/bin/jmeter.properties b/bin/jmeter.properties index f716bb3bcdd..8526b1c0b29 100644 --- a/bin/jmeter.properties +++ b/bin/jmeter.properties @@ -1103,12 +1103,24 @@ beanshell.server.file=../extras/startup.bsh # Set to 0 to disable the size check and display the whole response #view.results.tree.max_size=10485760 +# Max memory for SampleResults retained in View Results Tree +# When the limit is reached, JMeter will drop new SampleResults +# Setting to 0 disables the protection +# Default value is 100 Mb +#view.results.tree.max_memory_occupation=104857600 + # Order of Renderers in View Results Tree # Note full class names should be used for non jmeter core renderers # For JMeter core renderers, class names start with . and are automatically # prefixed with org.apache.jmeter.visualizers view.results.tree.renderers_order=.RenderAsText,.RenderAsRegexp,.RenderAsCssJQuery,.RenderAsXPath,.RenderAsHTML,.RenderAsHTMLWithEmbedded,.RenderAsDocument,.RenderAsJSON,.RenderAsXML +# Max number of Rows in View Results in Table +# When the limit is reached, JMeter will drop new SampleResults +# Setting to 0 disables the protection +# Default value is 100 Mb +#view.results.table.max_memory_occupation=104857600 + # Maximum size of Document that can be parsed by Tika engine; defaut=10 * 1024 * 1024 (10MB) # Set to 0 to disable the size check #document.max_size=0 @@ -1319,4 +1331,4 @@ system.properties=system.properties #testplan_validation.ignore_timers=true # Number of iterations to use to validate a Thread Group -#testplan_validation.number_iterations=1 \ No newline at end of file +#testplan_validation.number_iterations=1