Skip to content
Permalink
Browse files
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
  • Loading branch information
FSchumacher committed Apr 12, 2022
1 parent 76d1de3 commit 40de048e0edc23cfb78467747963a043ad6698c3
Showing 3 changed files with 88 additions and 0 deletions.
@@ -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
@@ -21,13 +21,19 @@
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;
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.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 @@ protected void setTextOptimized(String data) {
} 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);
}
}
}
@@ -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/>

0 comments on commit 40de048

Please sign in to comment.