Affects Version/s: None
Fix Version/s: 1.7.0
Currently we dispatch to metadata providers using reflection. With this change, we generate a dispatcher class and compile using Janino.
Currently calls to metadata providers are dispatched via reflection (Method.invoke, see ReflectiveRelMetadataProvider, ChainedRelMetadataProvider and CachingInvocationHandler), and I suspect that planning a complex query (especially with tracing enabled) makes millions of calls. Reflection has a performance problem; lots of boxing and unboxing and creating temporary arrays and bound objects.
One option we considered to improve performance was moving to MethodHandle. (JDK 1.7 introduced http://docs.oracle.com/javase/7/docs/api/java/lang/invoke/MethodHandle.html, a more efficient way to invoke methods. Access control etc. is done when the handle is created, not each invocation.) However, MethodHandle.invoke can dispatch only within one provider.
So, we should generate a dispatcher class, and compile and instantiate at run time using Janino.
For each metadata interface we will need to add a handler interface that has the same methods but two extra arguments (a sub-class of RelNode, and a RelMetadataQuery). Previously these arguments were passed by calling "bind" on an UnboundMetadata.
We can also make the dispatcher cache the results within a metadata call. This should yield a performance improvement when, say, a join requires many kinds of metadata (rowCount, averageRowSize, selectivity) and they all rely on the rowCount of the input, and that rowCount is expensive to compute.