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

Reply via email to