Skip to content

Commit 8823120

Browse files
committed
Cache standard library sources during compilation tests
1 parent f539802 commit 8823120

File tree

4 files changed

+70
-8
lines changed

4 files changed

+70
-8
lines changed

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

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

2222
/** Statistics about a cache */
23-
final class CacheStats(total: Long, misses: Long, uncached: Long):
23+
final case class CacheStats(total: Long, misses: Long, uncached: Long):
2424
val hits: Long = total - misses - uncached
2525

2626
override def toString: String =
@@ -37,6 +37,9 @@ object Caches:
3737
def stats(): CacheStats =
3838
CacheStats(total, misses = 0, uncached = total)
3939

40+
/** Default value for stamp function that indicates no stamping. */
41+
private def noStamp[K](key: K): Option[Unit] = Some(())
42+
4043
/** A thread-unsafe cache implementation based on a mutable [[Map]].
4144
*
4245
* Entries are not evicted.
@@ -47,7 +50,7 @@ object Caches:
4750
* `Some(stamp)`, the stamp is used to validate cached entries: cache
4851
* values are only reused if the stamp matches the cached stamp.
4952
*/
50-
final class MapCache[K, S, V](getStamp: K => Option[S]) extends Cache[K, V]:
53+
final class MapCache[K, S, V](getStamp: K => Option[S] = noStamp) extends Cache[K, V]:
5154
private val map = Map.empty[K, (S, V)]
5255
private var total = 0L
5356
private var misses = 0L
@@ -76,7 +79,7 @@ object Caches:
7679
*
7780
* Entries are not evicted.
7881
*/
79-
final class SynchronizedMapCache[K, S, V](getStamp: K => Option[S]) extends Cache[K, V]:
82+
final class SynchronizedMapCache[K, S, V](getStamp: K => Option[S] = noStamp) extends Cache[K, V]:
8083
private val map = ConcurrentHashMap[K, (S, V)]()
8184
private val total = LongAdder()
8285
private val misses = LongAdder()
@@ -146,4 +149,31 @@ object Caches:
146149
override def toString: String =
147150
s"FileBasedCache(${underlying.toString})"
148151

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

163+
def apply(key: K, value: => V): V =
164+
if shouldCache(key) then
165+
underlying(key, value)
166+
else
167+
uncached.increment()
168+
value
169+
170+
def stats(): CacheStats =
171+
val baseStats = underlying.stats()
172+
CacheStats(
173+
total = baseStats.total + uncached.longValue(),
174+
misses = baseStats.misses,
175+
uncached = baseStats.uncached + uncached.longValue()
176+
)
177+
178+
override def toString: String =
179+
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)