Skip to content

Commit e5b1ecc

Browse files
committed
Instrument collection sizes
Allow to record total sizes of collections on which some selected operation is performed. # Conflicts: # compiler/src/dotty/tools/dotc/transform/Instrumentation.scala
1 parent af1b4a0 commit e5b1ecc

File tree

3 files changed

+40
-13
lines changed

3 files changed

+40
-13
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -845,8 +845,6 @@ class Definitions {
845845
@tu lazy val Not_value: Symbol = NotClass.companionModule.requiredMethod(nme.value)
846846

847847
@tu lazy val ValueOfClass: ClassSymbol = requiredClass("scala.ValueOf")
848-
@tu lazy val StatsModule: Symbol = requiredModule("dotty.tools.dotc.util.Stats")
849-
@tu lazy val Stats_doRecord: Symbol = StatsModule.requiredMethod("doRecord")
850848

851849
@tu lazy val FromDigitsClass: ClassSymbol = requiredClass("scala.util.FromDigits")
852850
@tu lazy val FromDigits_WithRadixClass: ClassSymbol = requiredClass("scala.util.FromDigits.WithRadix")

compiler/src/dotty/tools/dotc/transform/Instrumentation.scala

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
package dotty.tools.dotc
1+
package dotty.tools
2+
package dotc
23
package transform
34

45
import core._
@@ -27,33 +28,57 @@ class Instrumentation extends MiniPhase { thisPhase =>
2728
override def isEnabled(using Context) =
2829
ctx.settings.Yinstrument.value
2930

30-
private val namesOfInterest = List(
31-
"::", "+=", "toString", "newArray", "box", "toCharArray",
32-
"map", "flatMap", "filter", "withFilter", "collect", "foldLeft", "foldRight", "take",
33-
"reverse", "mapConserve", "mapconserve", "filterConserve", "zip",
34-
"denotsNamed", "lookup", "lookupEntry", "lookupAll", "toList")
35-
private var namesToRecord: Set[Name] = _
31+
private val collectionNamesOfInterest = List(
32+
"map", "flatMap", "filter", "filterNot", "withFilter", "collect", "flatten", "foldLeft", "foldRight", "take",
33+
"reverse", "zip", "++", ":::", ":+", "distinct", "dropRight", "takeRight", "groupBy", "groupMap", "init", "inits",
34+
"interect", "mkString", "partition", "reverse_:::", "scanLeft", "scanRight",
35+
"sortBy", "sortWith", "sorted", "span", "splitAt", "takeWhile", "transpose", "unzip", "unzip3",
36+
"updated", "zipAll", "zipWithIndex",
37+
"mapConserve", "mapconserve", "filterConserve", "zipWithConserve", "mapWithIndexConserve"
38+
)
39+
40+
private val namesOfInterest = collectionNamesOfInterest ++ List(
41+
"::", "+=", "toString", "newArray", "box", "toCharArray", "termName", "typeName",
42+
"slice", "staticRef", "requiredClass")
3643

37-
private var consName: TermName = _
38-
private var consEqName: TermName = _
44+
private var namesToRecord: Set[Name] = _
45+
private var collectionNamesToRecord: Set[Name] = _
46+
private var Stats_doRecord: Symbol = _
47+
private var Stats_doRecordSize: Symbol = _
48+
private var CollectionIterableClass: ClassSymbol = _
3949

4050
override def prepareForUnit(tree: Tree)(using Context): Context =
4151
namesToRecord = namesOfInterest.map(_.toTermName).toSet
52+
collectionNamesToRecord = collectionNamesOfInterest.map(_.toTermName).toSet
53+
val StatsModule = requiredModule("dotty.tools.dotc.util.Stats")
54+
Stats_doRecord = StatsModule.requiredMethod("doRecord")
55+
Stats_doRecordSize = StatsModule.requiredMethod("doRecordSize")
56+
CollectionIterableClass = requiredClass("scala.collection.Iterable")
4257
ctx
4358

4459
private def record(category: String, tree: Tree)(using Context): Tree = {
4560
val key = Literal(Constant(s"$category@${tree.sourcePos.show}"))
46-
ref(defn.Stats_doRecord).appliedTo(key, Literal(Constant(1)))
61+
ref(Stats_doRecord).appliedTo(key, Literal(Constant(1)))
4762
}
4863

64+
private def recordSize(tree: Apply)(using Context): Tree = tree.fun match
65+
case sel @ Select(qual, name)
66+
if collectionNamesToRecord.contains(name)
67+
&& qual.tpe.widen.derivesFrom(CollectionIterableClass) =>
68+
val key = Literal(Constant(s"totalSize/${name} in ${qual.tpe.widen.classSymbol.name}@${tree.sourcePos.show}"))
69+
val qual1 = ref(Stats_doRecordSize).appliedTo(key, qual).cast(qual.tpe.widen)
70+
cpy.Apply(tree)(cpy.Select(sel)(qual1, name), tree.args)
71+
case _ =>
72+
tree
73+
4974
private def ok(using Context) =
5075
!ctx.owner.ownersIterator.exists(_.name.toString.startsWith("Stats"))
5176

5277
override def transformApply(tree: Apply)(using Context): Tree = tree.fun match {
5378
case Select(nu: New, _) =>
5479
cpy.Block(tree)(record(i"alloc/${nu.tpe}", tree) :: Nil, tree)
5580
case ref: RefTree if namesToRecord.contains(ref.name) && ok =>
56-
cpy.Block(tree)(record(i"call/${ref.name}", tree) :: Nil, tree)
81+
cpy.Block(tree)(record(i"call/${ref.name}", tree) :: Nil, recordSize(tree))
5782
case _ =>
5883
tree
5984
}

compiler/src/dotty/tools/dotc/util/Stats.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ import collection.mutable
2828
hits(name) += n
2929
}
3030

31+
def doRecordSize(fn: String, coll: scala.collection.Iterable[_]): coll.type =
32+
doRecord(fn, coll.size)
33+
coll
34+
3135
inline def trackTime[T](fn: String)(inline op: T): T =
3236
if (enabled) doTrackTime(fn)(op) else op
3337

0 commit comments

Comments
 (0)