You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@calcite.apache.org by "Julian Hyde (JIRA)" <ji...@apache.org> on 2016/01/22 02:08:39 UTC

[jira] [Commented] (CALCITE-604) Invoke metadata providers via a class generated at runtime, rather than reflection

    [ https://issues.apache.org/jira/browse/CALCITE-604?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15111721#comment-15111721 ] 

Julian Hyde commented on CALCITE-604:
-------------------------------------

To each existing metadata class, you need to add a {{DEF}} constant and a handler interface. For example, {{Memory}} was

{code}
  public interface Memory extends Metadata {
    Double memory();
    Double cumulativeMemoryWithinPhase();
    Double cumulativeMemoryWithinPhaseSplit();
  }
{code}

and is now

{code}
  public interface Memory extends Metadata {
    MetadataDef<Memory> DEF = MetadataDef.of(Memory.class,
        Memory.Handler.class, BuiltInMethod.MEMORY.method,
        BuiltInMethod.CUMULATIVE_MEMORY_WITHIN_PHASE.method,
        BuiltInMethod.CUMULATIVE_MEMORY_WITHIN_PHASE_SPLIT.method);

    Double memory();
    Double cumulativeMemoryWithinPhase();
    Double cumulativeMemoryWithinPhaseSplit();

    interface Handler extends MetadataHandler<Memory> {
      Double memory(RelNode r, RelMetadataQuery mq);
      Double cumulativeMemoryWithinPhase(RelNode r, RelMetadataQuery mq);
      Double cumulativeMemoryWithinPhaseSplit(RelNode r, RelMetadataQuery mq);
    }
  }
{code}

and 

{code}
public class RelMdMemory {
  ...
{code}

is now

{code}
public class RelMdMemory implements MetadataHandler<BuiltInMetadata.Memory> {
  public MetadataDef<BuiltInMetadata.Memory> getDef() {
    return BuiltInMetadata.Memory.DEF;
  }
  ...
{code}

> Invoke metadata providers via a class generated at runtime, rather than reflection
> ----------------------------------------------------------------------------------
>
>                 Key: CALCITE-604
>                 URL: https://issues.apache.org/jira/browse/CALCITE-604
>             Project: Calcite
>          Issue Type: Bug
>            Reporter: Julian Hyde
>            Assignee: Julian Hyde
>
> 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.
> 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. However, MethodHandle.invoke can dispatch only within one provider.
> So, we should generate a handler 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.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)