Skip to content

Commit eb88acd

Browse files
committed
Cache TASTy files content
1 parent 320e5ea commit eb88acd

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

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

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,10 +471,44 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
471471
classfileParser.run()
472472
}
473473

474+
object TastyLoader:
475+
476+
/** A cache of tasty bytes read from AbstractFiles to avoid reading and
477+
* decompressing the same tasty file over multiple compiler runs.
478+
*/
479+
private val tastyBytesCache = collection.mutable.WeakHashMap[AbstractFile, (Array[Byte], Long)]()
480+
481+
/** Maximum number of files to cache tasty bytes for.
482+
*
483+
* Heuristic: cache entries up to 10% of max memory, assuming an average
484+
* tasty file size of 10 KB (in the standard library, there are currently 936
485+
* tasty files totalling ~6.9 MB, which is ~7.4 KB per (uncompressed) tasty
486+
* file). For 1 GB max memory, this gives a cache size of ~10_000 entries,
487+
* which should be more than enough in practice.
488+
*
489+
* This limit would probably only be reached when running many consecutive
490+
* compilations in the same JVM (e.g. in a build server).
491+
*/
492+
private val maxTastyBytesCacheSize = Runtime.getRuntime.maxMemory() / 10 / 10_000
493+
494+
/** Get the bytes of the given tasty file, using the cache if possible. */
495+
def getTastyBytes(tastyFile: AbstractFile): Array[Byte] =
496+
tastyBytesCache.synchronized:
497+
val modifiedTime = tastyFile.lastModified
498+
tastyBytesCache.get(tastyFile) match
499+
case Some((bytes, time)) if time == modifiedTime =>
500+
bytes
501+
case _ =>
502+
val bytes = tastyFile.toByteArray
503+
if tastyBytesCache.size >= maxTastyBytesCacheSize then
504+
tastyBytesCache.clear()
505+
tastyBytesCache.put(tastyFile, (bytes, modifiedTime))
506+
bytes
507+
474508
class TastyLoader(val tastyFile: AbstractFile) extends SymbolLoader {
475509
val isBestEffortTasty = tastyFile.hasBetastyExtension
476510

477-
lazy val tastyBytes = tastyFile.toByteArray
511+
private def tastyBytes = TastyLoader.getTastyBytes(tastyFile)
478512

479513
private lazy val unpickler: tasty.DottyUnpickler =
480514
handleUnpicklingExceptions:

0 commit comments

Comments
 (0)