ADDITIONAL SYSTEM INFORMATION :
Window 10, Java 10 and onwards
A DESCRIPTION OF THE PROBLEM :
Performance degredation of getBounds() method of java.awt.font.TextLayout
We are observing performance degradation by many fold when using HarfBuz as a font engine when data is large.
In our specific use case we are using poi library that using making use of TextLayout to get the width of every column. We are wiriting 20000 rows to spreadsheet :
With ICU as font engine : 2.3 to 3 seconnds
With HarfBuzz as font engine : 50 to 80 seconnds
REGRESSION : Last worked in version 8u212
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
call getBounds() method of TextLayout for large data set i.e. for large number of TextLayouts.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Total time consumed in java 8 and java 10 & above should be nearly same.
Expected Time consumed arround 1.5 seconds
ACTUAL -
Total time consumed in java 10 & above is much much high than time consumed in java 8.
Actual Time consumed more than 40 seconds
---------- BEGIN SOURCE ----------
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.text.AttributedString;
public class TextlayoutPerf {
private static final FontRenderContext fontRenderContext = new FontRenderContext(null, true, true);
public static void main(String[] args){
long start = System.currentTimeMillis();
String text = "test test test stet test test test test test";
//Equivalent to 20000 rows and 2 column
for (int j = 0; j < 3 ; j++) {
for (int i = 0; i < 20000; i++) {
getCellWidth(15, 0, 25, new AttributedString(text));
}
}
System.out.print(System.currentTimeMillis() - start);
}
private static double getCellWidth(int defaultCharWidth, int colspan, double minWidth, AttributedString str) {
TextLayout layout = new TextLayout(str.getIterator(), fontRenderContext);
final Rectangle2D bounds;
long start1 = System.currentTimeMillis();
bounds = layout.getBounds();
// frameWidth accounts for leading spaces which is excluded from bounds.getWidth()
final double frameWidth = bounds.getX() + bounds.getWidth();
return frameWidth;
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
No workarround in java 10
FREQUENCY : always