Add test for cache hits

This commit is contained in:
Eugene Yokota 2025-05-02 00:50:28 -04:00
parent 2fd08caeda
commit d10e5b6f48
8 changed files with 107 additions and 32 deletions

View File

@ -118,7 +118,7 @@ object Aggregation {
val transform = nodeView(s, str, roots, extra)
runTask(toRun, s, str, structure.index.triggers, config)(using transform)
val stop = System.currentTimeMillis
val cacheSummary = Def.cacheEventLog.summary
val cacheSummary = Def.cacheEventLog.summary.toString()
Complete(start, stop, result, cacheSummary, newS)
def runTasks[A1](

View File

@ -1,9 +1,10 @@
import sbt.internal.util.StringVirtualFile1
import sbt.internal.util.{ CacheEventSummary, StringVirtualFile1 }
import sjsonnew.BasicJsonProtocol.*
val pure1 = taskKey[Unit]("")
val map1 = taskKey[String]("")
val mapN1 = taskKey[Unit]("")
val checkMapN1 = taskKey[Unit]("")
Global / localCacheDirectory := baseDirectory.value / "diskcache"
@ -29,3 +30,11 @@ mapN1 := (Def.cachedTask {
Def.declareOutput(output)
()
}).value
checkMapN1 := {
val config = Def.cacheConfiguration.value
val prev = config.cacheEventLog.previous match
case s: CacheEventSummary.Data => s
case s => sys.error(s"empty event log")
assert(prev.hitCount == 2, s"prev.hitCount = ${prev.hitCount}")
}

View File

@ -16,3 +16,4 @@ $ exists target/out/b2.txt
$ exists target/out/a.txt
$ exists target/out/b1.txt
$ exists target/out/c.txt
> checkMapN1

View File

@ -0,0 +1,21 @@
import sbt.internal.util.CacheEventSummary
val check = taskKey[Unit]("")
Global / localCacheDirectory := baseDirectory.value / "diskcache"
scalaVersion := "2.13.16"
addCompilerPlugin(("org.typelevel" % "kind-projector" % "0.13.3").cross(CrossVersion.full))
check := {
val config = Def.cacheConfiguration.value
val prev = config.cacheEventLog.previous match
case s: CacheEventSummary.Data => s
case s => sys.error(s"empty event log")
assert(prev.hitCount == 1, s"prev.hitCount = ${prev.hitCount}")
}
lazy val foo = (project in file("foo"))
.settings(
name := "foo"
)

View File

@ -0,0 +1,5 @@
package example
class A {
def foo = 1
}

View File

@ -0,0 +1,4 @@
> foo/compile
> clean
> foo/compile
> check

View File

@ -13,8 +13,45 @@ end ActionCacheEvent
case class ActionCacheError(outputFiles: Seq[VirtualFileRef])
enum CacheEventSummary:
case Empty
case Data(
hits: Seq[(String, Long)],
hitCount: Long,
missCount: Long,
hitRate: Double,
onsiteCount: Option[Long],
errorCount: Option[Long]
)
override def toString(): String = this match
case Empty => ""
case Data(
hits,
hitCount,
missCount,
hitRate,
onsiteCount,
errorCount
) =>
val hitDescs = hits.map {
case (id, 1) => s"1 $id cache hit"
case (id, v) => s"$v $id cache hits"
}.sorted
val missDesc = onsiteCount.map:
case 1 => s"1 onsite task"
case _ => s"$missCount onsite tasks"
val errorDesc = errorCount.map:
case 1 => s"1 error"
case errors => s"$errors errors"
val descs = hitDescs ++ missDesc ++ errorDesc
val descsSummary = descs.mkString(", ")
val hitRateStr = (hitRate * 100.0).floor.toInt
s"cache $hitRateStr%, $descsSummary"
end CacheEventSummary
class CacheEventLog:
private val acEvents = TrieMap.empty[ActionCacheEvent, Long]
private val previousEvents = TrieMap.empty[ActionCacheEvent, Long]
def append(event: ActionCacheEvent): Unit =
acEvents.updateWith(event) {
@ -23,31 +60,29 @@ class CacheEventLog:
}
def clear(): Unit =
previousEvents.clear()
previousEvents ++= acEvents
acEvents.clear()
def summary: String =
if acEvents.isEmpty then ""
def summary: CacheEventSummary = toSummary(acEvents)
def previous: CacheEventSummary = toSummary(previousEvents)
def toSummary(events: TrieMap[ActionCacheEvent, Long]): CacheEventSummary =
if events.isEmpty then CacheEventSummary.Empty
else
val total = acEvents.values.sum
val hits = acEvents.view.collect { case (ActionCacheEvent.Found(id), v) => (id, v) }.toMap
val total = events.values.sum
val hits = events.view.collect { case (ActionCacheEvent.Found(id), v) => (id, v) }.toMap
val hitCount = hits.values.sum
val missCount = total - hitCount
val hitRate = (hitCount.toDouble / total.toDouble * 100.0).floor.toInt
val hitDescs = hits.toSeq.map {
case (id, 1) => s"1 $id cache hit"
case (id, v) => s"$v $id cache hits"
}.sorted
val missDesc = acEvents
.get(ActionCacheEvent.OnsiteTask)
.map:
case 1 => s"1 onsite task"
case _ => s"$missCount onsite tasks"
val errorDesc = acEvents
.get(ActionCacheEvent.Error)
.map:
case 1 => s"1 error"
case errors => s"$errors errors"
val descs = hitDescs ++ missDesc ++ errorDesc
val descsSummary = descs.mkString(", ")
s"cache $hitRate%, $descsSummary"
val hitRate = (hitCount.toDouble / total.toDouble)
val onsiteCount = events.get(ActionCacheEvent.OnsiteTask)
val errorCount = events.get(ActionCacheEvent.Error)
CacheEventSummary.Data(
hits.toSeq,
hitCount,
missCount,
hitRate,
onsiteCount,
errorCount
)
end CacheEventLog

View File

@ -7,14 +7,14 @@ object CacheEventLogTest extends BasicTestSuite:
test("summary of 0 events") {
val logger = CacheEventLog()
val expectedSummary = ""
assertEquals(logger.summary, expectedSummary)
assertEquals(logger.summary.toString(), expectedSummary)
}
test("summary of 1 disk event") {
val logger = CacheEventLog()
logger.append(ActionCacheEvent.Found("disk"))
val expectedSummary = "cache 100%, 1 disk cache hit"
assertEquals(logger.summary, expectedSummary)
assertEquals(logger.summary.toString(), expectedSummary)
}
test("summary of 2 disk events") {
@ -22,7 +22,7 @@ object CacheEventLogTest extends BasicTestSuite:
logger.append(ActionCacheEvent.Found("disk"))
logger.append(ActionCacheEvent.Found("disk"))
val expectedSummary = "cache 100%, 2 disk cache hits"
assertEquals(logger.summary, expectedSummary)
assertEquals(logger.summary.toString(), expectedSummary)
}
test("summary of 1 disk, 1 onsite task") {
@ -30,7 +30,7 @@ object CacheEventLogTest extends BasicTestSuite:
logger.append(ActionCacheEvent.Found("disk"))
logger.append(ActionCacheEvent.OnsiteTask)
val expectedSummary = "cache 50%, 1 disk cache hit, 1 onsite task"
assertEquals(logger.summary, expectedSummary)
assertEquals(logger.summary.toString(), expectedSummary)
}
test("summary of 1 disk, 1 onsite task, 1 error") {
@ -39,7 +39,7 @@ object CacheEventLogTest extends BasicTestSuite:
logger.append(ActionCacheEvent.OnsiteTask)
logger.append(ActionCacheEvent.Error)
val expectedSummary = "cache 33%, 1 disk cache hit, 1 onsite task, 1 error"
assertEquals(logger.summary, expectedSummary)
assertEquals(logger.summary.toString(), expectedSummary)
}
test("summary of 1 disk, 2 errors") {
@ -48,7 +48,7 @@ object CacheEventLogTest extends BasicTestSuite:
logger.append(ActionCacheEvent.Error)
logger.append(ActionCacheEvent.Error)
val expectedSummary = "cache 33%, 1 disk cache hit, 2 errors"
assertEquals(logger.summary, expectedSummary)
assertEquals(logger.summary.toString(), expectedSummary)
}
test("summary of 1 disk, 2 remote, 1 onsite task") {
@ -58,7 +58,7 @@ object CacheEventLogTest extends BasicTestSuite:
logger.append(ActionCacheEvent.Found("remote"))
logger.append(ActionCacheEvent.OnsiteTask)
val expectedSummary = "cache 75%, 1 disk cache hit, 2 remote cache hits, 1 onsite task"
assertEquals(logger.summary, expectedSummary)
assertEquals(logger.summary.toString(), expectedSummary)
}
test("summary of 1 disk event after clear") {
@ -67,6 +67,6 @@ object CacheEventLogTest extends BasicTestSuite:
logger.clear()
logger.append(ActionCacheEvent.Found("disk"))
val expectedSummary = "cache 100%, 1 disk cache hit"
assertEquals(logger.summary, expectedSummary)
assertEquals(logger.summary.toString(), expectedSummary)
}
end CacheEventLogTest