From 3fc88179741f4b8d70c9ed03e70b9ee2a4b085fe Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Wed, 21 Aug 2019 21:16:39 -0700 Subject: [PATCH] Add parallelism to KeyIndex.aggregate I looked for serial bottlenecks in sbt project loading and discovered that KeyIndex.aggregate was relatively easily parallelizable. Before this time, it took about 1 second to run KeyIndex.aggregate in the akka project on my computer. After this change, it took 250ms. Given that I have 4 logical cores, the speedup is roughly linear. --- .../main/scala/sbt/internal/KeyIndex.scala | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/main/src/main/scala/sbt/internal/KeyIndex.scala b/main/src/main/scala/sbt/internal/KeyIndex.scala index 3e9071391..0031208dc 100644 --- a/main/src/main/scala/sbt/internal/KeyIndex.scala +++ b/main/src/main/scala/sbt/internal/KeyIndex.scala @@ -28,10 +28,26 @@ object KeyIndex { extra: BuildUtil[_], projects: Map[URI, Set[String]], configurations: Map[String, Seq[Configuration]] - ): ExtendableKeyIndex = - (base(projects, configurations) /: known) { (index, key) => - index.addAggregated(key, extra) + ): ExtendableKeyIndex = { + /* + * Used to be: + * (base(projects, configurations) /: known) { (index, key) => + * index.addAggregated(key, extra) + * } + * This was a significant serial bottleneck during project loading that we can work around by + * computing the aggregations in parallel and then bulk adding them to the index. + */ + val toAggregate = known.par.map { + case key if validID(key.key.label) => + Aggregation.aggregate(key, ScopeMask(), extra, reverse = true) + case _ => Nil } + (base(projects, configurations) /: toAggregate) { + case (index, Nil) => index + case (index, keys) => (index /: keys)(_ add _) + } + } + private[this] def base( projects: Map[URI, Set[String]], configurations: Map[String, Seq[Configuration]]