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 2022/04/12 16:25:34 UTC

[jmeter] branch master updated: Hack to make rendering of large text results faster

This is an automated email from the ASF dual-hosted git repository.

fschumacher pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git


The following commit(s) were added to refs/heads/master by this push:
     new 40de048e0e Hack to make rendering of large text results faster
40de048e0e is described below

commit 40de048e0edc23cfb78467747963a043ad6698c3
Author: Felix Schumacher <fe...@internetallee.de>
AuthorDate: Sun Mar 20 16:27:18 2022 +0100

    Hack to make rendering of large text results faster
    
    Currently the used JEditorPane is slow when using large texts, as it
    tries to find good places to break words.
    
    This hack disables word wrapping by using non-wrapping views
    for every element in the JEditorPane.
    
    Introduce a new setting view.results.tree.simple_view_limit for view results tree
    
    This setting is used to decide, whether the text view should switch to a simpler
    view model. That can help to get rid of UI unresponsiveness on large contents.
    
    Closes #706
---
 bin/jmeter.properties                              |  5 ++
 .../jmeter/visualizers/SamplerResultTab.java       | 77 ++++++++++++++++++++++
 xdocs/usermanual/properties_reference.xml          |  6 ++
 3 files changed, 88 insertions(+)

diff --git a/bin/jmeter.properties b/bin/jmeter.properties
index 22994b683c..69b77d46bd 100644
--- a/bin/jmeter.properties
+++ b/bin/jmeter.properties
@@ -1195,6 +1195,11 @@ cookies=cookies
 #view.results.tree.max_line_size=110000
 #view.results.tree.soft_wrap_line_size=100000
 
+# Even with the above setting the UI can be unresponsive on large contents in the text view,
+# so we allow to switch to a simpler view mode, that is faster, but does not break lines.
+# Can be switched off by setting it to -1
+#view.results.tree.simple_view_limit=10000
+
 # 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
diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java b/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java
index 5a9afe4fad..5e1d4a0b83 100644
--- a/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java
+++ b/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java
@@ -21,6 +21,11 @@ import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Component;
 import java.awt.GridLayout;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -28,6 +33,7 @@ import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
 
+import javax.swing.Action;
 import javax.swing.BorderFactory;
 import javax.swing.Icon;
 import javax.swing.ImageIcon;
@@ -43,11 +49,17 @@ import javax.swing.SwingConstants;
 import javax.swing.table.TableCellRenderer;
 import javax.swing.table.TableColumn;
 import javax.swing.text.BadLocationException;
+import javax.swing.text.Caret;
 import javax.swing.text.DefaultStyledDocument;
 import javax.swing.text.Document;
+import javax.swing.text.EditorKit;
+import javax.swing.text.Element;
+import javax.swing.text.PlainView;
 import javax.swing.text.Style;
 import javax.swing.text.StyleConstants;
 import javax.swing.text.StyledDocument;
+import javax.swing.text.View;
+import javax.swing.text.ViewFactory;
 
 import org.apache.jmeter.assertions.AssertionResult;
 import org.apache.jmeter.gui.util.HeaderAsPropertyRenderer;
@@ -94,6 +106,9 @@ public abstract class SamplerResultTab implements ResultRenderer {
 
     private static final String STYLE_REDIRECT = "Redirect"; // $NON-NLS-1$
 
+    private static final int SIMPLE_VIEW_LIMIT =
+            JMeterUtils.getPropDefault("view.results.tree.simple_view_limit", 10_000); // $NON-NLS-1$
+
     private JTextPane stats;
 
     /** Response Data pane */
@@ -694,7 +709,69 @@ public abstract class SamplerResultTab implements ResultRenderer {
         } catch (BadLocationException ex) {
             LOGGER.error("Error inserting text", ex);
         }
+        if (SIMPLE_VIEW_LIMIT >= 0 && document.getLength() > SIMPLE_VIEW_LIMIT) {
+            results.setEditorKit(new NonWrappingPlainTextEditorKit(results.getEditorKit()));
+        }
         KerningOptimizer.INSTANCE.configureKerning(results, document.getLength());
         results.setDocument(document);
     }
+    static class NonWrappingPlainTextEditorKit extends EditorKit {
+
+        private final EditorKit delegate;
+
+        NonWrappingPlainTextEditorKit(EditorKit delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public String getContentType() {
+            return delegate.getContentType();
+        }
+
+        @Override
+        public ViewFactory getViewFactory() {
+            //return new BasicTextAreaUI();
+            return new ViewFactory() {
+                @Override
+                public View create(Element elem) {
+                    return new PlainView(elem);
+                }
+            };
+        }
+
+        @Override
+        public Action[] getActions() {
+            return delegate.getActions();
+        }
+
+        @Override
+        public Caret createCaret() {
+            return delegate.createCaret();
+        }
+
+        @Override
+        public Document createDefaultDocument() {
+            return delegate.createDefaultDocument();
+        }
+
+        @Override
+        public void read(InputStream in, Document doc, int pos) throws IOException, BadLocationException {
+            delegate.read(in, doc, pos);
+        }
+
+        @Override
+        public void write(OutputStream out, Document doc, int pos, int len) throws IOException, BadLocationException {
+            delegate.write(out, doc, pos, len);
+        }
+
+        @Override
+        public void read(Reader in, Document doc, int pos) throws IOException, BadLocationException {
+            delegate.read(in, doc, pos);
+        }
+
+        @Override
+        public void write(Writer out, Document doc, int pos, int len) throws IOException, BadLocationException {
+            delegate.write(out, doc, pos, len);
+        }
+    }
 }
diff --git a/xdocs/usermanual/properties_reference.xml b/xdocs/usermanual/properties_reference.xml
index 6ab39a7b44..2643f37f09 100644
--- a/xdocs/usermanual/properties_reference.xml
+++ b/xdocs/usermanual/properties_reference.xml
@@ -1541,6 +1541,12 @@ JMETER-SERVER</source>
     Defaults to:
     <source>.RenderAsText,.RenderAsRegexp,.RenderAsCssJQuery,.RenderAsXPath,.RenderAsHTML,.RenderAsHTMLWithEmbedded,.RenderAsDocument,.RenderAsJSON,.RenderAsXML</source>
 </property>
+<property name="view.results.tree.simple_view_limit">
+    Configures maximum document length for text view before switching to a simpler view, that does not do line breaks.<br/>
+    Works probably best, when combined with a low setting of <code>view.results.tree.max_line_size</code>.
+    Can be switched off by setting the value to <code>-1</code>.<br/>
+    Defaults to: <code>10000</code>
+</property>
 <property name="document.max_size">
     Maximum size (in bytes) of Document that can be parsed by Tika engine<br/>
     Set to zero to disable the size check.<br/>