diff options
author | Paul Phillips <paulp@improving.org> | 2011-06-28 17:47:21 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-06-28 17:47:21 +0000 |
commit | 42fb66a2cbcad4fff0634dc935f135494f04be93 (patch) | |
tree | c1aad8ed0ae96f968a34164d481d524a4fbcf184 | |
parent | c23c21853a76adfc8694ce752853a5be5d5c8cf3 (diff) | |
download | scala-42fb66a2cbcad4fff0634dc935f135494f04be93.tar.gz scala-42fb66a2cbcad4fff0634dc935f135494f04be93.tar.bz2 scala-42fb66a2cbcad4fff0634dc935f135494f04be93.zip |
Continuing to press on RefChecks, discovered wh...
Continuing to press on RefChecks, discovered what seemed a pretty
spectacular performance bug, at least at first. I was disappointed to
see that the time gain didn't measure up. Still, nanos are nanos.
According to YourKit, millis spent in List#foreach on a compilation of
src/library broke down like this:
| +---LinearSeqOptimized$class.foreach | 173,123 100 % |
| +---RefChecks$RefCheckTransformer.register$1 | 117,658 68 % |
I think that is largely a profiler lie, but there is enough truth. After
adjusting to prune before recursing, the number of invocations of method
register in validateBaseTypes drops by 98%.
Review by odersky.
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index e842a667aa..a434af1175 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -7,7 +7,7 @@ package scala.tools.nsc package typechecker import symtab.Flags._ -import collection.mutable.{HashSet, HashMap} +import collection.{ mutable, immutable } import transform.InfoTransform import scala.collection.mutable.ListBuffer @@ -658,11 +658,13 @@ abstract class RefChecks extends InfoTransform { * </ol> */ private def validateBaseTypes(clazz: Symbol) { + val seenParents = mutable.HashSet[Type]() val seenTypes = new Array[List[Type]](clazz.info.baseTypeSeq.length) - for (i <- 0 until seenTypes.length) seenTypes(i) = Nil + for (i <- 0 until seenTypes.length) + seenTypes(i) = Nil /** validate all base types of a class in reverse linear order. */ - def register(tp: Type) { + def register(tp: Type): Unit = { // if (clazz.fullName.endsWith("Collection.Projection")) // println("validate base type "+tp) val baseClass = tp.typeSymbol @@ -674,7 +676,9 @@ abstract class RefChecks extends InfoTransform { tp :: (seenTypes(index) filter (tp1 => !(tp <:< tp1))) } } - tp.parents foreach register + val remaining = tp.parents filterNot seenParents + seenParents ++= remaining + remaining foreach register } register(clazz.tpe) for (i <- 0 until seenTypes.length) { @@ -701,7 +705,7 @@ abstract class RefChecks extends InfoTransform { private val CoVariance = 1 private val AnyVariance = 2 - private val escapedPrivateLocals = new HashSet[Symbol] + private val escapedPrivateLocals = new mutable.HashSet[Symbol] val varianceValidator = new Traverser { @@ -851,7 +855,7 @@ abstract class RefChecks extends InfoTransform { } private var currentLevel: LevelInfo = null - private val symIndex = new HashMap[Symbol, Int] + private val symIndex = new mutable.HashMap[Symbol, Int] private def pushLevel() { currentLevel = new LevelInfo(currentLevel) |