You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by la...@apache.org on 2019/05/16 18:03:54 UTC

[calcite] branch master updated: [CALCITE-3062] Do not populate provenanceMap if not debug

This is an automated email from the ASF dual-hosted git repository.

laurent pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/master by this push:
     new c6b6800  [CALCITE-3062] Do not populate provenanceMap if not debug
c6b6800 is described below

commit c6b6800c220e513f1d9a2b167b2f14cb689c0b06
Author: Laurent Goujon <la...@apache.org>
AuthorDate: Fri May 10 15:37:14 2019 -0700

    [CALCITE-3062] Do not populate provenanceMap if not debug
    
    VolcanoPlanner.provenanceMap captures provenance of all rel nodes added
    to the planner but the information is only printed out if planner log
    level is debug or finer.  As the map can get quite big with complex
    queries, the memory usage can increase significantly.
    
    Detect if planner log level is debug when creating a new volcano planner
    and use a blackhole map so that the map is not populated by default.
    
    Change-Id: If6393eb07438ea5f922c9f78f26089160926ef37
---
 .../calcite/plan/volcano/VolcanoPlanner.java       |  10 +-
 .../java/org/apache/calcite/util/BlackholeMap.java | 114 +++++++++++++++++++++
 .../main/java/org/apache/calcite/util/Util.java    |   5 +
 .../java/org/apache/calcite/util/UtilTest.java     |  21 ++++
 4 files changed, 148 insertions(+), 2 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java b/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
index eb4561a..dca0342 100644
--- a/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
+++ b/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
@@ -235,7 +235,7 @@ public class VolcanoPlanner extends AbstractRelOptPlanner {
   private final Map<List<String>, RelOptLattice> latticeByName =
       new LinkedHashMap<>();
 
-  final Map<RelNode, Provenance> provenanceMap = new HashMap<>();
+  final Map<RelNode, Provenance> provenanceMap;
 
   final Deque<VolcanoRuleCall> ruleCallStack = new ArrayDeque<>();
 
@@ -276,6 +276,9 @@ public class VolcanoPlanner extends AbstractRelOptPlanner {
     super(costFactory == null ? VolcanoCost.FACTORY : costFactory, //
         externalContext);
     this.zeroCost = this.costFactory.makeZeroCost();
+    // If LOGGER is debug enabled, enable provenance information to be captured
+    this.provenanceMap = LOGGER.isDebugEnabled() ? new HashMap<>()
+        : Util.blackholeMap();
   }
 
   //~ Methods ----------------------------------------------------------------
@@ -435,6 +438,7 @@ public class VolcanoPlanner extends AbstractRelOptPlanner {
     this.ruleNames.clear();
     this.materializations.clear();
     this.latticeByName.clear();
+    this.provenanceMap.clear();
   }
 
   public List<RelOptRule> getRules() {
@@ -656,7 +660,9 @@ public class VolcanoPlanner extends AbstractRelOptPlanner {
       LOGGER.debug(
           "Cheapest plan:\n{}", RelOptUtil.toString(cheapest, SqlExplainLevel.ALL_ATTRIBUTES));
 
-      LOGGER.debug("Provenance:\n{}", provenance(cheapest));
+      if (!provenanceMap.isEmpty()) {
+        LOGGER.debug("Provenance:\n{}", provenance(cheapest));
+      }
     }
     return cheapest;
   }
diff --git a/core/src/main/java/org/apache/calcite/util/BlackholeMap.java b/core/src/main/java/org/apache/calcite/util/BlackholeMap.java
new file mode 100644
index 0000000..045275e
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/util/BlackholeMap.java
@@ -0,0 +1,114 @@
+/*
+ * 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 java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * A {@code java.util.Map} implementation which ignores any {@code put} operation.
+ *
+ * The implementation does not fully conform to {@code java.util.Map} API, as any
+ * write operation would succeed, but any read operation would not return any value.
+ *
+ * @param <K> the type of the keys for the map
+ * @param <V> the type of the values for the map
+ */
+final class BlackholeMap<K, V> extends AbstractMap<K, V> {
+  /**
+   * Blackhole implementation of {@code Iterator}. Always empty.
+   *
+   * @param <E> type of the entries for the iterator
+   */
+  private static final class BHIterator<E> implements Iterator<E> {
+    @SuppressWarnings("rawtypes")
+    private static final Iterator INSTANCE = new BHIterator<>();
+    private BHIterator() {}
+
+    @Override public boolean hasNext() {
+      return false;
+    }
+
+    @Override public E next() {
+      throw new NoSuchElementException();
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> Iterator<T> of() {
+      return (Iterator<T>) INSTANCE;
+    }
+  }
+
+  /**
+   * Blackhole implementation of {@code Set}. Always ignores add.
+   *
+   * @param <E> type of the entries for the set
+   */
+  private static class BHSet<E> extends AbstractSet<E> {
+    @SuppressWarnings("rawtypes")
+    private static final Set INSTANCE = new BHSet<>();
+
+    @Override public boolean add(E e) {
+      return true;
+    }
+
+    @Override public Iterator<E> iterator() {
+      return BHIterator.of();
+    }
+
+    @Override public int size() {
+      return 0;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> Set<T> of() {
+      return (Set<T>) INSTANCE;
+    }
+
+  }
+
+  @SuppressWarnings("rawtypes")
+  private static final Map INSTANCE = new BlackholeMap<>();
+
+  private BlackholeMap() {}
+
+  @Override public V put(K key, V value) {
+    return null;
+  }
+
+  @Override public Set<Entry<K, V>> entrySet() {
+    return BHSet.of();
+  }
+
+  /**
+   * Gets an instance of {@code BlackholeMap}
+   *
+   * @param <K> type of the keys for the map
+   * @param <V> type of the values for the map
+   * @return a blackhole map
+   */
+  @SuppressWarnings("unchecked")
+  public static <K, V> Map<K, V> of() {
+    return (Map<K, V>) INSTANCE;
+  }
+}
+
+// End BlackholeMap.java
diff --git a/core/src/main/java/org/apache/calcite/util/Util.java b/core/src/main/java/org/apache/calcite/util/Util.java
index 9a7296d..289cf63 100644
--- a/core/src/main/java/org/apache/calcite/util/Util.java
+++ b/core/src/main/java/org/apache/calcite/util/Util.java
@@ -2428,6 +2428,11 @@ public class Util {
     };
   }
 
+  /** Returns a map which ignores any write operation. */
+  public static <K, V> Map<K, V> blackholeMap() {
+    return BlackholeMap.of();
+  }
+
   //~ Inner Classes ----------------------------------------------------------
 
   /**
diff --git a/core/src/test/java/org/apache/calcite/util/UtilTest.java b/core/src/test/java/org/apache/calcite/util/UtilTest.java
index bd9c28d..d7246fd 100644
--- a/core/src/test/java/org/apache/calcite/util/UtilTest.java
+++ b/core/src/test/java/org/apache/calcite/util/UtilTest.java
@@ -58,6 +58,7 @@ import java.lang.reflect.Modifier;
 import java.math.BigDecimal;
 import java.sql.Timestamp;
 import java.text.MessageFormat;
+import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.BitSet;
@@ -75,6 +76,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.NavigableMap;
 import java.util.NavigableSet;
+import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.Properties;
 import java.util.Random;
@@ -2467,6 +2469,25 @@ public class UtilTest {
     assertThat(c.classCount(), is(0));
   }
 
+  @Test public void testBlackHoleMap() {
+    final Map<Integer, Integer> map = BlackholeMap.of();
+
+    for (int i = 0; i < 100; i++) {
+      assertThat(map.put(i, i * i), is(nullValue()));
+      assertThat(map.size(), is(0));
+      assertThat(map.entrySet().add(new SimpleEntry<>(i, i * i)), is(true));
+      assertThat(map.entrySet().size(), is(0));
+      assertThat(map.keySet().size(), is(0));
+      assertThat(map.values().size(), is(0));
+      assertThat(map.entrySet().iterator().hasNext(), is(false));
+      try {
+        map.entrySet().iterator().next();
+        fail();
+      } catch (NoSuchElementException e) {
+        // Success
+      }
+    }
+  }
   private static <E> Matcher<Iterable<E>> isIterable(final Iterable<E> iterable) {
     final List<E> list = toList(iterable);
     return new TypeSafeMatcher<Iterable<E>>() {