From 41e80159b37d8a07922fb90d516b9105f2f185b7 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Tue, 19 Jan 2010 03:15:07 +0000 Subject: Digging into why the repl is so slow, discovere... Digging into why the repl is so slow, discovered that fsc is once again never reusing compiler instances (but for a different reason than #1683.) Small changes break equality and the little troopers are so darn quiet about it. Steady state, hot fsc repl startup times before this patch: 0m1.747s 0m1.789s 0m1.842s 0m1.690s After this patch: 0m1.139s 0m1.148s 0m1.090s 0m1.091s No review. Could use a test case but I have trouble coaxing partest this far outside the box. --- src/compiler/scala/tools/ant/Scalac.scala | 2 +- src/compiler/scala/tools/nsc/CompileServer.scala | 113 +++++++++++---------- src/compiler/scala/tools/nsc/CompilerCommand.scala | 4 +- src/compiler/scala/tools/nsc/ScriptRunner.scala | 4 +- src/compiler/scala/tools/nsc/Settings.scala | 7 +- 5 files changed, 68 insertions(+), 62 deletions(-) diff --git a/src/compiler/scala/tools/ant/Scalac.scala b/src/compiler/scala/tools/ant/Scalac.scala index 8bd5444ee3..1b96a47420 100644 --- a/src/compiler/scala/tools/ant/Scalac.scala +++ b/src/compiler/scala/tools/ant/Scalac.scala @@ -616,7 +616,7 @@ class Scalac extends MatchingTask { val out = new PrintWriter(new BufferedWriter(new FileWriter(file))) try { - for (setting <- settings.allSettings ; arg <- setting.unparse) + for (setting <- settings.settingSet ; arg <- setting.unparse) out println escapeArgument(arg) for (file <- sourceFiles) out println file.getAbsolutePath diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala index 67276b861f..36af000937 100644 --- a/src/compiler/scala/tools/nsc/CompileServer.scala +++ b/src/compiler/scala/tools/nsc/CompileServer.scala @@ -82,63 +82,70 @@ class StandardCompileServer extends SocketServer val password = compileSocket getPassword port val guessedPassword = in.readLine() val input = in.readLine() - if ((input ne null) && password == guessedPassword) { - val args = input.split("\0",-1).toList - if (args contains "-shutdown") { - out.println("[Compile server exited]") - shutDown = true - return - } - if (args contains "-reset") { - out.println("[Compile server was reset]") - compiler = null - return - } - def error(msg: String) { - out.println(/*new Position*/ FakePos("fsc"), - msg + "\n fsc -help gives more information") - } - val command = newOfflineCompilerCommand(args, new Settings(error), error, false) - reporter = new ConsoleReporter(command.settings, in, out) { - // disable prompts, so that compile server cannot block - override def displayPrompt = () - } + if (input == null || password != guessedPassword) + return - if (command.shouldStopWithInfo) { - reporter.info(null, - command.getInfoMessage(newGlobal(command.settings, reporter)), true) - } else if (command.files.isEmpty) - reporter.info(null, command.usageMsg, true) - else { - try { - if ((compiler ne null) && settingsAreCompatible(command.settings, compiler.settings)) { - compiler.settings = command.settings - compiler.reporter = reporter - } else { - if (args contains "-verbose") - out.println("[Starting new compile server instance]") - compiler = newGlobal(command.settings, reporter) - } - val c = compiler - val run = new c.Run() - run compile command.files - } catch { - case ex @ FatalError(msg) => - if (command.settings.debug.value) - ex.printStackTrace(out); - reporter.error(null, "fatal error: " + msg) - compiler = null - case ex: Throwable => - ex.printStackTrace(out); - reporter.error(null, "fatal error (server aborted): " + ex.getMessage()) - shutDown = true - } - reporter.printSummary() - if (isMemoryFullEnough) - compiler = null + val args = input.split("\0", -1).toList + if (args contains "-shutdown") { + out.println("[Compile server exited]") + shutDown = true + return + } + if (args contains "-reset") { + out.println("[Compile server was reset]") + compiler = null + return + } + + def error(msg: String) { + out.println(FakePos("fsc"), msg + "\n fsc -help gives more information") + } + + val command = newOfflineCompilerCommand(args, new Settings(error), error, false) + + reporter = new ConsoleReporter(command.settings, in, out) { + // disable prompts, so that compile server cannot block + override def displayPrompt = () + } + + if (command.shouldStopWithInfo) + reporter.info(null, command.getInfoMessage(newGlobal(command.settings, reporter)), true) + else if (command.files.isEmpty) + reporter.info(null, command.usageMsg, true) + else { + try { + if (compiler != null && command.settings == compiler.settings) { + compiler.settings = command.settings + compiler.reporter = reporter + } + else { + if (args contains "-verbose") { + val reason = if (compiler == null) "compiler is null" else "settings not equal" + out.println("[Starting new compile server instance because %s]".format(reason)) } + compiler = newGlobal(command.settings, reporter) + } + val c = compiler + val run = new c.Run() + run compile command.files + } + catch { + case ex @ FatalError(msg) => + if (command.settings.debug.value) + ex.printStackTrace(out); + reporter.error(null, "fatal error: " + msg) + compiler = null + case ex: Throwable => + ex.printStackTrace(out); + reporter.error(null, "fatal error (server aborted): " + ex.getMessage()) + shutDown = true + } } + + reporter.printSummary() + if (isMemoryFullEnough) + compiler = null } /** A directory holding redirected output */ diff --git a/src/compiler/scala/tools/nsc/CompilerCommand.scala b/src/compiler/scala/tools/nsc/CompilerCommand.scala index 8465227133..75a3414d75 100644 --- a/src/compiler/scala/tools/nsc/CompilerCommand.scala +++ b/src/compiler/scala/tools/nsc/CompilerCommand.scala @@ -33,7 +33,7 @@ class CompilerCommand( val cmdName = "scalac" private val helpSyntaxColumnWidth: Int = - (settings.allSettings map (_.helpSyntax.length)) max + (settings.settingSet map (_.helpSyntax.length)) max private def format(s: String): String = { val buf = new StringBuilder(s) @@ -44,7 +44,7 @@ class CompilerCommand( /** Creates a help message for a subset of options based on cond */ def createUsageMsg(label: String, cond: (Setting) => Boolean): String = - settings.allSettings . + settings.settingSet . filter(cond) . map(s => format(s.helpSyntax) + " " + s.helpDescription) . mkString("Usage: %s \n%s options include:\n " . diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala index 3423f8f45f..f9d4d7983a 100644 --- a/src/compiler/scala/tools/nsc/ScriptRunner.scala +++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala @@ -204,8 +204,8 @@ object ScriptRunner } } - val compSettingNames = new Settings(error).allSettings map (_.name) - val compSettings = settings.allSettings filter (compSettingNames contains _.name) + val compSettingNames = new Settings(error).settingSet.toList map (_.name) + val compSettings = settings.settingSet.toList filter (compSettingNames contains _.name) val coreCompArgs = compSettings flatMap (_.unparse) val compArgs = coreCompArgs ::: List("-Xscript", scriptMain(settings), scriptFile) var compok = true diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala index 157bc2dc1f..4242d0df47 100644 --- a/src/compiler/scala/tools/nsc/Settings.scala +++ b/src/compiler/scala/tools/nsc/Settings.scala @@ -61,9 +61,9 @@ class Settings(errorFn: String => Unit) extends ScalacSettings { private def guessedScalaExtDirs: Option[String] = guess(List("lib"), _.isDirectory) - override def hashCode() = allSettings.hashCode + override def hashCode() = settingSet.hashCode override def equals(that: Any) = that match { - case s: Settings => this.allSettings == s.allSettings + case s: Settings => this.settingSet == s.settingSet case _ => false } @@ -75,7 +75,7 @@ class Settings(errorFn: String => Unit) extends ScalacSettings { case _ => "" == value } - for (setting <- allSettings ; (dep, value) <- setting.dependency) + for (setting <- settingSet ; (dep, value) <- setting.dependency) if (!setting.isDefault && !hasValue(dep, value)) { errorFn("incomplete option " + setting.name + " (requires " + dep.name + ")") return false @@ -811,7 +811,6 @@ trait ScalacSettings { /** A list of all settings */ protected var allsettings: Set[Setting] = TreeSet[Setting]() def settingSet: Set[Setting] = allsettings - def allSettings: List[Setting] = settingSet.toList /** Disable a setting */ def disable(s: Setting) = allsettings -= s -- cgit v1.2.3