mirror of https://github.com/sbt/sbt.git
Merge pull request #8364 from eed3si9n/wip/cache-analysis
[2.x] perf: Cache Zinc Analysis across compilations
This commit is contained in:
commit
7a96851176
|
|
@ -9,7 +9,10 @@
|
|||
package sbt
|
||||
package internal
|
||||
|
||||
import com.github.benmanes.caffeine.cache.{ Cache as CCache, Caffeine, Weigher }
|
||||
import java.io.File
|
||||
import java.nio.file.{ Files, NoSuchFileException }
|
||||
import java.nio.file.attribute.BasicFileAttributes
|
||||
import Keys.{ organization, thisProject, autoGeneratedProject, publish, publishLocal, skip }
|
||||
import Def.Setting
|
||||
// import sbt.ProjectExtra.apply
|
||||
|
|
@ -18,7 +21,7 @@ import sbt.internal.util.{ Attributed, StringAttributeMap }
|
|||
import sbt.internal.inc.{ FileAnalysisStore, ReflectUtilities }
|
||||
import sbt.util.CacheImplicits.given
|
||||
import xsbti.{ FileConverter, VirtualFileRef }
|
||||
import xsbti.compile.CompileAnalysis
|
||||
import xsbti.compile.{ AnalysisContents, CompileAnalysis }
|
||||
|
||||
trait BuildDef {
|
||||
def projectDefinitions(@deprecated("unused", "") baseDirectory: File): Seq[Project] = projects
|
||||
|
|
@ -87,6 +90,26 @@ private[sbt] object BuildDef:
|
|||
): Seq[xsbti.compile.CompileAnalysis] =
|
||||
in.flatMap(a => extractAnalysis(a.metadata, converter))
|
||||
|
||||
private[sbt] final val localAnalysisCacheByteSize = 100 * 1024L * 1024L
|
||||
private val weigher: Weigher[String, (Option[AnalysisContents], Long, Long)] = {
|
||||
case (_, (_, _, sizeBytes)) => sizeBytes.toInt
|
||||
}
|
||||
private val inMemoryAnalysisCache: CCache[String, (Option[AnalysisContents], Long, Long)] =
|
||||
Caffeine
|
||||
.newBuilder()
|
||||
.maximumWeight(localAnalysisCacheByteSize)
|
||||
.weigher(weigher)
|
||||
.build()
|
||||
private def getOrElseUpdate(ref: VirtualFileRef, lastModified: Long, sizeBytes: Long)(
|
||||
value: => Option[AnalysisContents]
|
||||
): Option[AnalysisContents] =
|
||||
Option(inMemoryAnalysisCache.getIfPresent(ref.id())) match
|
||||
case Some((v, mod, i)) if lastModified == mod && sizeBytes == i => v
|
||||
case _ =>
|
||||
val v = value
|
||||
inMemoryAnalysisCache.put(ref.id(), (v, lastModified, sizeBytes))
|
||||
v
|
||||
|
||||
private[sbt] def extractAnalysis(
|
||||
metadata: StringAttributeMap,
|
||||
converter: FileConverter
|
||||
|
|
@ -94,10 +117,21 @@ private[sbt] object BuildDef:
|
|||
import sbt.OptionSyntax.*
|
||||
def asBinary(file: File) = FileAnalysisStore.binary(file).get.asScala
|
||||
def asText(file: File) = FileAnalysisStore.text(file).get.asScala
|
||||
def fallback(file: File) = asBinary(file).orElse(asText(file))
|
||||
def getContents(ref: VirtualFileRef): Option[AnalysisContents] =
|
||||
val path = converter.toPath(ref)
|
||||
val file = path.toFile()
|
||||
try
|
||||
val attrs = Files.readAttributes(path, classOf[BasicFileAttributes])
|
||||
if attrs.isDirectory then fallback(file)
|
||||
else
|
||||
val lastModified = attrs.lastModifiedTime().toMillis()
|
||||
val sizeBytes = attrs.size()
|
||||
getOrElseUpdate(ref, lastModified, sizeBytes)(fallback(file))
|
||||
catch case _: NoSuchFileException => fallback(file)
|
||||
for
|
||||
ref <- metadata.get(Keys.analysis)
|
||||
file = converter.toPath(VirtualFileRef.of(ref)).toFile
|
||||
content <- asBinary(file).orElse(asText(file))
|
||||
content <- getContents(VirtualFileRef.of(ref))
|
||||
yield content.getAnalysis
|
||||
|
||||
end BuildDef
|
||||
|
|
|
|||
Loading…
Reference in New Issue