aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Martres <smarter@ubuntu.com>2017-04-14 02:23:59 +0200
committerGuillaume Martres <smarter@ubuntu.com>2017-04-14 02:50:04 +0200
commitd773a32c9731dd5b105ac718900f8217fa75bcb2 (patch)
tree590d781ef7f81663e3baff0df9920b8ac1e52c2b
parent9e45ad16d012e6a2ff3be411c2fe101b1c74b831 (diff)
downloaddotty-d773a32c9731dd5b105ac718900f8217fa75bcb2.zip
dotty-d773a32c9731dd5b105ac718900f8217fa75bcb2.tar.gz
dotty-d773a32c9731dd5b105ac718900f8217fa75bcb2.tar.bz2
Make warm compilation speed with sbt 2x faster
Previously, every call to `compile` in sbt with dotty took about the same time because we created a new ClassLoader everytime and thus thrased the JIT code cache, by reusing ClassLoaders we can make `compile` about 2x faster. You can reproduce this by running: > dotty-compiler-bootstrapped/compile This takes ~50 seconds on my machine. Then clean using: > ;dotty-compiler-bootstrapped/clean;dotty-compiler-update And run `dotty-compiler-bootstrapped/compile` again, this takes ~25 seconds for me. I get very similar timings from scalac (replacing `dotty-compiler-bootstrapped` by `dotty-compiler`).
-rw-r--r--sbt-bridge/src/xsbt/CompilerClassLoader.scala15
1 files changed, 14 insertions, 1 deletions
diff --git a/sbt-bridge/src/xsbt/CompilerClassLoader.scala b/sbt-bridge/src/xsbt/CompilerClassLoader.scala
index 3cb3f34..c0bdcb5 100644
--- a/sbt-bridge/src/xsbt/CompilerClassLoader.scala
+++ b/sbt-bridge/src/xsbt/CompilerClassLoader.scala
@@ -2,6 +2,8 @@ package xsbt
import java.net.{URL, URLClassLoader}
+import scala.collection.mutable
+
/** A classloader to run the compiler
*
* A CompilerClassLoader is constructed from a list of `urls` that need to be on
@@ -42,6 +44,14 @@ class CompilerClassLoader(urls: Array[URL], sbtLoader: ClassLoader)
}
object CompilerClassLoader {
+ /** Cache the result of `fixBridgeLoader`.
+ *
+ * Reusing ClassLoaders is important for warm performance since otherwise the
+ * JIT code cache for the compiler will be discarded between every call to
+ * the sbt `compile` task.
+ */
+ private[this] val fixedLoaderCache = new mutable.WeakHashMap[ClassLoader, ClassLoader]
+
/** Fix the compiler bridge ClassLoader
*
* Soundtrack: https://www.youtube.com/watch?v=imamcajBEJs
@@ -70,7 +80,10 @@ object CompilerClassLoader {
* @param bridgeLoader The classloader that sbt uses to load the compiler bridge
* @return A fixed classloader that works with dotty
*/
- def fixBridgeLoader(bridgeLoader: ClassLoader) = bridgeLoader match {
+ def fixBridgeLoader(bridgeLoader: ClassLoader): ClassLoader =
+ fixedLoaderCache.getOrElseUpdate(bridgeLoader, computeFixedLoader(bridgeLoader))
+
+ private[this] def computeFixedLoader(bridgeLoader: ClassLoader) = bridgeLoader match {
case bridgeLoader: URLClassLoader =>
val dualLoader = bridgeLoader.getParent
val dualLoaderClass = dualLoader.getClass