Add TaskTree Caching stats to query output
Change-Id: I91d48e5f1199ba61a4edf63e4444285ed820a40c
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/HitHashMap.java b/src/main/java/com/googlesource/gerrit/plugins/task/HitHashMap.java
new file mode 100644
index 0000000..ff9ff3b
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/HitHashMap.java
@@ -0,0 +1,87 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed 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 com.googlesource.gerrit.plugins.task;
+
+import java.util.HashMap;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+public class HitHashMap<K, V> extends HashMap<K, V> implements StatisticsMap<K, V> {
+ public static class Statistics {
+ public long hits;
+ public int size;
+ }
+
+ public static final long serialVersionUID = 1;
+
+ protected Statistics statistics;
+
+ @Override
+ public V get(Object key) {
+ V v = super.get(key);
+ if (statistics != null && v != null) {
+ statistics.hits++;
+ }
+ return v;
+ }
+
+ @Override
+ public V getOrDefault(Object key, V dv) {
+ V v = get(key);
+ if (v == null) {
+ return dv;
+ }
+ return v;
+ }
+
+ @Override
+ public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
+ V v = get(key);
+ if (v == null) {
+ v = mappingFunction.apply(key);
+ if (v != null) {
+ put(key, v);
+ }
+ }
+ return v;
+ }
+
+ @Override
+ public V computeIfPresent(
+ K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException(); // Todo if needed
+ }
+
+ @Override
+ public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException(); // Todo if needed
+ }
+
+ @Override
+ public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException(); // Todo if needed
+ }
+
+ @Override
+ public void initStatistics() {
+ statistics = new Statistics();
+ }
+
+ @Override
+ public Object getStatistics() {
+ statistics.size = size();
+ return statistics;
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/HitHashMapOfCollection.java b/src/main/java/com/googlesource/gerrit/plugins/task/HitHashMapOfCollection.java
new file mode 100644
index 0000000..7429dba
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/HitHashMapOfCollection.java
@@ -0,0 +1,63 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed 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 com.googlesource.gerrit.plugins.task;
+
+import static java.util.stream.Collectors.toList;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+
+public class HitHashMapOfCollection<K, V extends Collection<?>> extends HitHashMap<K, V> {
+ public static class Statistics extends HitHashMap.Statistics {
+ public List<Integer> top5CollectionSizes;
+ public List<Integer> bottom5CollectionSizes;
+ }
+
+ public static final long serialVersionUID = 1;
+
+ protected Statistics statistics;
+
+ @Override
+ public void initStatistics() {
+ super.initStatistics();
+ statistics = new Statistics();
+ }
+
+ @Override
+ public Object getStatistics() {
+ super.getStatistics();
+ statistics.hits = super.statistics.hits;
+ statistics.size = super.statistics.size;
+
+ List<Integer> collectionSizes =
+ values().stream().map(l -> l.size()).sorted(Comparator.reverseOrder()).collect(toList());
+ statistics.top5CollectionSizes = new ArrayList<>(5);
+ statistics.bottom5CollectionSizes = new ArrayList<>(5);
+ for (int i = 0; i < 5 && i < collectionSizes.size(); i++) {
+ statistics.top5CollectionSizes.add(collectionSizes.get(i));
+ int bottom = collectionSizes.size() - 6 + i;
+ if (bottom > 4 && bottom < collectionSizes.size()) {
+ // The > 4 ensures that there are no entries also in the top list
+ statistics.bottom5CollectionSizes.add(collectionSizes.get(bottom));
+ }
+ }
+ if (statistics.bottom5CollectionSizes.isEmpty()) {
+ statistics.bottom5CollectionSizes = null;
+ }
+ return statistics;
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/StatisticsMap.java b/src/main/java/com/googlesource/gerrit/plugins/task/StatisticsMap.java
new file mode 100644
index 0000000..aeeb434
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/StatisticsMap.java
@@ -0,0 +1,23 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed 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 com.googlesource.gerrit.plugins.task;
+
+import java.util.Map;
+
+public interface StatisticsMap<K, V> extends Map<K, V> {
+ void initStatistics();
+
+ Object getStatistics();
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java
index 00b7dcf..4dfeb99 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java
@@ -56,6 +56,7 @@
public long numberOfTaskPluginAttributes;
public PredicateCache.Statistics predicateCache;
public Preloader.Statistics preloader;
+ public TaskTree.Statistics treeCaches;
}
public static class TaskAttribute {
@@ -334,6 +335,7 @@
statistics = new Statistics();
predicateCache.initStatistics();
definitions.preloader.initStatistics();
+ definitions.initStatistics();
}
}
@@ -344,6 +346,7 @@
pluginInfosByChange.values().stream().filter(tpa -> tpa != null).count();
statistics.predicateCache = predicateCache.getStatistics();
statistics.preloader = definitions.preloader.getStatistics();
+ statistics.treeCaches = definitions.getStatistics();
}
return statistics;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
index 47b9e75..c7964ad 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
@@ -67,6 +67,10 @@
Node create(NodeList parent, Task definition) throws Exception;
}
+ public static class Statistics {
+ public Object definitionsPerSubSectionCache;
+ }
+
protected static final String TASK_DIR = "task";
protected final AccountResolver accountResolver;
@@ -76,9 +80,11 @@
protected final NodeList root = new NodeList();
protected final Provider<ChangeQueryBuilder> changeQueryBuilderProvider;
protected final Provider<ChangeQueryProcessor> changeQueryProcessorProvider;
- protected final Map<SubSectionKey, List<Task>> definitionsBySubSection = new HashMap<>();
+ protected final StatisticsMap<SubSectionKey, List<Task>> definitionsBySubSection =
+ new HitHashMapOfCollection<>();
protected ChangeData changeData;
+ protected Statistics statistics;
@Inject
public TaskTree(
@@ -547,6 +553,18 @@
return BranchNameKey.create(allUsers.get(), RefNames.refsUsers(acct));
}
+ public void initStatistics() {
+ statistics = new Statistics();
+ definitionsBySubSection.initStatistics();
+ }
+
+ public Statistics getStatistics() {
+ if (statistics != null) {
+ statistics.definitionsPerSubSectionCache = definitionsBySubSection.getStatistics();
+ }
+ return statistics;
+ }
+
protected static List<Node> refresh(List<Node> nodes)
throws ConfigInvalidException, StorageException {
for (Node node : nodes) {