Skip to content

Commit 5b4ee6b

Browse files
committed
Cache standard library sources during compilation tests
1 parent 700b08c commit 5b4ee6b

File tree

4 files changed

+69
-8
lines changed

4 files changed

+69
-8
lines changed

compiler/src/dotty/tools/dotc/core/Caches.scala

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ object Caches:
2828
s"${this.getClass.getSimpleName}(stats() = ${stats()})"
2929

3030
/** Statistics about a cache */
31-
final class CacheStats(total: Long, misses: Long, uncached: Long):
31+
final case class CacheStats(total: Long, misses: Long, uncached: Long):
3232
val hits: Long = total - misses - uncached
3333

3434
override def toString: String =
@@ -45,11 +45,13 @@ object Caches:
4545
def stats(): CacheStats =
4646
CacheStats(total, misses = 0, uncached = total)
4747

48+
private def noStamp[K](key: K): Option[Unit] = Some(())
49+
4850
/** A thread-unsafe cache implementation based on a mutable [[Map]].
4951
*
5052
* Entries are not evicted.
5153
*/
52-
final class MapCache[K, S, V](getStamp: K => Option[S]) extends Cache[K, V]:
54+
final class MapCache[K, S, V](getStamp: K => Option[S] = noStamp) extends Cache[K, V]:
5355
private val map = Map.empty[K, (S, V)]
5456
private var total = 0L
5557
private var misses = 0L
@@ -78,7 +80,7 @@ object Caches:
7880
*
7981
* Entries are not evicted.
8082
*/
81-
final class SynchronizedMapCache[K, S, V](getStamp: K => Option[S]) extends Cache[K, V]:
83+
final class SynchronizedMapCache[K, S, V](getStamp: K => Option[S] = noStamp) extends Cache[K, V]:
8284
private val map = ConcurrentHashMap[K, (S, V)]()
8385
private val total = LongAdder()
8486
private val misses = LongAdder()
@@ -148,4 +150,31 @@ object Caches:
148150
override def toString: String =
149151
s"FileBasedCache(${underlying.toString})"
150152

153+
/** Filtering cache wrapper that only caches values whose key satisfies a
154+
* given predicate.
155+
*
156+
* @param underlying
157+
* Underlying cache
158+
* @param shouldCache
159+
* Should the value associated with the given key should be cached?
160+
*/
161+
final class FilteringCache[K, V](underlying: Cache[K, V], shouldCache: K => Boolean) extends Cache[K, V]:
162+
private val uncached = LongAdder()
151163

164+
def apply(key: K, value: => V): V =
165+
if shouldCache(key) then
166+
underlying(key, value)
167+
else
168+
uncached.increment()
169+
value
170+
171+
def stats(): CacheStats =
172+
val baseStats = underlying.stats()
173+
CacheStats(
174+
total = baseStats.total + uncached.longValue(),
175+
misses = baseStats.misses,
176+
uncached = baseStats.uncached + uncached.longValue()
177+
)
178+
179+
override def toString: String =
180+
s"FilteringCache(${underlying.toString}, uncached = ${uncached.longValue()})"
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package dotty.tools
2+
3+
import dotty.tools.dotc.core.Caches.{FilteringCache, SynchronizedMapCache}
4+
import dotty.tools.dotc.core.CacheStores.{CacheStore, DefaultCacheStore}
5+
import dotty.tools.io.AbstractFile
6+
7+
object TestCacheStore extends CacheStore:
8+
/** Use the default global classpath cache. */
9+
val classPaths = DefaultCacheStore.classPaths
10+
11+
private val stdLibDir = "library/src"
12+
13+
/** Cache files across runs, without invalidation. */
14+
val files = FilteringCache(SynchronizedMapCache(), _.startsWith((stdLibDir)))
15+
16+
/** Cache source files across runs, without invalidation.
17+
*
18+
* We use a [[SynchronizedMapCache]] and not a [[FileBasedCache]] here
19+
* because we assume that source files in `library/src` do not change during
20+
* a test run.
21+
*/
22+
val sources = FilteringCache(SynchronizedMapCache(), _.canonicalPath.startsWith(stdLibDir))

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import TestSources.sources
1919
import reporting.TestReporter
2020
import vulpix._
2121
import dotty.tools.dotc.config.ScalaSettings
22+
import dotty.tools.dotc.core.CacheStores.DefaultCacheStore
2223

2324
class CompilationTests {
2425
import ParallelTesting._
@@ -406,6 +407,7 @@ object CompilationTests extends ParallelTesting {
406407

407408
implicit val summaryReport: SummaryReporting = new SummaryReport
408409
@AfterClass def tearDown(): Unit = {
410+
println(s"Cache statistics: $TestCacheStore")
409411
super.cleanup()
410412
summaryReport.echoSummary()
411413
}

compiler/test/dotty/tools/vulpix/ParallelTesting.scala

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ trait ParallelTesting extends RunnerOrchestration:
6363

6464
protected def testPlatform: TestPlatform = TestPlatform.JVM
6565

66+
private def setupTestContext(initCtx: FreshContext): FreshContext =
67+
initCtx.setCacheStore(TestCacheStore)
68+
initCtx
69+
70+
private class TestDriver extends Driver:
71+
override protected def initCtx =
72+
setupTestContext(super.initCtx.fresh)
73+
6674
/** A test source whose files or directory of files is to be compiled
6775
* in a specific way defined by the `Test`
6876
*/
@@ -533,8 +541,8 @@ trait ParallelTesting extends RunnerOrchestration:
533541
val reporter = mkReporter
534542

535543
val driver =
536-
if (times == 1) new Driver
537-
else new Driver {
544+
if (times == 1) TestDriver()
545+
else new TestDriver() {
538546
private def ntimes(n: Int)(op: Int => Reporter): Reporter =
539547
(1 to n).foldLeft(emptyReporter) ((_, i) => op(i))
540548

@@ -686,7 +694,7 @@ trait ParallelTesting extends RunnerOrchestration:
686694
val classes = flattenFiles(targetDir).filter(isBestEffortTastyFile).map(_.toString)
687695
val flags = flags0 `and` "-from-tasty" `and` "-Ywith-best-effort-tasty"
688696
val reporter = mkReporter
689-
val driver = new Driver
697+
val driver = TestDriver()
690698

691699
driver.process(flags.all ++ classes, reporter = reporter)
692700

@@ -698,7 +706,7 @@ trait ParallelTesting extends RunnerOrchestration:
698706
.and("-Ywith-best-effort-tasty")
699707
.and("-d", targetDir.getPath)
700708
val reporter = mkReporter
701-
val driver = new Driver
709+
val driver = TestDriver()
702710

703711
val args = Array("-classpath", flags.defaultClassPath + JFile.pathSeparator + bestEffortDir.toString) ++ flags.options
704712

@@ -716,7 +724,7 @@ trait ParallelTesting extends RunnerOrchestration:
716724

717725
val reporter = mkReporter
718726

719-
val driver = new Driver
727+
val driver = TestDriver()
720728

721729
driver.process(flags.all ++ classes, reporter = reporter)
722730

0 commit comments

Comments
 (0)