Merge pull request #5666 from eatkins/cache-compiled-map

This commit is contained in:
Dale Wijnand 2020-07-07 18:21:04 +01:00 committed by GitHub
commit 30e4c02c9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 65 additions and 28 deletions

View File

@ -963,6 +963,7 @@ lazy val mainProj = (project in file("main"))
// the binary compatible version.
exclude[IncompatibleMethTypeProblem]("sbt.internal.server.NetworkChannel.this"),
exclude[IncompatibleSignatureProblem]("sbt.internal.DeprecatedContinuous.taskDefinitions"),
exclude[MissingClassProblem]("sbt.internal.SettingsGraph*")
)
)
.configure(

View File

@ -198,17 +198,24 @@ trait Init[ScopeType] {
compile(dMap)
}
@deprecated("Use makeWithCompiledMap", "1.4.0")
def make(init: Seq[Setting[_]])(
implicit delegates: ScopeType => Seq[ScopeType],
scopeLocal: ScopeLocal,
display: Show[ScopedKey[_]]
): Settings[ScopeType] = {
): Settings[ScopeType] = makeWithCompiledMap(init)._2
def makeWithCompiledMap(init: Seq[Setting[_]])(
implicit delegates: ScopeType => Seq[ScopeType],
scopeLocal: ScopeLocal,
display: Show[ScopedKey[_]]
): (CompiledMap, Settings[ScopeType]) = {
val cMap = compiled(init)(delegates, scopeLocal, display)
// order the initializations. cyclic references are detected here.
val ordered: Seq[Compiled[_]] = sort(cMap)
// evaluation: apply the initializations.
try {
applyInits(ordered)
(cMap, applyInits(ordered))
} catch {
case rru: RuntimeUndefined =>
throw Uninitialized(cMap.keys.toSeq, delegates, rru.undefined, true)

View File

@ -64,7 +64,8 @@ case class SettingsUsage(val settingsExample: SettingsExample) {
// "compiles" and applies the settings.
// This can be split into multiple steps to access intermediate results if desired.
// The 'inspect' command operates on the output of 'compile', for example.
val applied: Settings[Scope] = make(mySettings)(delegates, scopeLocal, showFullKey)
val applied: Settings[Scope] =
makeWithCompiledMap(mySettings)(delegates, scopeLocal, showFullKey)._2
// Show results.
/* for(i <- 0 to 5; k <- Seq(a, b)) {

View File

@ -200,7 +200,7 @@ object SettingsTest extends Properties("settings") {
def evaluate(settings: Seq[Setting[_]]): Settings[Scope] =
try {
make(settings)(delegates, scopeLocal, showFullKey)
makeWithCompiledMap(settings)(delegates, scopeLocal, showFullKey)._2
} catch {
case e: Throwable => e.printStackTrace(); throw e
}

View File

@ -747,7 +747,7 @@ object Defaults extends BuildCommon {
cleanKeepGlobs ++= historyPath.value.map(_.toGlob).toVector,
clean := Def.taskDyn(Clean.task(resolvedScoped.value.scope, full = true)).value,
consoleProject := consoleProjectTask.value,
transitiveDynamicInputs := SettingsGraph.task.value,
transitiveDynamicInputs := WatchTransitiveDependencies.task.value,
) ++ sbt.internal.DeprecatedContinuous.taskDefinitions
def generate(generators: SettingKey[Seq[Task[Seq[File]]]]): Initialize[Task[Seq[File]]] =

View File

@ -32,7 +32,19 @@ final class BuildStructure(
val streams: State => Streams,
val delegates: Scope => Seq[Scope],
val scopeLocal: ScopeLocal,
private[sbt] val compiledMap: Map[ScopedKey[_], Def.Compiled[_]],
) {
@deprecated("Used the variant that takes a compiledMap", "1.4.0")
def this(
units: Map[URI, LoadedBuildUnit],
root: URI,
settings: Seq[Setting[_]],
data: Settings[Scope],
index: StructureIndex,
streams: State => Streams,
delegates: Scope => Seq[Scope],
scopeLocal: ScopeLocal,
) = this(units, root, settings, data, index, streams, delegates, scopeLocal, Map.empty)
val extra: BuildUtil[ResolvedProject] = BuildUtil(root, units, index.keyIndex, data)

View File

@ -170,9 +170,9 @@ private[sbt] object Continuous extends DeprecatedContinuous {
// Extract all of the globs that we will monitor during the continuous build.
val inputs = {
val configs = scopedKey.get(internalDependencyConfigurations).getOrElse(Nil)
val args =
new SettingsGraph.Arguments(scopedKey, extracted, compiledMap, logger, configs, state)
SettingsGraph.transitiveDynamicInputs(args)
import WatchTransitiveDependencies.{ Arguments => DArguments }
val args = new DArguments(scopedKey, extracted, compiledMap, logger, configs, state)
WatchTransitiveDependencies.transitiveDynamicInputs(args)
}
val repository = getRepository(state)
@ -240,7 +240,7 @@ private[sbt] object Continuous extends DeprecatedContinuous {
dynamicInputs: mutable.Set[DynamicInput],
)(implicit extracted: Extracted, logger: Logger): Seq[Config] = {
val commandKeys = commands.map(parseCommand(_, state))
val compiledMap = SettingsGraph.compile(extracted.structure)
val compiledMap = WatchTransitiveDependencies.compile(extracted.structure)
commandKeys.flatMap(_.map(getConfig(state, _, compiledMap, dynamicInputs)))
}

View File

@ -117,9 +117,7 @@ object LintUnused {
val extracted = Project.extract(state)
val structure = extracted.structure
val display = Def.showShortKey(None) // extracted.showKey
val actual = true
val comp =
Def.compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal, display)
val comp = structure.compiledMap
val cMap = Def.flattenLocals(comp)
val used: Set[ScopedKey[_]] = cMap.values.flatMap(_.dependencies).toSet
val unused: Seq[ScopedKey[_]] = cMap.keys.filter(!used.contains(_)).toSeq

View File

@ -251,12 +251,16 @@ private[sbt] object Load {
val delegates = timed("Load.apply: config.delegates", log) {
config.delegates(loaded)
}
val data = timed("Load.apply: Def.make(settings)...", log) {
val (cMap, data) = timed("Load.apply: Def.make(settings)...", log) {
// When settings.size is 100000, Def.make takes around 10s.
if (settings.size > 10000) {
log.info(s"resolving key references (${settings.size} settings) ...")
}
Def.make(settings)(delegates, config.scopeLocal, Project.showLoadingKey(loaded))
Def.makeWithCompiledMap(settings)(
delegates,
config.scopeLocal,
Project.showLoadingKey(loaded)
)
}
Project.checkTargets(data) foreach sys.error
val index = timed("Load.apply: structureIndex", log) {
@ -271,7 +275,8 @@ private[sbt] object Load {
index,
streams,
delegates,
config.scopeLocal
config.scopeLocal,
cMap
)
(rootEval, bs)
}
@ -338,7 +343,8 @@ private[sbt] object Load {
implicit display: Show[ScopedKey[_]]
): BuildStructure = {
val transformed = finalTransforms(newSettings)
val newData = Def.make(transformed)(structure.delegates, structure.scopeLocal, display)
val (cMap, newData) =
Def.makeWithCompiledMap(transformed)(structure.delegates, structure.scopeLocal, display)
def extra(index: KeyIndex) = BuildUtil(structure.root, structure.units, index, newData)
val newIndex = structureIndex(newData, transformed, extra, structure.units)
val newStreams = mkStreams(structure.units, structure.root, newData)
@ -350,7 +356,8 @@ private[sbt] object Load {
index = newIndex,
streams = newStreams,
delegates = structure.delegates,
scopeLocal = structure.scopeLocal
scopeLocal = structure.scopeLocal,
compiledMap = cMap,
)
}

View File

@ -21,7 +21,7 @@ import sbt.nio.file.Glob
import scala.annotation.tailrec
private[sbt] object SettingsGraph {
private[sbt] object WatchTransitiveDependencies {
private implicit class SourceOps(val source: Source) {
def toGlob: Glob = {
val filter = source.includeFilter -- source.excludeFilter
@ -41,8 +41,7 @@ private[sbt] object SettingsGraph {
f(extracted, compile(extracted.structure))
}
private[sbt] def compile(structure: BuildStructure): CompiledMap =
compiled(structure.settings)(structure.delegates, structure.scopeLocal, (_: ScopedKey[_]) => "")
private[sbt] def compile(structure: BuildStructure): CompiledMap = structure.compiledMap
private[sbt] final class Arguments(
val scopedKey: ScopedKey[_],
val extracted: Extracted,

View File

@ -15,7 +15,7 @@ import sbt.Keys._
import sbt.internal.Clean.ToSeqPath
import sbt.internal.Continuous.FileStampRepository
import sbt.internal.util.AttributeKey
import sbt.internal.{ Clean, Continuous, DynamicInput, SettingsGraph }
import sbt.internal.{ Clean, Continuous, DynamicInput, WatchTransitiveDependencies }
import sbt.nio.FileStamp.Formats._
import sbt.nio.FileStamper.{ Hash, LastModified }
import sbt.nio.Keys._
@ -108,7 +108,8 @@ private[sbt] object Settings {
case transitiveDynamicInputs.key =>
scopedKey.scope.task.toOption.toSeq.map { key =>
val updatedKey = Def.ScopedKey(scopedKey.scope.copy(task = Zero), key)
transitiveDynamicInputs in scopedKey.scope := SettingsGraph.task(updatedKey).value
transitiveDynamicInputs in scopedKey.scope :=
WatchTransitiveDependencies.task(updatedKey).value
}
case dynamicDependency.key => (dynamicDependency in scopedKey.scope := { () }) :: Nil
case transitiveClasspathDependency.key =>

View File

@ -102,7 +102,8 @@ object FakeState {
val delegates: (Scope) => Seq[Scope] = _ => Nil
val scopeLocal: Def.ScopeLocal = _ => Nil
val data: Settings[Scope] = Def.make(settings)(delegates, scopeLocal, Def.showFullKey)
val (cMap, data: Settings[Scope]) =
Def.makeWithCompiledMap(settings)(delegates, scopeLocal, Def.showFullKey)
val extra: KeyIndex => BuildUtil[_] = (keyIndex) =>
BuildUtil(base.toURI, Map.empty, keyIndex, data)
val structureIndex: StructureIndex =
@ -140,7 +141,8 @@ object FakeState {
structureIndex,
streams,
delegates,
scopeLocal
scopeLocal,
cMap,
)
val attributes = AttributeMap.empty ++ AttributeMap(

View File

@ -241,7 +241,7 @@ abstract class TestBuild {
throw e
}
}
val data = Def.make(settings)(env.delegates, const(Nil), display)
val data = Def.makeWithCompiledMap(settings)(env.delegates, const(Nil), display)._2
val keys = data.allKeys((s, key) => ScopedKey(s, key))
val keyMap = keys.map(k => (k.key.label, k.key)).toMap[String, AttributeKey[_]]
val projectsMap = env.builds.map(b => (b.uri, b.projects.map(_.id).toSet)).toMap

View File

@ -18,7 +18,6 @@ import scala.collection.mutable
import xsbti.{ Logger => _, _ }
import sbt.io.IO
import sbt.internal.util._
import sbt.internal.BuildStreams.{ Streams => _, _ }
import sbt.internal.Load._
import sbt.util._
@ -171,14 +170,24 @@ object SettingQueryTest extends org.specs2.mutable.Specification {
val scopeLocal: ScopeLocal = EvaluateTask.injectStreams
val display: Show[ScopedKey[_]] = Project showLoadingKey loadedBuild
val data: Settings[Scope] = Def.make(settings)(delegates, scopeLocal, display)
val (cMap, data) = Def.makeWithCompiledMap(settings)(delegates, scopeLocal, display)
val extra: KeyIndex => BuildUtil[_] = index => BuildUtil(baseUri, units, index, data)
val index: StructureIndex = structureIndex(data, settings, extra, units)
val streams: State => Streams = mkStreams(units, baseUri, data)
val structure: BuildStructure =
new BuildStructure(units, baseUri, settings, data, index, streams, delegates, scopeLocal)
new BuildStructure(
units,
baseUri,
settings,
data,
index,
streams,
delegates,
scopeLocal,
cMap
)
structure
}