From 0929cf689403b0702f8921540b335aaf424ed630 Mon Sep 17 00:00:00 2001 From: friendseeker <66892505+Friendseeker@users.noreply.github.com> Date: Tue, 17 Sep 2024 00:16:27 -0700 Subject: [PATCH 1/3] early return in transitive invalidation if possible --- .../sbt/internal/inc/IncrementalCommon.scala | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalCommon.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalCommon.scala index 492b0e63f..1548fb3cf 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalCommon.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalCommon.scala @@ -464,16 +464,10 @@ private[inc] abstract class IncrementalCommon( val dependsOnClass = findClassDependencies(_, relations) val firstClassInvalidation: Set[String] = { val invalidated = - if (invalidateTransitively) { - // Invalidate by brute force (normally happens when we've done more than 3 incremental runs) - IncrementalCommon.transitiveDeps(initial, log)(dependsOnClass) - } else { - changes.apiChanges.flatMap(invalidateClassesInternally(relations, _, isScalaClass)).toSet - } - val included = includeTransitiveInitialInvalidations(initial, invalidated, dependsOnClass) - log.debug("Final step, transitive dependencies:\n\t" + included) - included + changes.apiChanges.flatMap(invalidateClassesInternally(relations, _, isScalaClass)).toSet + includeTransitiveInitialInvalidations(initial, invalidated, dependsOnClass) } + log.debug("Final step, transitive dependencies:\n\t" + firstClassInvalidation) // Invalidate classes linked with a class file that is produced by more than one source file val secondClassInvalidation = IncrementalCommon.invalidateNamesProducingSameClassFile(relations) @@ -506,7 +500,13 @@ private[inc] abstract class IncrementalCommon( Set.empty } else { if (invalidateTransitively) { - newInvalidations ++ recompiledClasses + val firstClassTransitiveInvalidation = includeTransitiveInitialInvalidations( + initial, + IncrementalCommon.transitiveDeps(initial, log)(dependsOnClass), + dependsOnClass + ) + log.debug("Invalidate by brute force:\n\t" + firstClassTransitiveInvalidation) + firstClassTransitiveInvalidation ++ secondClassInvalidation ++ thirdClassInvalidation } else { firstClassInvalidation ++ secondClassInvalidation ++ thirdClassInvalidation } From 39aa5135d83b9457bdaafd7daac989a03880648b Mon Sep 17 00:00:00 2001 From: friendseeker <66892505+Friendseeker@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:32:49 -0700 Subject: [PATCH 2/3] Add back Carston's transitive invalidation logic Probably not needed anymore but better safe than sorry --- .../src/main/scala/sbt/internal/inc/IncrementalCommon.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalCommon.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalCommon.scala index 1548fb3cf..4bdef942d 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalCommon.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalCommon.scala @@ -506,7 +506,7 @@ private[inc] abstract class IncrementalCommon( dependsOnClass ) log.debug("Invalidate by brute force:\n\t" + firstClassTransitiveInvalidation) - firstClassTransitiveInvalidation ++ secondClassInvalidation ++ thirdClassInvalidation + firstClassTransitiveInvalidation ++ secondClassInvalidation ++ thirdClassInvalidation ++ recompiledClasses } else { firstClassInvalidation ++ secondClassInvalidation ++ thirdClassInvalidation } From 34aa51af3c10e4b0b0dbc7325e4dda503ce5048b Mon Sep 17 00:00:00 2001 From: friendseeker <66892505+Friendseeker@users.noreply.github.com> Date: Sun, 22 Sep 2024 20:54:45 -0700 Subject: [PATCH 3/3] Add unit test to demonstrate the 1 cycle saving --- .../source-dependencies/transitive-early-stopping/A.scala | 3 +++ .../source-dependencies/transitive-early-stopping/B.scala | 3 +++ .../source-dependencies/transitive-early-stopping/C.scala | 4 ++++ .../source-dependencies/transitive-early-stopping/D.scala | 3 +++ .../transitive-early-stopping/changes/A.scala | 3 +++ .../source-dependencies/transitive-early-stopping/test | 5 +++++ 6 files changed, 21 insertions(+) create mode 100644 zinc/src/sbt-test/source-dependencies/transitive-early-stopping/A.scala create mode 100644 zinc/src/sbt-test/source-dependencies/transitive-early-stopping/B.scala create mode 100644 zinc/src/sbt-test/source-dependencies/transitive-early-stopping/C.scala create mode 100644 zinc/src/sbt-test/source-dependencies/transitive-early-stopping/D.scala create mode 100644 zinc/src/sbt-test/source-dependencies/transitive-early-stopping/changes/A.scala create mode 100644 zinc/src/sbt-test/source-dependencies/transitive-early-stopping/test diff --git a/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/A.scala b/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/A.scala new file mode 100644 index 000000000..d26475934 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/A.scala @@ -0,0 +1,3 @@ +object A { + val a: Int = 0 +} \ No newline at end of file diff --git a/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/B.scala b/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/B.scala new file mode 100644 index 000000000..e2eb7968d --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/B.scala @@ -0,0 +1,3 @@ +object B { + val b = A.a +} \ No newline at end of file diff --git a/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/C.scala b/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/C.scala new file mode 100644 index 000000000..75b2d7c07 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/C.scala @@ -0,0 +1,4 @@ +object C { + val c1 = B.b + val c2: Int = 0; +} \ No newline at end of file diff --git a/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/D.scala b/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/D.scala new file mode 100644 index 000000000..497b75205 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/D.scala @@ -0,0 +1,3 @@ +object D { + val d: Int = C.c2 +} \ No newline at end of file diff --git a/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/changes/A.scala b/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/changes/A.scala new file mode 100644 index 000000000..822a53e8f --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/changes/A.scala @@ -0,0 +1,3 @@ +object A { + val a: String = "" +} \ No newline at end of file diff --git a/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/test b/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/test new file mode 100644 index 000000000..10867af1a --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/transitive-early-stopping/test @@ -0,0 +1,5 @@ +> compile + +$ copy-file changes/A.scala A.scala +> compile +> checkIterations 4 \ No newline at end of file