From c9dc0416433635948b26ac1975ef2f119e36ef16 Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Mon, 27 Jul 2020 15:33:51 -0700 Subject: [PATCH 1/2] Don't use managedCache for library stamps Using the managedCached introduced an unintended performance regression because it ensured that we always computed the hash of each jar on the dependency classpath. The backing ReadStamps only computes the stamp if the timestamp of the jar has changed. --- main/src/main/scala/sbt/Defaults.scala | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index b50211a37..63f21e78c 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -231,13 +231,7 @@ object Defaults extends BuildCommon { def getAllSourceStamps() : java.util.Map[xsbti.VirtualFileRef, xsbti.compile.analysis.Stamp] = new java.util.HashMap[xsbti.VirtualFileRef, xsbti.compile.analysis.Stamp] - def library(fr: xsbti.VirtualFileRef): xsbti.compile.analysis.Stamp = { - val path = converter.toPath(fr) - managedCache - .getOrElseUpdate(path, sbt.nio.FileStamper.Hash) - .map(_.stamp) - .getOrElse(backing.library(fr)) - } + def library(fr: xsbti.VirtualFileRef): xsbti.compile.analysis.Stamp = backing.library(fr) def product(fr: xsbti.VirtualFileRef): xsbti.compile.analysis.Stamp = backing.product(fr) def source(fr: xsbti.VirtualFile): xsbti.compile.analysis.Stamp = { val path = converter.toPath(fr) From 7ba5fd79f8857b87bd86736cdeefbc04d97e3350 Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Fri, 24 Jul 2020 17:02:27 -0700 Subject: [PATCH 2/2] Use time wrapped stamper for dependency classpath It is expensive to compute the the hash of every jar on the classpath so we can try to avoid that by using the timeWrappedStamper which only computes the hash if the last modified time has changed. --- main/src/main/scala/sbt/Defaults.scala | 9 ++++++--- main/src/main/scala/sbt/nio/FileStamp.scala | 7 ++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 63f21e78c..487ee7958 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -74,6 +74,7 @@ import sbt.librarymanagement.CrossVersion.{ binarySbtVersion, binaryScalaVersion import sbt.librarymanagement._ import sbt.librarymanagement.ivy._ import sbt.librarymanagement.syntax._ +import sbt.nio.FileStamp import sbt.nio.Keys._ import sbt.nio.file.syntax._ import sbt.nio.file.{ FileTreeView, Glob, RecursiveGlob } @@ -2215,9 +2216,11 @@ object Classpaths { ).map(exportClasspath) ++ Seq( dependencyClasspathFiles := data(dependencyClasspath.value).map(_.toPath), dependencyClasspathFiles / outputFileStamps := { - val cache = managedFileStampCache.value - val stamper = (managedSourcePaths / outputFileStamper).value - dependencyClasspathFiles.value.flatMap(p => cache.getOrElseUpdate(p, stamper).map(p -> _)) + val stamper = timeWrappedStamper.value + val converter = fileConverter.value + dependencyClasspathFiles.value.flatMap( + p => FileStamp(stamper.library(converter.toVirtualFile(p))).map(p -> _) + ) } ) diff --git a/main/src/main/scala/sbt/nio/FileStamp.scala b/main/src/main/scala/sbt/nio/FileStamp.scala index 1de4503ad..1a892373e 100644 --- a/main/src/main/scala/sbt/nio/FileStamp.scala +++ b/main/src/main/scala/sbt/nio/FileStamp.scala @@ -11,7 +11,7 @@ import java.io.{ File, IOException } import java.nio.file.{ Path, Paths } import java.util.concurrent.ConcurrentHashMap -import sbt.internal.inc.{ EmptyStamp, Stamper, LastModified => IncLastModified } +import sbt.internal.inc.{ EmptyStamp, Stamper, Hash => IncHash, LastModified => IncLastModified } import sbt.io.IO import sbt.nio.file.FileAttributes import sjsonnew.{ Builder, JsonFormat, Unbuilder, deserializationError } @@ -65,6 +65,11 @@ object FileStamp { case FileStamper.Hash => hash(path) case FileStamper.LastModified => lastModified(path) } + private[sbt] def apply(stamp: XStamp): Option[FileStamp] = stamp match { + case lm: IncLastModified => Some(new LastModified(lm.value)) + case s: IncHash => Some(fromZincStamp(s)) + case _ => None + } private[sbt] def apply(path: Path, fileAttributes: FileAttributes): Option[FileStamp] = try { if (fileAttributes.isDirectory) lastModified(path)