[GitHub] [calcite] neoremind commented on a change in pull request #1875: [CALCITE-3873] Use global caching for ReflectiveVisitDispatcher implementation

2020-04-09 Thread GitBox
neoremind commented on a change in pull request #1875: [CALCITE-3873] Use 
global caching for ReflectiveVisitDispatcher implementation
URL: https://github.com/apache/calcite/pull/1875#discussion_r406614630
 
 

 ##
 File path: 
core/src/main/java/org/apache/calcite/util/ReflectiveVisitDispatcherImpl.java
 ##
 @@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.util;
+
+import org.apache.calcite.config.CalciteSystemProperty;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.ImmutableList;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Looking up methods relating to reflective visitation. Caching reflect
+ * method globally, every instance of the class shares the global cache to
+ * mitigate java reflection invocation overhead.
+ *
+ * @param  Argument type
+ * @param  Return type
+ */
+public class ReflectiveVisitDispatcherImpl
+implements ReflectiveVisitDispatcher {
+
+  /**
+   * Global singleton cache with limited size used to cache methods. Every 
instance
+   * of the class will share this cache to mitigate java reflection invocation
+   * overhead when looking up methods.
+   * Note that there should be multiple ways to implement caching, for 
example,
+   * 1) Passing Cache between objects and hopefully using Java's
+   * RAII (Resource Acquisition Is Initialization) like try-finally to
+   * garbage collect.
+   * 2) Using ThreadLocal to store cache per thread.
+   * 3) Using global cache.
+   * Solution 1) and 2) could introduce complexity to the main course and 
it only
+   * works per instance or per thread.
+   * Solution 3) which introduces a controllable global small sized cache is a
+   * better solution to balance memory usage and performance.
+   */
+  private static final Cache, Method> GLOBAL_METHOD_CACHE =
 
 Review comment:
   Yes, good catch, method referencing of CacheLoader.from is more readable and 
less code is needed.


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [calcite] neoremind commented on a change in pull request #1875: [CALCITE-3873] Use global caching for ReflectiveVisitDispatcher implementation

2020-04-01 Thread GitBox
neoremind commented on a change in pull request #1875: [CALCITE-3873] Use 
global caching for ReflectiveVisitDispatcher implementation
URL: https://github.com/apache/calcite/pull/1875#discussion_r401494623
 
 

 ##
 File path: 
core/src/main/java/org/apache/calcite/config/CalciteSystemProperty.java
 ##
 @@ -332,6 +332,23 @@
   intProperty("calcite.bindable.cache.concurrencyLevel", 1,
   v -> v >= 1 && v <= Integer.MAX_VALUE);
 
+  /**
+   * The maximum size of the cache used for storing methods by
+   * {@link org.apache.calcite.util.ReflectiveVisitDispatcher}.
+   *
+   * The default value is 128.
+   *
+   * The property can take any value between [1, 256] inclusive. If the
+   * value is not valid (or not specified) then the default value is used.
+   *
+   * Looking up method by reflection invocation is slow, caching technique 
will
+   * mitigate the overhead.
+   */
+  public static final CalciteSystemProperty
+  REFLECT_VISIT_DISPATCHER_METHOD_CACHE_MAX_SIZE =
+  intProperty("calcite.reflect.visit.dispatcher.method.cache.maxSize", 128,
+  v -> v > 0 && v <= 256);
 
 Review comment:
   got it, I will update later.


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [calcite] neoremind commented on a change in pull request #1875: [CALCITE-3873] Use global caching for ReflectiveVisitDispatcher implementation

2020-04-01 Thread GitBox
neoremind commented on a change in pull request #1875: [CALCITE-3873] Use 
global caching for ReflectiveVisitDispatcher implementation
URL: https://github.com/apache/calcite/pull/1875#discussion_r401474401
 
 

 ##
 File path: 
core/src/main/java/org/apache/calcite/config/CalciteSystemProperty.java
 ##
 @@ -332,6 +332,23 @@
   intProperty("calcite.bindable.cache.concurrencyLevel", 1,
   v -> v >= 1 && v <= Integer.MAX_VALUE);
 
+  /**
+   * The maximum size of the cache used for storing methods by
+   * {@link org.apache.calcite.util.ReflectiveVisitDispatcher}.
+   *
+   * The default value is 128.
+   *
+   * The property can take any value between [1, 256] inclusive. If the
+   * value is not valid (or not specified) then the default value is used.
+   *
+   * Looking up method by reflection invocation is slow, caching technique 
will
+   * mitigate the overhead.
+   */
+  public static final CalciteSystemProperty
+  REFLECT_VISIT_DISPATCHER_METHOD_CACHE_MAX_SIZE =
+  intProperty("calcite.reflect.visit.dispatcher.method.cache.maxSize", 128,
+  v -> v > 0 && v <= 256);
 
 Review comment:
   I make it as configurable in the previous commit through constructor, so 
that the caller would make choice, but I take suggestion from hsyuan to make it 
always as global cache 


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [calcite] neoremind commented on a change in pull request #1875: [CALCITE-3873] Use global caching for ReflectiveVisitDispatcher implementation

2020-04-01 Thread GitBox
neoremind commented on a change in pull request #1875: [CALCITE-3873] Use 
global caching for ReflectiveVisitDispatcher implementation
URL: https://github.com/apache/calcite/pull/1875#discussion_r401439918
 
 

 ##
 File path: 
core/src/main/java/org/apache/calcite/config/CalciteSystemProperty.java
 ##
 @@ -332,6 +332,23 @@
   intProperty("calcite.bindable.cache.concurrencyLevel", 1,
   v -> v >= 1 && v <= Integer.MAX_VALUE);
 
+  /**
+   * The maximum size of the cache used for storing methods by
+   * {@link org.apache.calcite.util.ReflectiveVisitDispatcher}.
+   *
+   * The default value is 128.
+   *
+   * The property can take any value between [1, 256] inclusive. If the
+   * value is not valid (or not specified) then the default value is used.
+   *
+   * Looking up method by reflection invocation is slow, caching technique 
will
+   * mitigate the overhead.
+   */
+  public static final CalciteSystemProperty
+  REFLECT_VISIT_DISPATCHER_METHOD_CACHE_MAX_SIZE =
+  intProperty("calcite.reflect.visit.dispatcher.method.cache.maxSize", 128,
+  v -> v > 0 && v <= 256);
 
 Review comment:
   I count the reference of the method: `ReflectUtil#createMethodDispatcher` 
and `ReflectUtil#createDispatcher`, there are 68 places might be called through 
ReflectUtil (see below), the methods we are caching is limited, so I initialize 
the max cache size to 128 to hold them on, upper limit to 256 (answer your 
below question) in case future updates might use this feature as well, so it 
won't be a big burden as they stay in memory. In my opinion, I would rather 
call it a global caching, not memory leak, because we might use them 
repeatedly. 
   
   ```
   org.apache.calcite.rel.rel2sql.RelToSqlConverter#visit: 18 overloading 
methods
   org.apache.calcite.sql2rel.RelDecorrelator#decorrelateRel: 15 overloading 
methods
   org.apache.calcite.sql2rel.RelFieldTrimmer#trimFields: 11 overloading methods
   org.apache.calcite.sql2rel.RelStructuredTypeFlattener#rewriteRel: 22 
overloading methods
   org.apache.calcite.interpreter.Interpreter.CompilerImpl#rewrite: 1 method.
   org.apache.calcite.interpreter.Interpreter.CompilerImpl#visit: 1 method.
   ```


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [calcite] neoremind commented on a change in pull request #1875: [CALCITE-3873] Use global caching for ReflectiveVisitDispatcher implementation

2020-04-01 Thread GitBox
neoremind commented on a change in pull request #1875: [CALCITE-3873] Use 
global caching for ReflectiveVisitDispatcher implementation
URL: https://github.com/apache/calcite/pull/1875#discussion_r401439918
 
 

 ##
 File path: 
core/src/main/java/org/apache/calcite/config/CalciteSystemProperty.java
 ##
 @@ -332,6 +332,23 @@
   intProperty("calcite.bindable.cache.concurrencyLevel", 1,
   v -> v >= 1 && v <= Integer.MAX_VALUE);
 
+  /**
+   * The maximum size of the cache used for storing methods by
+   * {@link org.apache.calcite.util.ReflectiveVisitDispatcher}.
+   *
+   * The default value is 128.
+   *
+   * The property can take any value between [1, 256] inclusive. If the
+   * value is not valid (or not specified) then the default value is used.
+   *
+   * Looking up method by reflection invocation is slow, caching technique 
will
+   * mitigate the overhead.
+   */
+  public static final CalciteSystemProperty
+  REFLECT_VISIT_DISPATCHER_METHOD_CACHE_MAX_SIZE =
+  intProperty("calcite.reflect.visit.dispatcher.method.cache.maxSize", 128,
+  v -> v > 0 && v <= 256);
 
 Review comment:
   I count the reference of the method: `ReflectUtil#createMethodDispatcher` 
and `ReflectUtil#createDispatcher`, there are 68 places might be called through 
ReflectUtil (see below), the methods we are caching is limited, so I initialize 
the max cache size to 128 to hold them on, upper limit to 256 (answer your 
below question) to not make it not a big burden as they stay in memory. In my 
opinion, I would rather call it a global caching, not memory leak, because we 
might use them repeatedly. 
   
   ```
   org.apache.calcite.rel.rel2sql.RelToSqlConverter#visit: 18 overloading 
methods
   org.apache.calcite.sql2rel.RelDecorrelator#decorrelateRel: 15 overloading 
methods
   org.apache.calcite.sql2rel.RelFieldTrimmer#trimFields: 11 overloading methods
   org.apache.calcite.sql2rel.RelStructuredTypeFlattener#rewriteRel: 22  
overloading methods
   org.apache.calcite.interpreter.Interpreter.CompilerImpl#rewrite: 1 method.
   org.apache.calcite.interpreter.Interpreter.CompilerImpl#visit: 1 method.
   ```


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [calcite] neoremind commented on a change in pull request #1875: [CALCITE-3873] Use global caching for ReflectiveVisitDispatcher implementation

2020-03-26 Thread GitBox
neoremind commented on a change in pull request #1875: [CALCITE-3873] Use 
global caching for ReflectiveVisitDispatcher implementation
URL: https://github.com/apache/calcite/pull/1875#discussion_r398636010
 
 

 ##
 File path: 
core/src/main/java/org/apache/calcite/util/ReflectVisitDispatcherImpl.java
 ##
 @@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.util;
+
+import org.apache.calcite.config.CalciteSystemProperty;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.ImmutableList;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Looking up methods relating to reflective visitation. Caching reflect
+ * method globally, every instance of the class shares the global cache to
+ * mitigating java reflection invocation overhead.
+ *
 
 Review comment:
   Thanks for pointing out typo :-)


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [calcite] neoremind commented on a change in pull request #1875: [CALCITE-3873] Use global caching for ReflectiveVisitDispatcher implementation

2020-03-26 Thread GitBox
neoremind commented on a change in pull request #1875: [CALCITE-3873] Use 
global caching for ReflectiveVisitDispatcher implementation
URL: https://github.com/apache/calcite/pull/1875#discussion_r398391089
 
 

 ##
 File path: core/src/main/java/org/apache/calcite/util/ReflectUtil.java
 ##
 @@ -403,71 +403,40 @@ private static Method lookupVisitMethod(
   }
 
   /**
-   * Creates a dispatcher for calls to {@link #lookupVisitMethod}. The
-   * dispatcher caches methods between invocations.
+   * Creates a dispatcher for calls to {@link #lookupVisitMethod}. By default 
the
+   * dispatcher caches methods globally. If caching methods between invocations
+   * is preferred, use the overridden method {@link #createDispatcher(Class, 
Class, boolean)}.
*
-   * @param visitorBaseClazz Visitor base class
-   * @param visiteeBaseClazz Visitee base class
+   * @param visitorBaseClazzVisitor base class
+   * @param visiteeBaseClazzVisitee base class
* @return cache of methods
*/
   public static  ReflectiveVisitDispatcher createDispatcher(
   final Class visitorBaseClazz,
   final Class visiteeBaseClazz) {
+return createDispatcher(visitorBaseClazz, visiteeBaseClazz, true);
+  }
+
+  /**
+   * Creates a dispatcher for calls to {@link #lookupVisitMethod}.
+   *
+   * @param visitorBaseClazzVisitor base class
+   * @param visiteeBaseClazzVisitee base class
+   * @param useGlobalMethodCacheIf set to true, the created dispatchers 
will
+   *share a globally cache to store methods to
+   *mitigating reflection invocation overhead
+   *when looking up method. If set to false, 
every
+   *dispatcher instance will only cache methods
+   *between invocations individually.
+   * @return cache of methods
+   */
+  public static  ReflectiveVisitDispatcher createDispatcher(
+  final Class visitorBaseClazz,
+  final Class visiteeBaseClazz,
+  final boolean useGlobalMethodCache) {
 
 Review comment:
   Comment addressed. Make `ReflectiveVisitDispatcher` to always use global 
caching.


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [calcite] neoremind commented on a change in pull request #1875: [CALCITE-3873] Use global caching for ReflectiveVisitDispatcher implementation

2020-03-25 Thread GitBox
neoremind commented on a change in pull request #1875: [CALCITE-3873] Use 
global caching for ReflectiveVisitDispatcher implementation
URL: https://github.com/apache/calcite/pull/1875#discussion_r398291034
 
 

 ##
 File path: core/src/main/java/org/apache/calcite/util/ReflectUtil.java
 ##
 @@ -403,71 +403,40 @@ private static Method lookupVisitMethod(
   }
 
   /**
-   * Creates a dispatcher for calls to {@link #lookupVisitMethod}. The
-   * dispatcher caches methods between invocations.
+   * Creates a dispatcher for calls to {@link #lookupVisitMethod}. By default 
the
+   * dispatcher caches methods globally. If caching methods between invocations
+   * is preferred, use the overridden method {@link #createDispatcher(Class, 
Class, boolean)}.
*
-   * @param visitorBaseClazz Visitor base class
-   * @param visiteeBaseClazz Visitee base class
+   * @param visitorBaseClazzVisitor base class
+   * @param visiteeBaseClazzVisitee base class
* @return cache of methods
*/
   public static  ReflectiveVisitDispatcher createDispatcher(
   final Class visitorBaseClazz,
   final Class visiteeBaseClazz) {
+return createDispatcher(visitorBaseClazz, visiteeBaseClazz, true);
+  }
+
+  /**
+   * Creates a dispatcher for calls to {@link #lookupVisitMethod}.
+   *
+   * @param visitorBaseClazzVisitor base class
+   * @param visiteeBaseClazzVisitee base class
+   * @param useGlobalMethodCacheIf set to true, the created dispatchers 
will
+   *share a globally cache to store methods to
+   *mitigating reflection invocation overhead
+   *when looking up method. If set to false, 
every
+   *dispatcher instance will only cache methods
+   *between invocations individually.
+   * @return cache of methods
+   */
+  public static  ReflectiveVisitDispatcher createDispatcher(
+  final Class visitorBaseClazz,
+  final Class visiteeBaseClazz,
+  final boolean useGlobalMethodCache) {
 
 Review comment:
   To maintain backward compatibility, I add one param boolean 
`useGlobalMethodCache` to method `ReflectiveVisitDispatcher 
createDispatcher(..)` and provide an overridden method to make 
`useGlobalMethodCache=true` by default, so anywhere else won't be changed, but 
the underlying behavior will enable global caching. In case there might be 
situations where `ReflectiveVisitDispatcher` is likely to cache per instance 
and does not want to bother the global cache, so to make that flexibility 
possible I made such change.


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [calcite] neoremind commented on a change in pull request #1875: [CALCITE-3873] Use global caching for ReflectiveVisitDispatcher implementation

2020-03-25 Thread GitBox
neoremind commented on a change in pull request #1875: [CALCITE-3873] Use 
global caching for ReflectiveVisitDispatcher implementation
URL: https://github.com/apache/calcite/pull/1875#discussion_r398291034
 
 

 ##
 File path: core/src/main/java/org/apache/calcite/util/ReflectUtil.java
 ##
 @@ -403,71 +403,40 @@ private static Method lookupVisitMethod(
   }
 
   /**
-   * Creates a dispatcher for calls to {@link #lookupVisitMethod}. The
-   * dispatcher caches methods between invocations.
+   * Creates a dispatcher for calls to {@link #lookupVisitMethod}. By default 
the
+   * dispatcher caches methods globally. If caching methods between invocations
+   * is preferred, use the overridden method {@link #createDispatcher(Class, 
Class, boolean)}.
*
-   * @param visitorBaseClazz Visitor base class
-   * @param visiteeBaseClazz Visitee base class
+   * @param visitorBaseClazzVisitor base class
+   * @param visiteeBaseClazzVisitee base class
* @return cache of methods
*/
   public static  ReflectiveVisitDispatcher createDispatcher(
   final Class visitorBaseClazz,
   final Class visiteeBaseClazz) {
+return createDispatcher(visitorBaseClazz, visiteeBaseClazz, true);
+  }
+
+  /**
+   * Creates a dispatcher for calls to {@link #lookupVisitMethod}.
+   *
+   * @param visitorBaseClazzVisitor base class
+   * @param visiteeBaseClazzVisitee base class
+   * @param useGlobalMethodCacheIf set to true, the created dispatchers 
will
+   *share a globally cache to store methods to
+   *mitigating reflection invocation overhead
+   *when looking up method. If set to false, 
every
+   *dispatcher instance will only cache methods
+   *between invocations individually.
+   * @return cache of methods
+   */
+  public static  ReflectiveVisitDispatcher createDispatcher(
+  final Class visitorBaseClazz,
+  final Class visiteeBaseClazz,
+  final boolean useGlobalMethodCache) {
 
 Review comment:
   To maintain backward compatibility, I add one param boolean 
`useGlobalMethodCache` to method `ReflectiveVisitDispatcher 
createDispatcher(..)` and provide an overridden method to make 
`useGlobalMethodCache=true` by default, so anywhere else won't be changed, but 
the underlying behavior will enable caching. In case there might be situations 
where `ReflectiveVisitDispatcher` is likely to cache per instance and does not 
want to bother the global cache, so to make that flexibility possible I made 
such change.


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services