https://bz.apache.org/bugzilla/show_bug.cgi?id=68119
Bug ID: 68119 Summary: Significant overhead in javax.el.CompositeELResolver.convertToType Product: Tomcat 9 Version: 9.0.x Hardware: All OS: All Status: NEW Severity: normal Priority: P2 Component: EL Assignee: dev@tomcat.apache.org Reporter: jeng...@amazon.com Target Milestone: ----- A high-volume, latency-sensitive application shows that approximately 0.8% of cpu is spent executing javax.el.CompositeELResolver.convertToType. Of this, > 95% is spent locally within the method, and the remainder is spent within javax.el.ELResolver.convertToType. The source code for CompositeELResolver.convertToType is: @Override public Object convertToType(ELContext context, Object obj, Class<?> type) { context.setPropertyResolved(false); int sz = this.size; for (int i = 0; i < sz; i++) { Object result = this.resolvers[i].convertToType(context, obj, type); if (context.isPropertyResolved()) { return result; } } return null; } The source code for ELResolver.convertToType is: public final Object convertToType(ELContext context, Object obj, Class<?> type) { context.setPropertyResolved(false); return null; } The high cost of CompositeELResolver.convertToType is because the loop uses vtable lookup for method invocations (INVOKEVIRTUAL); the calls cannot be inlined because ELResolver.convertToType can be overridden by any of approximately 15 implementations. However, within the Tomcat codebase, the only implementation that actually DOES anything is this CompositeELResolver. In effect, we're paying method invocation overhead that is guaranteed to do nothing except, perhaps, recursively do more nothing. Recognizing the potential need for custom implementations of ELResolvert.convertToType, we may want to maintain the current method but strip out the "known" implementations, such as those defined in ELContextImpl.getDefaultResolver(). This would allow the JIT compiler to optimize away loops over arrays of length zero, one, or two while still accommodating applications that directly call CompositeResolver.add(). Note that the array CompositeELResolver.resolvers is also used in other methods (for better reasons) and this may require a distinct array for convertToType. ELResolver.convertToType is relatively cheap, but is called so often that the aggregate is detectable by our tools. While the task of setting false to false is truly redundant, the changes suggested above are sufficient to eliminate the penalty with no further effort. Performance tests with a zero-length array show a 95% reduction in runtime; removing the code completely shows a 100% reduction in runtime. -- You are receiving this mail because: You are the assignee for the bug. --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org