In-depth profiling of a high-volume, performance-sensitive application identified an avoidable use of an itable method call, a.k.a. invoking an interface method rather than a static or virtual method. The performance impact is well described at https://stackoverflow.com/questions/21679998/does-it-matter-for-runtime-performance-if-a-method-is-called-by-its-explicit-typ#:~:text=invokeinterface%20is%20known%20to%20be,to%20prefer%20invokevirtual%20to%20invokeinterface%20 The underlying problem is calls to Node.getValue(), such as in AstAnd.getValue(): Object obj = children[0].getValue(ctx); where "children" is "Node[]". There are roughly 30 distinct implementations of Node and no JIT is capable of optimizing those away. Fortunately, all 30 of the Node implementation extends the class SimpleNode. Changing the references to Node to use SimpleNode will enable JVMs to instead use invokevirtual. Our tools struggle to measure the actual impact of this issue, because it occurs in small amounts in so many different code paths, and occurs repeatedly in each layer of a nested AST evaluation. My best guess is 0.2% cpu, directly on the latency critical path. I hope the fix is as simple as it seems. :)
Perhaps a simpler solution is to change Node from an interface to an abstract class, then have SimpleNode extends Node rather than implement it. This achieves the same ends with more targeted and isolated changes.
Created attachment 39353 [details] Proposed patch - Tomcat 11 - v1 This is complicated by Node being generated code. Since there isn't a test to validate the fix, is the attached what is being requested?
Yes, that's perfect, thanks!
Fixed in: - 11.0.x for 11.0.0-M14 onwards - 10.1.x for 10.1.16 onwards - 9.0.x for 9.0.83 onwards - 8.5.x for 8.5.96 onwards
Production results confirm a small improvement - greater than zero but not enormous. Sorry, I'm not able to provide hard numbers because of the huge number of distinct code paths.