diff options
author | Paul Phillips <paulp@improving.org> | 2010-12-07 02:59:01 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-12-07 02:59:01 +0000 |
commit | fbe897d165bfbb8cda05e4b25f0f773288653f54 (patch) | |
tree | 4377600c688b4644721a6289c388100e24546fae | |
parent | a8db7a2da783b0752aad1a738b0e5600c303e97e (diff) | |
download | scala-fbe897d165bfbb8cda05e4b25f0f773288653f54.tar.gz scala-fbe897d165bfbb8cda05e4b25f0f773288653f54.tar.bz2 scala-fbe897d165bfbb8cda05e4b25f0f773288653f54.zip |
Tackling long standing issues with startup.
anyone can offer any reason why it's not (long past) time to do this I
can back the truck up. (But I will have a list of bourne shell scripts
for you to write.)
With this commit:
1) -J options are now passed to the underlying JVM, along with -D
options which already were. scala -Dfoo=bar and scala -J-Dfoo=bar are
identical (but -J can pass arbitrary arguments to the jvm: -J-verbose,
-J-Xmx4G, etc.)
2) Eliminated DefinesSetting. It was ill-conceived because setting
system properties must be done at JVM start to guarantee they will be
seen where appropriate: by the time scala is involved it's too late. The
starter script takes care of routing -D to the jvm, and no longer sends
them along to scala as well. Since we have a new system package you can
read any property in system.props, like this:
% scala -Dp1="hi" -Dp2="bye" -e 'println(system.props filterKeys
(_.length == 2))' Map(p2 -> bye, p1 -> hi)
3) After measuring that startup is a full second faster by putting
the scala jars on the bootclasspath, I gave us a standard way to
take advantage of this. It's not done by default, although we should
seriously consider it (I'm familiar with the issues that have arisen in
the past.) Reclaim your life, one startup second at a time.
The flag is --usebootcp, as below:
// Here's a way (in bash 4) to compare repl startup times each way while
true ; do time pscala -i <(echo "system exit 0") ; done |& grep real
while true ; do time pscala --usebootcp -i <(echo "system exit 0") ;
done |& grep real
Once again I find myself unable to nominate any plausible reviewer (if
there were anyone interested in this stuff, they'd be doing it instead
of me) so no review.
5 files changed, 34 insertions, 65 deletions
diff --git a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl index ceb6ec5ad4..25616c171a 100644 --- a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl +++ b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # ############################################################################## # Copyright 2002-2010, LAMP/EPFL @@ -63,21 +63,44 @@ fi # Reminder: substitution ${JAVA_OPTS:=-Xmx256M -Xms16M} DO NOT work on Solaris [ -n "$JAVA_OPTS" ] || JAVA_OPTS="@javaflags@" -# break out -D options and add them to JAVA_OPTS as well so they reach the -# underlying JVM in time to do some good. -for i -do - case "$i" in +# break out -D and -J options and add them to JAVA_OPTS as well +# so they reach the underlying JVM in time to do some good. The +# -D options will be available as system properties. +declare -a java_args +declare -a scala_args +CPSWITCH="-cp \"$TOOL_CLASSPATH\"" + +while [ $# -gt 0 ]; do + case "$1" in -D*) - JAVA_OPTS="$JAVA_OPTS $i" ;; + java_args=("${java_args[@@]}" "$1") + shift + ;; + -J*) + java_args=("${java_args[@@]}" "${1:2}") + shift + ;; + --usebootcp) + CPSWITCH="-Xbootclasspath/a:\"$TOOL_CLASSPATH\"" + shift + ;; *) + scala_args=("${scala_args[@@]}" "$1") + shift ;; esac -done - +done +# reset "$@@" to the remaining args +set -- "${scala_args[@@]}" if [ -z "$JAVACMD" -a -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then JAVACMD="$JAVA_HOME/bin/java" fi -exec "${JAVACMD:=java}" $JAVA_OPTS -cp "$TOOL_CLASSPATH" -Dscala.usejavacp=true -Dscala.home="$SCALA_HOME" -Denv.emacs="$EMACS" @properties@ @class@ @toolflags@ "$@@" +exec "${JAVACMD:=java}" \ + "${java_args[@@]}" \ + $CPSWITCH \ + -Dscala.usejavacp=true \ + -Dscala.home="$SCALA_HOME" \ + -Denv.emacs="$EMACS" \ + @properties@ @class@ @toolflags@ "$@@" diff --git a/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala index c4e2e93235..3131c78bd0 100644 --- a/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala @@ -11,7 +11,6 @@ trait AbsScalaSettings { type BooleanSetting <: AbsSetting { type T = Boolean } type ChoiceSetting <: AbsSetting { type T = String } - type DefinesSetting <: AbsSetting { type T = List[(String, String)] } type IntSetting <: AbsSetting { type T = Int } type MultiStringSetting <: AbsSetting { type T = List[String] } type PathSetting <: AbsSetting { type T = String } @@ -23,7 +22,6 @@ trait AbsScalaSettings { def BooleanSetting(name: String, descr: String): BooleanSetting def ChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: String): ChoiceSetting - def DefinesSetting(): DefinesSetting def IntSetting(name: String, descr: String, default: Int, range: Option[(Int, Int)], parser: String => Option[Int]): IntSetting def MultiStringSetting(name: String, helpArg: String, descr: String): MultiStringSetting def OutputSetting(outputDirs: OutputDirs, default: String): OutputSetting diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala index e4366b8758..a6499f0ca2 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -107,16 +107,6 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal // any non-Nil return value means failure and we return s unmodified tryToSetIfExists(p, args split "," toList, (s: Setting) => s.tryToSetColon _) } - // if arg is of form -Dfoo=bar or -Dfoo (name = "-D") - def isPropertyArg(s: String) = lookupSetting(s take 2) match { - case Some(x: DefinesSetting) => true - case _ => false - } - def parsePropertyArg(s: String): Option[List[String]] = { - val (p, args) = (s take 2, s drop 2) - - tryToSetIfExists(p, List(args), (s: Setting) => s.tryToSetProperty _) - } // if arg is of form -Xfoo or -Xfoo bar (name = "-Xfoo") def parseNormalArg(p: String, args: List[String]): Option[List[String]] = @@ -181,11 +171,7 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal // // Internally we use Option[List[String]] to discover error, // but the outside expects our arguments back unchanged on failure - if (isPropertyArg(arg)) parsePropertyArg(arg) match { - case Some(_) => rest - case None => args - } - else if (arg contains ":") parseColonArg(arg) match { + if (arg contains ":") parseColonArg(arg) match { case Some(_) => rest case None => args } @@ -234,7 +220,6 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal def BooleanSetting(name: String, descr: String) = add(new BooleanSetting(name, descr)) def ChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: String) = add(new ChoiceSetting(name, helpArg, descr, choices, default)) - def DefinesSetting() = add(new DefinesSetting()) def IntSetting(name: String, descr: String, default: Int, range: Option[(Int, Int)], parser: String => Option[Int]) = add(new IntSetting(name, descr, default, range, parser)) def MultiStringSetting(name: String, arg: String, descr: String) = add(new MultiStringSetting(name, arg, descr)) def OutputSetting(outputDirs: OutputDirs, default: String) = add(new OutputSetting(outputDirs, default)) @@ -622,39 +607,4 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal withHelpSyntax(name + ":<phase>") } - - /** A setting for a -D style property definition */ - class DefinesSetting private[nsc] extends Setting("-D", "set a Java property") { - type T = List[(String, String)] - protected var v: T = Nil - withHelpSyntax(name + "<prop>") - - // given foo=bar returns Some(foo, bar), or None if parse fails - def parseArg(s: String): Option[(String, String)] = { - if (s == "") return None - val idx = s indexOf '=' - - if (idx < 0) Some(s, "") - else Some(s take idx, s drop (idx + 1)) - } - - protected[nsc] override def tryToSetProperty(args: List[String]): Option[List[String]] = - tryToSet(args) - - def tryToSet(args: List[String]) = - if (args.isEmpty) None - else parseArg(args.head) match { - case None => None - case Some((a, b)) => value = value ++ List((a, b)) ; Some(args.tail) - } - - def unparse: List[String] = - value map { case (k,v) => "-D" + k + (if (v == "") "" else "=" + v) } - - /** Apply the specified properties to the current JVM and returns them. */ - def applyToJVM() = { - value foreach { case (k, v) => System.getProperties.setProperty(k, v) } - value - } - } } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 37e595fba1..360a19d54b 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -31,7 +31,6 @@ trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings { val classpath = PathSetting ("-classpath", "Specify where to find user class files.", scalaUserClassPath) . withAbbreviation ("-cp") val d = OutputSetting (outputDirs, ".") - val defines = DefinesSetting() val optimise = BooleanSetting ("-optimise", "Generates faster bytecode by applying optimisations to the program") . withAbbreviation("-optimize") . withPostSetHook(set => List(inline, Xcloselim, Xdce) foreach (_.value = set.value)) diff --git a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala index 118daed7ff..98a124b310 100644 --- a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala @@ -49,5 +49,4 @@ trait StandardScalaSettings { * nicely map to identifiers. */ val argfiles: BooleanSetting // exists only to echo help message, should be done differently - val defines: DefinesSetting // not entirely clear that DefinesSetting makes sense as a Setting } |