JDK-8189809 : Large performance regression in Swing text layout.
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 9,10
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2017-10-23
  • Updated: 2017-12-15
  • Resolved: 2017-12-11
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 10
10 b36Fixed
Related Reports
Relates :  
Description
This bug was reported on Swing alias by Alan Snyder <javalists@cbfiddle.com>

The performance downgrade is rather big > 20x.

Test to benchmark the layout:
===================================

import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Element;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.View;

public class Test {
 public static void main(String[] args) {
  boolean isRepeat = args.length > 0 && args[0].equals("repeat");
  new Test(isRepeat ? 1000 : 1);
 }

 public Test(int count) {
  TestRunner r = new TestRunner();
  for (int i = 0; i < 100; i++) {
   r.runTest();
  }
  for (int counter = 0; counter < count; counter++) {
   long ts1 = System.currentTimeMillis();
   for (int i = 0; i < 2000; i++) {
    r.runTest();
   }

   long ts2 = System.currentTimeMillis();
   System.err.println("Test: " + (ts2 - ts1) + " milliseconds");
  }
 }

 class TestRunner {
  View view;
  int counter;
  float width;
  float height;

  TestRunner() {
   try {
    DefaultStyledDocument doc = new DefaultStyledDocument();
    String text = createText();
    doc.insertString(0, text, new SimpleAttributeSet());
    Element p = doc.getParagraphElement(0);
    JTextPane pane = new JTextPane(doc);
    view = pane.getUI().getRootView(pane);
   } catch (BadLocationException ex) {
    throw new UnsupportedOperationException(ex);
   }
  }

  void runTest() {
   counter++;
   if (counter % 2 == 0) {
    width = 600;
    height = 600;
   } else {
    width = 800;
    height = 400;
   }
   view.setSize(width, height);
  }

  String createText() {
   String s = "Inserts some content into the document. Inserting content causes a write lock to be held while the actual changes are taking place, followed by notification to the observers on the thread that grabbed the write lock. ";
   return s + s + s + s + s + "\n";
  }
 }
}





Comments
As discussed in the email thread getStringBounds has no fast path like stringWidth. Fix proposes adding one, but it will not on its own get back all the lost performance but does help.
07-12-2017

http://mail.openjdk.java.net/pipermail/2d-dev/2017-December/008743.html
07-12-2017

It seems the major contribution if from the next code in sun.swing.SwingUtilities2: public static float getFontStringWidth(String data, FontMetrics fm, boolean useFPAPI) { if (useFPAPI) { Rectangle2D bounds = fm.getFont() .getStringBounds(data, fm.getFontRenderContext()); return (float) bounds.getWidth(); } else { return fm.stringWidth(data); } } the old stringWidth() is much faster than getStringBounds().
23-10-2017

The regression is caused by JDK-8156217
23-10-2017