LUCENE-9793: Add task time aggregation utility (enabled with -Ptask.times=true).
diff --git a/build.gradle b/build.gradle
index 25086fd..d03721b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -131,6 +131,7 @@
apply from: file('gradle/ide/eclipse.gradle')
// Validation tasks
+apply from: file('gradle/validation/measure-task-times.gradle')
apply from: file('gradle/validation/error-prone.gradle')
apply from: file('gradle/validation/precommit.gradle')
apply from: file('gradle/validation/forbidden-apis.gradle')
diff --git a/gradle/validation/measure-task-times.gradle b/gradle/validation/measure-task-times.gradle
new file mode 100644
index 0000000..c495d8d
--- /dev/null
+++ b/gradle/validation/measure-task-times.gradle
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+import java.util.concurrent.ConcurrentHashMap
+import java.util.stream.Collectors
+
+// Measure aggregate wall time of each task execution time (summed up across
+// all projects).
+
+if (propertyOrDefault("task.times", null) != null) {
+ gradle.taskGraph.whenReady { TaskExecutionGraph graph ->
+ def taskTimes = new ConcurrentHashMap<String, Long>()
+ def measured = graph.allTasks.findAll { task -> true }
+
+ graph.addTaskExecutionListener(new TaskExecutionListener() {
+ @Override
+ void beforeExecute(Task task) {
+ def start = System.currentTimeMillis()
+ if (measured.contains(task)) {
+ taskTimes.put(task.path, start)
+ }
+ }
+
+ @Override
+ void afterExecute(Task task, TaskState taskState) {
+ def stop = System.currentTimeMillis()
+ if (measured.contains(task)) {
+ if (taskState.didWork) {
+ taskTimes.compute(task.path, { k, v -> stop - v })
+ } else {
+ taskTimes.remove(task.path)
+ }
+ }
+ }
+ })
+
+ // After the build is finished, check the test count.
+ gradle.buildFinished {
+ // Compute aggregate times of all task execution times.
+ def aggregates = taskTimes.entrySet().stream()
+ .collect(Collectors.groupingBy({e -> e.key.replaceAll(".*:", "")}))
+ .entrySet().stream()
+ .collect(Collectors.toMap(
+ {e -> e.key },
+ {e -> e.value.stream().mapToLong({ entry -> entry.value }).sum() }
+ ))
+
+ logger.lifecycle("Aggregate task times (possibly running in parallel!):")
+ aggregates.entrySet().stream()
+ .sorted({a, b -> Long.compare(b.value, a.value) })
+ .forEach {v ->
+ logger.lifecycle(String.format(Locale.ROOT, " %6.2f sec. %s", v.value / 1000.0, v.key))
+ }
+ }
+ }
+}