Skip to content

Commit

Permalink
Reduce time spent in lubs
Browse files Browse the repository at this point in the history
Reduce time spent in lubs by making depth more adaptive. It now takes into account separately the depth of the lub types and the maximal depth of theior base type sequences. It cuts depth more aggressively if it is the base types  instead of the types themselves that grow deep.

The old truncation behavior is retained under option -Xfull-lubs

Another change is that we now track depth more precisely, which should also help or at least allow better statistics.

Also added statistics that measure #lubs and time spent in them.
  • Loading branch information
odersky authored and adriaanm committed Jun 8, 2012
1 parent abc1c0b commit 1dd02bd
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 78 deletions.
1 change: 1 addition & 0 deletions src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ trait ScalaSettings extends AbsScalaSettings

val XoldPatmat = BooleanSetting ("-Xoldpatmat", "Use the pre-2.10 pattern matcher. Otherwise, the 'virtualizing' pattern matcher is used in 2.10.")
val XnoPatmatAnalysis = BooleanSetting ("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.")
val XfullLubs = BooleanSetting ("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.")

/** Compatibility stubs for options whose value name did
* not previously match the option name.
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/scala/tools/nsc/util/Statistics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ abstract class StatisticsInfo {
inform(" of which in app impl : " + subtypeAppInfos)
inform(" of which in improv : " + subtypeImprovCount)
inform("#sametype : " + sametypeCount)
inform("#toplevel lub : " + lubCount)
inform("#all lub : " + nestedLubCount)
inform("ms type-flow-analysis: " + analysis.timer.millis)

if (phase.name == "typer") {
Expand All @@ -155,6 +157,7 @@ abstract class StatisticsInfo {
inform(" failed apply : " + showRelTyper(failedApplyNanos))
inform(" failed op= : " + showRelTyper(failedOpEqNanos))
inform("time spent ref scanning : " + showRelTyper(isReferencedNanos))
inform("time spent in lubs : " + showRelTyper(lubNanos))
inform("micros by tree node : " + showCounts(microsByType))
inform("#visits by tree node : " + showCounts(visitsByType))
val average = new ClassCounts
Expand Down
35 changes: 4 additions & 31 deletions src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -127,38 +127,11 @@ trait BaseTypeSeqs {

def exists(p: Type => Boolean): Boolean = elems exists p

lazy val maxDepth: Int = maxDepthOfElems
lazy val maxDepth = maxDepthOfElems

protected def maxDepthOfElems = {
protected def maxDepthOfElems: Int = {
var d = 0
for (i <- 0 until length) d = max(d, maxDpth(elems(i)))
d
}

/** The maximum depth of type `tp` */
protected def maxDpth(tp: Type): Int = tp match {
case TypeRef(pre, sym, args) =>
max(maxDpth(pre), maxDpth(args) + 1)
case RefinedType(parents, decls) =>
max(maxDpth(parents), maxDpth(decls.toList.map(_.info)) + 1)
case TypeBounds(lo, hi) =>
max(maxDpth(lo), maxDpth(hi))
case MethodType(paramtypes, result) =>
maxDpth(result)
case NullaryMethodType(result) =>
maxDpth(result)
case PolyType(tparams, result) =>
max(maxDpth(result), maxDpth(tparams map (_.info)) + 1)
case ExistentialType(tparams, result) =>
max(maxDpth(result), maxDpth(tparams map (_.info)) + 1)
case _ =>
1
}

/** The maximum depth of all types `tps` */
private def maxDpth(tps: Seq[Type]): Int = {
var d = 0
for (tp <- tps) d = max(d, maxDpth(tp))
for (i <- 1 until length) d = max(d, typeDepth(elems(i)))
d
}

Expand Down Expand Up @@ -252,7 +225,7 @@ trait BaseTypeSeqs {
override def map(g: Type => Type) = lateMap(g)
override def lateMap(g: Type => Type) = orig.lateMap(x => g(f(x)))
override def exists(p: Type => Boolean) = elems exists (x => p(f(x)))
override protected def maxDepthOfElems: Int = (elems map (x => maxDpth(f(x)))).max
override protected def maxDepthOfElems: Int = elems map (x => typeDepth(f(x))) max
override def toString = elems.mkString("MBTS(", ",", ")")
}

Expand Down
Loading

0 comments on commit 1dd02bd

Please sign in to comment.