Regression: Unicode Smiley text measuring extremely slow in 25.0.1
Calling TextMeasurer::getLayout on "😊🙂😀"
in 21: SmileyRegression.breakSmilies avgt 3 0,006 ± 0,001 ms/op in 25: SmileyRegression.breakSmilies avgt 3 1,116 ± 3,488 ms/op
The performance in 21 is almost identical to Temurin's.
This hurts really hard, as this call is done usually directly on the EDT, so your UI is going to freeze to halt.
Following is the code to reproduce: (I used jbang to ease running the benchmark):
SmileyRegression.java :
///usr/bin/env jbang "$0" "$@" ; exit
//DEPS org.openjdk.jmh:jmh-core:1.19 org.openjdk.jmh:jmh-generator-annprocess:1.19
//COMPILE_OPTIONS -processor org.openjdk.jmh.generators.BenchmarkProcessor
package smiley;
// benchmark imports
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.RunnerException;
import java.util.concurrent.TimeUnit;
import java.io.IOException;
// actual imports
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.font.TextMeasurer;
import java.awt.geom.Rectangle2D;
import java.text.AttributedString;
// configure jmh
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
@Warmup(iterations = 3)
@Measurement(iterations = 3)
@Fork(value = 1, warmups = 1)
public class SmileyRegression {
String rawText = "\uD83D\uDE0A\uD83D\uDE42\uD83D\uDE00";
AttributedString smiles = new AttributedString(rawText);
FontRenderContext frc = new FontRenderContext(null, true, false);
@Benchmark
public void breakSmilies() {
TextMeasurer tm = new TextMeasurer(smiles.getIterator(), frc);
TextLayout tl = tm.getLayout(0, rawText.length());
if (tl.getBounds().getWidth() < 0) throw new IllegalStateException();
}
public static void main(String[] args) throws IOException, RunnerException {
org.openjdk.jmh.Main.main(args);
}
}
jbang --verbose SmileyRegression.java
I got the following results on xlinux.
Benchmark Mode Cnt Score Error Units
SmileyRegression.breakSmilies avgt 3 0.007 ± 0.002 ms/op Semeru 21.0.9
SmileyRegression.breakSmilies avgt 3 0.364 ± 0.769 ms/op Semeru 25.0.1
SmileyRegression.breakSmilies avgt 3 0.004 ± 0.001 ms/op Temurin 25.0.1
@hzongaro @vijaysun-omr fyi
@0xdaryl
The performance difference is observed between Semeru JDK 21.0.9 and JDK 25.0.1 (both from the Semeru downloads page that use the 0.56 OpenJ9 release).
However, the performance is significantly improved with the latest JDK 25 build from master (Dec 3).
Benchmark Mode Cnt Score Error Units
SmileyRegression.breakSmilies avgt 3 0.024 ± 0.021 ms/op Semeru JDK 21.0.9 (0.56 OpenJ9 release)
SmileyRegression.breakSmilies avgt 3 0.025 ± 0.039 ms/op Semeru JDK 21.0.10 (master, Dec 3)
SmileyRegression.breakSmilies avgt 3 0.554 ± 2.031 ms/op Semeru JDK 25.0.1 (0.56 OpenJ9 release)
SmileyRegression.breakSmilies avgt 3 0.055 ± 0.054 ms/op Semeru JDK 25.0.1 (master, Dec 3)
SmileyRegression.breakSmilies avgt 3 0.019 ± 0.050 ms/op Temurin JDK 25.0.1
I'm pretty sure I know why it improved, but I would like to look into it deeper to confirm before commenting. There is still a performance gap with JDK 21 and Temurin to look into, suggesting some other performance opportunities to find.