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.

To download the current JDK release, click here.
JDK 26
26 b12Fixed
Related Reports
Causes :  
Description
The regression is only seen on Mac and Windows, not on Linux intel or ARM.
Seems to be related to JDK-8353230.
Comments
25 is an LTS for .. well all vendors I expect .. so I think it is a backport candidate
21-08-2025

[~vdyakov] I'll defer to [~prr] on that one, I'm relatively new to the project and not familiar with the backporting criteria.
20-08-2025

[~dgredler] [~prr]do we want to back port it to 25u ?
20-08-2025

Changeset: c220a6c7 Branch: master Author: Daniel Gredler <dgredler@openjdk.org> Date: 2025-08-20 07:26:02 +0000 URL: https://git.openjdk.org/jdk/commit/c220a6c7bb5fe2e27514235f2efa9183a33f12a5
20-08-2025

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!
20-06-2025