Bug 66294 - Util.getContextClassLoader() can be a hotspot
Summary: Util.getContextClassLoader() can be a hotspot
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 9
Classification: Unclassified
Component: EL (show other bugs)
Version: 9.0.65
Hardware: All Linux
: P2 regression (vote)
Target Milestone: -----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-10-04 10:20 UTC by Maximilian Hensel
Modified: 2022-11-08 14:21 UTC (History)
1 user (show)



Attachments
Benchmark which shows performance difference between getting class loader with/without privileges (1.02 KB, text/plain)
2022-10-04 10:20 UTC, Maximilian Hensel
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Maximilian Hensel 2022-10-04 10:20:37 UTC
Created attachment 38401 [details]
Benchmark which shows performance difference between getting class loader with/without privileges

In our application Util.getContextClassLoader() is a hotspot with almost all the cost coming from AccessController.doPrivileged. By adding instrumentation we've confirmed that the native implementation of AccessController.doPrivileged itself and not PrivilegedGetTccl.run() is expensive. In an example request to our application we had 17000 calls to Util.getContextClassLoader() and recorded this CPU time in the methods:
0.682 ms for javax.el.Util$PrivilegedGetTccl.run()
27.800 ms for javax.el.Util.getContextClassLoader()

This potential hotspot was introduced four years ago when a change was made to get the context class loader of the Thread with privileges enabled: https://bz.apache.org/bugzilla/show_bug.cgi?id=62080

We'd like to fix this hotspot by calling Thread.currentThread().getContextClassLoader() without privileges enabled again. This would be a revert of the change here: https://github.com/apache/tomcat/commit/7c359957f0b600b92e964b1a2497374e6cac4bc3#diff-f5b7c13f66b3d070a6b1c1713ad4b60fd70b26f579a746edc8fe9f19109243b2L93
Since this change addressed a rare bug, we probably have to make this change backwards compatible by adding a configuration switch.

I have also included a basic benchmark which compares the performance of the two approaches. The benchmark shows a difference by factor 100. I ran the benchmark with JDK 8 and 11.

Since SecurityManager and related functionality are on track to deprecation, this change may be mandatory in the future, irrespective of the performance benefit:
https://openjdk.org/jeps/411
Comment 1 Mark Thomas 2022-10-12 17:51:23 UTC
Given that the SecurityManager is heading towards deprecation, why not just run without a SecurityManager to avoid this hotspot?
Comment 2 Maximilian Hensel 2022-10-13 14:50:38 UTC
(In reply to Mark Thomas from comment #1)
> Given that the SecurityManager is heading towards deprecation, why not just
> run without a SecurityManager to avoid this hotspot?

We've checked this, but unfortunately, it is not possible for us to run without SecurityManager for non-Tomcat reasons.
Comment 3 Mark Thomas 2022-11-08 13:19:21 UTC
Fixed in:
- 10.1.x for 10.1.2 onwards
-  9.0.x for  9.0.69 onwards
-  8.5.x for  8.5.84 onwards

The privileged block is now disabled by default so this should "just work" once you upgrade.
Comment 4 Maximilian Hensel 2022-11-08 14:21:59 UTC
Thanks, that's great to hear.