jengebr opened a new pull request, #770: URL: https://github.com/apache/tomcat/pull/770
This change fixes https://bz.apache.org/bugzilla/show_bug.cgi?id=69381 by caching the JVM-provided `Method[]`. The OpenJDK compiler creates duplicate `Method` objects on every call to `Class.getMethods()`, which is an expensive task that is only made worse on complex classes that have more `Method`s. ClassLoader leaks are avoided by keying off the class' name (`String`) and storing the `Method[]` in a `WeakReference<Method[]>`. The cost of the concurrency is easily outweighed by the savings from not duplicating dozens of objects, as demonstrated from output in the modified `TestELParserPerformance` provided at the bottom of this PR body. Key points from the data: 1. Non-reflective expressions are unaffected. 2. For a bean with 10 methods, this logic is 42% faster. 3. For a bean with 20 methods, this logic is 57% faster 4. The new code still scales by number of `Method`s, but the growth is far less (4% vs 40%). Original: ``` ${beanA.name} duration=[599ms] or 599 ns each ${beanA.name} duration=[337ms] or 337 ns each ${beanA.name} duration=[330ms] or 330 ns each ${beanA.name} duration=[331ms] or 331 ns each ${beanA.name} duration=[330ms] or 330 ns each Result: name ${beanA.getName()} duration=[1586ms] or 1586 ns each ${beanA.getName()} duration=[1401ms] or 1401 ns each ${beanA.getName()} duration=[1477ms] or 1477 ns each ${beanA.getName()} duration=[1401ms] or 1401 ns each ${beanA.getName()} duration=[1398ms] or 1398 ns each Result: name ${beanB.getName()} duration=[1921ms] or 1921 ns each ${beanB.getName()} duration=[1972ms] or 1972 ns each ${beanB.getName()} duration=[1969ms] or 1969 ns each ${beanB.getName()} duration=[1970ms] or 1970 ns each ${beanB.getName()} duration=[1974ms] or 1974 ns each Result: name ``` Optimized: ``` ${beanA.name} duration=[570ms] or 570 ns each ${beanA.name} duration=[336ms] or 336 ns each ${beanA.name} duration=[330ms] or 330 ns each ${beanA.name} duration=[330ms] or 330 ns each ${beanA.name} duration=[330ms] or 330 ns each Result: name ${beanA.getName()} duration=[990ms] or 990 ns each ${beanA.getName()} duration=[807ms] or 807 ns each ${beanA.getName()} duration=[814ms] or 814 ns each ${beanA.getName()} duration=[815ms] or 815 ns each ${beanA.getName()} duration=[812ms] or 812 ns each Result: name ${beanB.getName()} duration=[883ms] or 883 ns each ${beanB.getName()} duration=[848ms] or 848 ns each ${beanB.getName()} duration=[848ms] or 848 ns each ${beanB.getName()} duration=[848ms] or 848 ns each ${beanB.getName()} duration=[848ms] or 848 ns each Result: name ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org