JDK-8359955 : Regressions ~7% in several J2DBench in 25-b26
Type:Bug
Component:client-libs
Sub-Component:2d
Affected Version:25
Priority:P3
Status:Resolved
Resolution:Fixed
Submitted:2025-06-18
Updated:2025-08-27
Resolved:2025-08-20
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.
A pull request was submitted for review.
Branch: master
URL: https://git.openjdk.org/jdk/pull/26702
Date: 2025-08-08 16:37:36 +0000
08-08-2025
Great, I'll go ahead and submit the PR with both of these changes. Thanks!
08-08-2025
This Windows patch also worked well -
benchmark / baseline b9 / b9 + this patch / % better
===========================================
"J2dBench-vimg_text_aa", 11781.05, 12355.60, 4.877,
"J2dBench-vimg_text_lcd", 11744.35, 12377.70, 5.393,
"J2dBench-vimg_text_noaa", 20992.80, 22872.75, 8.955,
08-08-2025
I started that run - hopefully will complete overnight, will report Friday, I'm taking tomorrow off.
06-08-2025
[~ecaspole] Since the general approach seems promising, here is a follow-on commit making a similar change in CompositeGlyphMapper:
https://github.com/openjdk/jdk/commit/fbbadb94e92e728417b7d6989119476d75a90a91
Can you check whether it mitigates the Windows performance degradation which you were seeing? Unfortunately I can't replicate the performance issue on Windows on my end, so I can't check the impact locally first.
05-08-2025
Seems worth it to me !
05-08-2025
That's great, thanks for the quick feedback on the performance side.
[~prr] [~honkar] What is your take on the slight increment in complexity and memory use? Worth it for the performance?
05-08-2025
This patch worked well, these vimg text improved by about 9% on our MacOSX aarch64 Minis!
benchmark / baseline b9 / b9 + this patch
===================================
"J2dBench-vimg_text_aa", 24156.30, 26500.25, 9.703,
"J2dBench-vimg_text_lcd", 24140.70, 26425.90, 9.466,
"J2dBench-vimg_text_noaa", 24329.70, 26485.55, 8.861,
05-08-2025
I am building this patch now and will run the perf/footprint/etc tests when that is ready.
04-08-2025
OK, here's a proposed fix which mitigates most of the macOS performance regression:
https://github.com/gredler/jdk/commit/20477a9ae44e2a0ba976f01434d7fe8a0aeb0220
Briefly, CCharToGlyphMapper caches glyph IDs, but it doesn't cache glyph IDs for chars which may be affected by the raw / non-raw distinction, since the cached value may not be correct if we ask for a raw glyph ID one time, but a non-raw glyph ID the next time (or vice versa). This caching carve-out is the reason for the degraded performance. The proposed change splits the cache into two caches, one for raw glyph IDs and one for non-raw glyph IDs, so that no caching exception is necessary.
This code is faster, but a little more complex and will use a little more memory at runtime. Does the performance / complexity / memory use trade-off look acceptable?
Once this open point is verified, I can look at applying the same treatment to CompositeGlyphMapper for the Windows use case (this is just a guess as to root cause on my end, since I can't replicate the performance regression on my Windows 11 Pro machine).
02-08-2025
We are running on Windows 2019 Datacenter edition.
25-07-2025
Interesting! The only thing I can think is that there must be a Windows version / font setup difference between the machines. There were two classes with glyph caching which were affected by JDK-8353230: CCharToGlyphMapper (a Mac-only class) and CompositeGlyphMapper (not platform-specific). The Mac performance regression is related to less efficient caching in CCharToGlyphMapper, so it's possible (but I can't be sure) that the Windows regression that you are seeing is related to less efficient caching in CompositeGlyphMapper. I'm going to finish putting together a possible CCharToGlyphMapper change which improves performance on the Mac side at the cost of higher memory use, get some feedback, and if there is consensus that it's the right trade-off, then I'll take a shot in the dark and see about a similar change in CompositeGlyphMapper for the Windows side.
25-07-2025
I reran overnight with the J2DBench 8u version and the latest version, with 3190 vs 3191 (which contains only JDK-8353230 ) with similar results:
8u
J2dBench-vimg_text_noaa-G1
MacOSX aarch64 / MacOSX x64 / Windows x64
-8.23%. / -6.15%. / -7.50%
Current
MacOSX aarch64 / MacOSX x64 / Windows x64
-8.54% / -6.15% / -8.13%
Also, FWIW we run Windows on headless OCI servers of shape BM.Optimized3.36.
25-07-2025
I just added the vimg_text_noaa-1.opt for the 8u version, and I will rerun both versions and give an update.
24-07-2025
Thanks for the clarification! I ran the text_noaa test (note: it seems to require mainline J2DBench rather than jdk8u J2DBench, which is the opposite of the text_aa file), but I'm still not seeing a clear regression on Windows. I'm seeing something in the 0.5% to 1% range (see below). I do see a clear 7% to 8% performance regression on Mac, and after some profiling this seems linked to the changes in CCharToGlyphMapper, which is a Mac-only class. I'm going to see whether I can mitigate this Mac performance impact, though it may end up being a tradeoff between maintainability and performance.
---------------
Windows text_noaa results:
$ java -Duser.language=en -Duser.region=US -jar dist/J2DAnalyzer.jar -ShowUncontested vimg_text_noaa.opt.java-24.0.1.res
Options common across all tests:
testname=text.Rendering.tests.drawString
text.opts.advopts.tlruns=1
text.opts.graphics.gtx=Identity
text.opts.font.ftx=Identity
text.opts.graphics.tfm=false
global.dest=VolatileImg()
text.opts.advopts.maptype=FONT
text.opts.font.fsize=13.0
text.opts.graphics.textaa=Off
text.opts.graphics.gaa=false
text.opts.font.fname=Default
text.opts.advopts.gvstyle=0
text.opts.font.fstyle=0
text.opts.data.tscript=english
text.opts.data.tlength=16:
vimg_text_noaa.java-24.0.1: 235.7214247 (var=2.61%) (100.0%)
text.opts.data.tlength=64:
vimg_text_noaa.java-24.0.1: 344.2360655 (var=1.15%) (100.0%)
Summary:
vimg_text_noaa.java-24.0.1:
Number of tests: 2
Overall average: 289.9787451739134
Best spread: 1.15% variance
Worst spread: 2.61% variance
(Basis for results comparison)
$ java -Duser.language=en -Duser.region=US -jar dist/J2DAnalyzer.jar -ShowUncontested vimg_text_noaa.opt.java-25-before.res
Options common across all tests:
testname=text.Rendering.tests.drawString
text.opts.advopts.tlruns=1
text.opts.graphics.gtx=Identity
text.opts.font.ftx=Identity
text.opts.graphics.tfm=false
global.dest=VolatileImg()
text.opts.advopts.maptype=FONT
text.opts.font.fsize=13.0
text.opts.graphics.textaa=Off
text.opts.graphics.gaa=false
text.opts.font.fname=Default
text.opts.advopts.gvstyle=0
text.opts.font.fstyle=0
text.opts.data.tscript=english
text.opts.data.tlength=16:
vimg_text_noaa.java-25-before: 232.2127659 (var=2.62%) (100.0%)
text.opts.data.tlength=64:
vimg_text_noaa.java-25-before: 345.0298750 (var=2.07%) (100.0%)
Summary:
vimg_text_noaa.java-25-before:
Number of tests: 2
Overall average: 288.62132051267236
Best spread: 2.07% variance
Worst spread: 2.62% variance
(Basis for results comparison)
$ java -Duser.language=en -Duser.region=US -jar dist/J2DAnalyzer.jar -ShowUncontested vimg_text_noaa.opt.java-25-after.res
Options common across all tests:
testname=text.Rendering.tests.drawString
text.opts.advopts.tlruns=1
text.opts.graphics.gtx=Identity
text.opts.font.ftx=Identity
text.opts.graphics.tfm=false
global.dest=VolatileImg()
text.opts.advopts.maptype=FONT
text.opts.font.fsize=13.0
text.opts.graphics.textaa=Off
text.opts.graphics.gaa=false
text.opts.font.fname=Default
text.opts.advopts.gvstyle=0
text.opts.font.fstyle=0
text.opts.data.tscript=english
text.opts.data.tlength=16:
vimg_text_noaa.java-25-after: 232.6705324 (var=0.96%) (100.0%)
text.opts.data.tlength=64:
vimg_text_noaa.java-25-after: 341.5076252 (var=2.16%) (100.0%)
Summary:
vimg_text_noaa.java-25-after:
Number of tests: 2
Overall average: 287.08907884597056
Best spread: 0.96% variance
Worst spread: 2.16% variance
(Basis for results comparison)
23-07-2025
You are right and I am sorry not to notice earlier - try the file I just attached, text_noaa. I see that there are more regression cases on Mac than Windows. I usually run on Mac and I glossed over this point earlier. Almost all cases on mac are about 6% slower but on Windows it's only text_noaa.
22-07-2025
I haven't been able to replicate on Windows. Here's what I'm seeing on my end. How does it compare to your results?
25-before = commit b7ca672d5c5f11f472110154868f08299f6e8796 (right before JDK-8353230 landed)
25-after = commit 94039e22bbe943888e858d8ae278145e2668526a (the commit in which JDK-8353230 landed)
24.0.1 = extra baseline added, since there were more changes in this area of the code during 25 and I wanted to see the overall changes including more than just this one commit
-------------------------
$ "/cygdrive/c/Program Files/Eclipse Adoptium/jdk-24.0.1.9-hotspot/bin/java" -server -jar dist/J2DBench.jar -batch -loadopts vimg_text_aa.opt -saveres vimg_text_aa.opt.java-24.0.1.res -title "vimg_text_aa.java-24.0.1" -desc "vimg_text_aa.java-24.0.1"
Option imageio.input.image.jpegcodec.tests.decodeAsBufferedImage=disabled at line 138 ignored: Key failed to match an existing option
Option imageio.output.image.jpegcodec.tests.encode=disabled at line 164 ignored: Key failed to match an existing option
Test(text.Rendering.tests.drawString) took 1980ms for 31766 reps
Test(text.Rendering.tests.drawString) took 1942ms for 31766 reps
Test(text.Rendering.tests.drawString) took 1897ms for 31766 reps
Test(text.Rendering.tests.drawString) averaged 262032.65165836056 chars/sec
with english, Default, !gaa, ident, 16, std, On, !tfm, 1, 13.0, plain, font, ident, to VolatileImg
Test(text.Rendering.tests.drawString) took 1901ms for 11001 reps
Test(text.Rendering.tests.drawString) took 1892ms for 11001 reps
Test(text.Rendering.tests.drawString) took 1899ms for 11001 reps
Test(text.Rendering.tests.drawString) averaged 371080.81517919886 chars/sec
with english, Default, !gaa, ident, 64, std, On, !tfm, 1, 13.0, plain, font, ident, to VolatileImg
All test results:
Test(text.Rendering.tests.drawString) averaged 262032.65165836056 chars/sec
with english, Default, !gaa, ident, 16, std, On, !tfm, 1, 13.0, plain, font, ident, to VolatileImg
Test(text.Rendering.tests.drawString) averaged 371080.81517919886 chars/sec
with english, Default, !gaa, ident, 64, std, On, !tfm, 1, 13.0, plain, font, ident, to VolatileImg
$ "/cygdrive/c/work/openjdk/jdk/build/windows-x86_64-server-release/images/jdk/bin/java" -server -jar dist/J2DBench.jar -batch -loadopts vimg_text_aa.opt -saveres vimg_text_aa.opt.java-25-before.res -title "vimg_text_aa.java-25-before" -desc "vimg_text_aa.java-25-before"
Option imageio.input.image.jpegcodec.tests.decodeAsBufferedImage=disabled at line 138 ignored: Key failed to match an existing option
Option imageio.output.image.jpegcodec.tests.encode=disabled at line 164 ignored: Key failed to match an existing option
Test(text.Rendering.tests.drawString) took 1979ms for 31702 reps
Test(text.Rendering.tests.drawString) took 1966ms for 31702 reps
Test(text.Rendering.tests.drawString) took 1956ms for 31702 reps
Test(text.Rendering.tests.drawString) averaged 257870.86934417897 chars/sec
with !tfm, to VolatileImg, !gaa, ident, plain, 1, On, font, std, ident, Default, 13.0, english, 16
Test(text.Rendering.tests.drawString) took 1902ms for 10929 reps
Test(text.Rendering.tests.drawString) took 1859ms for 10929 reps
Test(text.Rendering.tests.drawString) took 1871ms for 10929 reps
Test(text.Rendering.tests.drawString) averaged 372579.54545454547 chars/sec
with !tfm, to VolatileImg, !gaa, ident, plain, 1, On, font, std, ident, Default, 13.0, english, 64
All test results:
Test(text.Rendering.tests.drawString) averaged 257870.86934417897 chars/sec
with !tfm, to VolatileImg, !gaa, ident, plain, 1, On, font, std, ident, Default, 13.0, english, 16
Test(text.Rendering.tests.drawString) averaged 372579.54545454547 chars/sec
with !tfm, to VolatileImg, !gaa, ident, plain, 1, On, font, std, ident, Default, 13.0, english, 64
$ "/cygdrive/c/work/openjdk/jdk/build/windows-x86_64-server-release/images/jdk/bin/java" -server -jar dist/J2DBench.jar -batch -loadopts vimg_text_aa.opt -saveres vimg_text_aa.opt.java-25-after.res -title "vimg_text_aa.java-25-after" -desc "vimg_text_aa.java-25-after"
Option imageio.input.image.jpegcodec.tests.decodeAsBufferedImage=disabled at line 138 ignored: Key failed to match an existing option
Option imageio.output.image.jpegcodec.tests.encode=disabled at line 164 ignored: Key failed to match an existing option
Test(text.Rendering.tests.drawString) took 1954ms for 31722 reps
Test(text.Rendering.tests.drawString) took 1892ms for 31722 reps
Test(text.Rendering.tests.drawString) took 1811ms for 31722 reps
Test(text.Rendering.tests.drawString) averaged 269163.1606858759 chars/sec
with ident, std, !tfm, ident, to VolatileImg, !gaa, font, 1, english, 13.0, 16, On, plain, Default
Test(text.Rendering.tests.drawString) took 1929ms for 11079 reps
Test(text.Rendering.tests.drawString) took 1889ms for 11079 reps
Test(text.Rendering.tests.drawString) took 1886ms for 11079 reps
Test(text.Rendering.tests.drawString) averaged 372925.6661991585 chars/sec
with ident, std, !tfm, ident, to VolatileImg, !gaa, font, 1, english, 13.0, 64, On, plain, Default
All test results:
Test(text.Rendering.tests.drawString) averaged 269163.1606858759 chars/sec
with ident, std, !tfm, ident, to VolatileImg, !gaa, font, 1, english, 13.0, 16, On, plain, Default
Test(text.Rendering.tests.drawString) averaged 372925.6661991585 chars/sec
with ident, std, !tfm, ident, to VolatileImg, !gaa, font, 1, english, 13.0, 64, On, plain, Default
$ java -Duser.language=en -Duser.region=US -jar dist/J2DAnalyzer.jar -ShowUncontested vimg_text_aa.opt.java-24.0.1.res
Options common across all tests:
testname=text.Rendering.tests.drawString
text.opts.advopts.tlruns=1
text.opts.graphics.gtx=Identity
text.opts.font.ftx=Identity
text.opts.graphics.tfm=false
global.dest=VolatileImg
text.opts.advopts.maptype=FONT
text.opts.font.fsize=13.0
text.opts.graphics.textaa=On
text.opts.graphics.gaa=false
text.opts.font.fname=Default
text.opts.advopts.gvstyle=0
text.opts.font.fstyle=0
text.opts.data.tscript=english
text.opts.data.tlength=16:
vimg_text_aa.java-24.0.1: 261.7178166 (var=4.38%) (100.0%)
text.opts.data.tlength=64:
vimg_text_aa.java-24.0.1: 370.7551342 (var=0.48%) (100.0%)
Summary:
vimg_text_aa.java-24.0.1:
Number of tests: 2
Overall average: 316.23647548251586
Best spread: 0.48% variance
Worst spread: 4.38% variance
(Basis for results comparison)
$ java -Duser.language=en -Duser.region=US -jar dist/J2DAnalyzer.jar -ShowUncontested vimg_text_aa.opt.java-25-before.res
Options common across all tests:
testname=text.Rendering.tests.drawString
text.opts.advopts.tlruns=1
text.opts.graphics.gtx=Identity
text.opts.font.ftx=Identity
text.opts.graphics.tfm=false
global.dest=VolatileImg
text.opts.advopts.maptype=FONT
text.opts.font.fsize=13.0
text.opts.graphics.textaa=On
text.opts.font.fname=Default
text.opts.graphics.gaa=false
text.opts.advopts.gvstyle=0
text.opts.data.tscript=english
text.opts.font.fstyle=0
text.opts.data.tlength=16:
vimg_text_aa.java-25-before: 258.0020345 (var=1.18%) (100.0%)
text.opts.data.tlength=64:
vimg_text_aa.java-25-before: 373.8407268 (var=2.31%) (100.0%)
Summary:
vimg_text_aa.java-25-before:
Number of tests: 2
Overall average: 315.92138073600756
Best spread: 1.18% variance
Worst spread: 2.31% variance
(Basis for results comparison)
$ java -Duser.language=en -Duser.region=US -jar dist/J2DAnalyzer.jar -ShowUncontested vimg_text_aa.opt.java-25-after.res
Options common across all tests:
testname=text.Rendering.tests.drawString
text.opts.advopts.tlruns=1
text.opts.graphics.gtx=Identity
text.opts.font.ftx=Identity
text.opts.graphics.tfm=false
global.dest=VolatileImg
text.opts.advopts.maptype=FONT
text.opts.graphics.textaa=On
text.opts.font.fsize=13.0
text.opts.font.fname=Default
text.opts.graphics.gaa=false
text.opts.advopts.gvstyle=0
text.opts.font.fstyle=0
text.opts.data.tscript=english
text.opts.data.tlength=16:
vimg_text_aa.java-25-after: 268.2621564 (var=7.9%) (100.0%)
text.opts.data.tlength=64:
vimg_text_aa.java-25-after: 375.3605082 (var=2.28%) (100.0%)
Summary:
vimg_text_aa.java-25-after:
Number of tests: 2
Overall average: 321.81133232680133
Best spread: 2.28% variance
Worst spread: 7.9% variance
(Basis for results comparison)
22-07-2025
The J2DBench scores are pixels/sec so yes higher is better.
22-07-2025
[~ecaspole] Can you clarify one thing? What are the units for the "Overall average" lines? It sounds like higher is better?
22-07-2025
OK, thanks for checking on that. I'll see about pulling the `jdk8u` version of J2DBench to replicate.
25-06-2025
Over time the J2DBench has added more properties and become incompatible with our old properties files. I will try to update the properties files, but for the time being we can keep on using the 8u version of J2DBench where the old properties still work.
25-06-2025
We are running the 8u version of J2DBench in weekly testing because we have to test 8 updates too. But I will try to figure out why the main-line repo one seems to be different, I don't know why.
24-06-2025
Thanks for the guidance!
[~ecaspole] Does this options file need to be run using the `jdk8u` version of J2DBench? I had assumed that it would be OK to run it using the version in the main-line development tree, but it ends up not running any tests. I'm not sure if it's because I'm not in `jdk8u` or due to some other factor (note empty list of test results at the end):
$ java -server -jar dist/J2DBench.jar -batch -loadopts vimg_text_aa.opt -saveres vimg_text_aa.opt.baseline.res -title "vimg_text_aa.baseline" -desc "vimg_text_aa.baseline"
Option global.dest.screen=disabled at line 8 ignored: Key failed to match an existing option
Option global.dest.volimg=enabled at line 14 ignored: Key failed to match an existing option
Option graphics.imaging.src.volimg.opaque=disabled at line 57 ignored: Key failed to match an existing option
Option graphics.imaging.src.volimg.bitmask=disabled at line 58 ignored: Key failed to match an existing option
Option graphics.imaging.src.volimg.translucent=disabled at line 59 ignored: Key failed to match an existing option
Option graphics.imaging.tests.drawimage=disabled at line 72 ignored: Key failed to match an existing option
Option graphics.imaging.tests.drawimagebg=disabled at line 73 ignored: Key failed to match an existing option
Option graphics.imaging.tests.drawimagescaleup=disabled at line 74 ignored: Key failed to match an existing option
Option graphics.imaging.tests.drawimagescaledown=disabled at line 75 ignored: Key failed to match an existing option
Option graphics.imaging.tests.drawimagetxform=disabled at line 76 ignored: Key failed to match an existing option
Option imageio.input.image.jpegcodec.tests.decodeAsBufferedImage=disabled at line 138 ignored: Key failed to match an existing option
Option imageio.output.image.jpegcodec.tests.encode=disabled at line 164 ignored: Key failed to match an existing option
All test results:
23-06-2025
Hi [~dgredler]
With help from [~prr] I was able to extract this into a fairly simple sequence.
Check out jdk8u from here: https://github.com/openjdk/jdk8u/tree/master
Look in jdk8u/jdk/src/share/demo/java2d/J2DBench/
With a JDK 8, build with ant as shown in the README
Now with the vimg_text_aa.opt I attached to the JBS, you can run like this:
% mkdir result
baseline-jdk/bin/java -server -jar dist/J2DBench.jar -batch -loadopts ./vimg_text_aa.opt -saveres ./result/vimg_text_aa.opt.baseline.res -title "vimg_text_aa.baseline" -desc "vimg_text_aa_1.baseline"
patch-jdk/bin/java -server -jar dist/J2DBench.jar -batch -loadopts ./vimg_text_aa.opt -saveres ./result/vimg_text_aa.opt.patch.res -title "vimg_text_aa.patch" -desc "vimg_text_aa_1.patch"
Then run the Analyzer on each result and it will print the scores:
% java -Duser.language=en -Duser.region=US -jar dist/J2DAnalyzer.jar ./result/vimg_text_aa.opt.baseline.res -ShowUncontested
% java -Duser.language=en -Duser.region=US -jar dist/J2DAnalyzer.jar ./result/vimg_text_aa.opt.patch.res -ShowUncontested
On my MacBook Pro M1 Max, I got scores like:
Baseline:
Overall average: 28077.016592846423
Patch:
Overall average: 25440.151896778967
Let me know if you can get this to work.
23-06-2025
J2DBench is in the repo at src/demo/share/java2d/J2DBench
There is a README that tells you how to build and run it.
There are a few build options.
"make" may be the easiest but you will need to set JDK 8 on your path for the build,
since "-target 7" is used by the make build so that in theory javac is stable for resulting test runs.
Of course you can run with any later JDK - ie the ones you'd like to compare !
java -jar dist/J2DBench.jar ......
You will see various set up options - global options and benchmarks to run.
Eric is going to attach an "options.txt" file which you can load into the UI and a command line then you should have everything you need to reproduce the same as the perf. team see.
23-06-2025
We are reviewing it internally and we will advise you soon.
20-06-2025
[~ecaspole] This would be my first exposure to J2DBench, how would I reproduce a test run which exhibits the performance issue? Thanks!