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) {