Skip to content

Commit 3450dfb

Browse files
committed
Profile more events, make the profiler more Scala3 idiomatic
1 parent b9af5a2 commit 3450dfb

File tree

7 files changed

+90
-29
lines changed

7 files changed

+90
-29
lines changed

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ private sealed trait YSettings:
447447
//.withPostSetHook( _ => YprofileEnabled.value = true )
448448
val YprofileRunGcBetweenPhases: Setting[List[String]] = PhasesSetting(ForkSetting, "Yprofile-run-gc", "Run a GC between phases - this allows heap size to be accurate at the expense of more time. Specify a list of phases, or *", "_")
449449
//.withPostSetHook( _ => YprofileEnabled.value = true )
450-
val YprofileTrace: Setting[String] = StringSetting("-Yprofile-trace", "file", "Capture trace of compilation in Chrome Trace format", "profile.trace")
450+
val YprofileTrace: Setting[String] = StringSetting(ForkSetting, "Yprofile-trace", "file", "Capture trace of compilation in Chrome Trace format", "profile.trace")
451451
//.withPostSetHook( _ => YprofileEnabled.value = true )
452452

453453
val YbestEffort: Setting[Boolean] = BooleanSetting(ForkSetting, "Ybest-effort", "Enable best-effort compilation attempting to produce betasty to the META-INF/best-effort directory, regardless of errors, as part of the pickler phase.")

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import java.nio.channels.ClosedByInterruptException
88
import scala.util.control.NonFatal
99

1010
import dotty.tools.dotc.classpath.FileUtils.{hasTastyExtension, hasBetastyExtension}
11-
import dotty.tools.io.{ ClassPath, ClassRepresentation, AbstractFile }
11+
import dotty.tools.io.{ ClassPath, ClassRepresentation, AbstractFile, NoAbstractFile }
1212
import dotty.tools.backend.jvm.DottyBackendInterface.symExtensions
1313

1414
import Contexts.*, Symbols.*, Flags.*, SymDenotations.*, Types.*, Scopes.*, Names.*
@@ -333,7 +333,18 @@ abstract class SymbolLoader extends LazyType { self =>
333333
def description(using Context): String = s"proxy to ${self.description}"
334334
}
335335

336-
override def complete(root: SymDenotation)(using Context): Unit = {
336+
private inline def tryProfileCompletion[T](root: SymDenotation)(inline body: T)(using Context): T = {
337+
if ctx.profiler eq null
338+
then body
339+
else
340+
val sym = root.symbol
341+
val associatedFile = root.symbol.associatedFile match
342+
case file: AbstractFile => file
343+
case _ => NoAbstractFile
344+
ctx.profiler.onCompletion(sym, associatedFile)(body)
345+
}
346+
347+
override def complete(root: SymDenotation)(using Context): Unit = tryProfileCompletion(root) {
337348
def signalError(ex: Exception): Unit = {
338349
if (ctx.debug) ex.printStackTrace()
339350
val msg = ex.getMessage()
@@ -408,7 +419,6 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
408419

409420
def compilationUnitInfo: CompilationUnitInfo | Null = CompilationUnitInfo(classfile)
410421

411-
412422
def description(using Context): String = "class file " + classfile.toString
413423

414424
override def doComplete(root: SymDenotation)(using Context): Unit =

compiler/src/dotty/tools/dotc/profile/ChromeTrace.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ final class ChromeTrace(f: Path) extends Closeable {
6363
traceWriter.close()
6464
}
6565

66-
def traceDurationEvent(name: String, startNanos: Long, durationNanos: Long, tid: String = this.tid(), pidSuffix: String = ""): Unit = {
66+
def traceDurationEvent(name: String, startNanos: Long, durationNanos: Long, tid: String = this.tid(), pidSuffix: String = ""): Unit = synchronized {
6767
val durationMicros = nanosToMicros(durationNanos)
6868
val startMicros = nanosToMicros(startNanos)
6969
objStart()
@@ -85,7 +85,7 @@ final class ChromeTrace(f: Path) extends Closeable {
8585
str2("pid", pid, "-", pidSuffix)
8686
}
8787

88-
def traceCounterEvent(name: String, counterName: String, count: Long, processWide: Boolean): Unit = {
88+
def traceCounterEvent(name: String, counterName: String, count: Long, processWide: Boolean): Unit = synchronized {
8989
objStart()
9090
str("cat", "scalac")
9191
str("name", name)
@@ -104,7 +104,7 @@ final class ChromeTrace(f: Path) extends Closeable {
104104
def traceDurationEventStart(cat: String, name: String, colour: String = "", pidSuffix: String = tid()): Unit = traceDurationEventStartEnd(EventType.Start, cat, name, colour, pidSuffix)
105105
def traceDurationEventEnd(cat: String, name: String, colour: String = "", pidSuffix: String = tid()): Unit = traceDurationEventStartEnd(EventType.End, cat, name, colour, pidSuffix)
106106

107-
private def traceDurationEventStartEnd(eventType: String, cat: String, name: String, colour: String, pidSuffix: String = ""): Unit = {
107+
private def traceDurationEventStartEnd(eventType: String, cat: String, name: String, colour: String, pidSuffix: String = ""): Unit = synchronized {
108108
objStart()
109109
str("cat", cat)
110110
str("name", name)

compiler/src/dotty/tools/dotc/profile/Profiler.scala

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ import dotty.tools.dotc.core.Contexts.*
1616
import dotty.tools.dotc.CompilationUnit
1717
import dotty.tools.dotc.core.Types.Type
1818
import dotty.tools.dotc.core.Symbols.Symbol
19+
import dotty.tools.dotc.core.Flags
20+
import dotty.tools.backend.jvm.DottyBackendInterface.symExtensions
1921
import dotty.tools.io.AbstractFile
2022
import annotation.internal.sharable
23+
import dotty.tools.dotc.core.Symbols.NoSymbol
2124

2225
object Profiler {
2326
def apply()(using Context): Profiler =
@@ -78,15 +81,39 @@ sealed trait Profiler {
7881

7982
def afterPhase(phase: Phase, profileBefore: ProfileSnap): Unit
8083

84+
inline def onUnit[T](phase: Phase, unit: CompilationUnit)(inline body: T): T =
85+
beforeUnit(phase, unit)
86+
try body
87+
finally afterUnit(phase, unit)
8188
def beforeUnit(phase: Phase, unit: CompilationUnit): Unit = ()
8289
def afterUnit(phase: Phase, unit: CompilationUnit): Unit = ()
8390

91+
inline def onTypedImplDef[T](sym: Symbol)(inline body: T): T =
92+
beforeTypedImplDef(sym)
93+
try body
94+
finally afterTypedImplDef(sym)
8495
def beforeTypedImplDef(sym: Symbol): Unit = ()
8596
def afterTypedImplDef(sym: Symbol): Unit = ()
8697

98+
99+
inline def onImplicitSearch[T](pt: Type)(inline body: T): T =
100+
beforeImplicitSearch(pt)
101+
try body
102+
finally afterImplicitSearch(pt)
87103
def beforeImplicitSearch(pt: Type): Unit = ()
88104
def afterImplicitSearch(pt: Type): Unit = ()
89105

106+
inline def onMacroExpansion[T](macroSym: Symbol)(inline body: T): T =
107+
beforeMacroExpansion(macroSym)
108+
try body
109+
finally afterMacroExpansion(macroSym)
110+
def beforeMacroExpansion(macroSym: Symbol): Unit = ()
111+
def afterMacroExpansion(macroSym: Symbol): Unit = ()
112+
113+
inline def onCompletion[T](root: Symbol, associatedFile: AbstractFile)(inline body: T): T =
114+
beforeCompletion(root, associatedFile)
115+
try body
116+
finally afterCompletion(root, associatedFile)
90117
def beforeCompletion(root: Symbol, associatedFile: AbstractFile): Unit = ()
91118
def afterCompletion(root: Symbol, associatedFile: AbstractFile): Unit = ()
92119
}
@@ -280,13 +307,42 @@ private [profile] class RealProfiler(reporter : ProfileReporter)(using Context)
280307

281308
override def beforeImplicitSearch(pt: Type): Unit =
282309
if chromeTrace != null
283-
then chromeTrace.traceDurationEventStart(Category.Implicit, "?[" + pt.typeSymbol.fullName + "]", colour = "yellow")
284-
310+
then chromeTrace.traceDurationEventStart(Category.Implicit, s"?[${symbolName(pt.typeSymbol)}]", colour = "yellow")
285311

286312
override def afterImplicitSearch(pt: Type): Unit =
287313
if chromeTrace != null
288-
then chromeTrace.traceDurationEventEnd(Category.Implicit, "?[" + pt.typeSymbol.fullName + "]", colour = "yellow")
314+
then chromeTrace.traceDurationEventEnd(Category.Implicit, s"?[${symbolName(pt.typeSymbol)}]", colour = "yellow")
315+
316+
override def beforeMacroExpansion(macroSym: Symbol): Unit =
317+
if chromeTrace != null
318+
then chromeTrace.traceDurationEventStart(Category.Macro, s"«${symbolName(macroSym)}»", colour = "olive")
319+
320+
override def afterMacroExpansion(macroSym: Symbol): Unit =
321+
if chromeTrace != null
322+
then chromeTrace.traceDurationEventEnd(Category.Macro, s"«${symbolName(macroSym)}»", colour = "olive")
323+
324+
override def beforeCompletion(root: Symbol, associatedFile: AbstractFile): Unit =
325+
if chromeTrace != null
326+
then
327+
chromeTrace.traceDurationEventStart(Category.Completion, "", colour = "thread_state_sleeping")
328+
chromeTrace.traceDurationEventStart(Category.File, associatedFile.name)
329+
chromeTrace.traceDurationEventStart(Category.Completion, completionName(root, associatedFile))
289330

331+
override def afterCompletion(root: Symbol, associatedFile: AbstractFile): Unit =
332+
if chromeTrace != null
333+
then
334+
chromeTrace.traceDurationEventEnd(Category.Completion, completionName(root, associatedFile))
335+
chromeTrace.traceDurationEventEnd(Category.File, associatedFile.name)
336+
chromeTrace.traceDurationEventEnd(Category.Completion, "", colour = "thread_state_sleeping")
337+
338+
private def symbolName(sym: Symbol): String = sym.name.toString
339+
private def completionName(root: Symbol, associatedFile: AbstractFile): String =
340+
def isTopLevel = root.owner != NoSymbol && root.owner.is(Flags.Package)
341+
if root.is(Flags.Package) || isTopLevel
342+
then root.javaBinaryName
343+
else
344+
val enclosing = root.enclosingClass
345+
s"${enclosing.javaBinaryName}::${root.name}"
290346
}
291347

292348
case class EventType(name: String)

compiler/src/dotty/tools/dotc/quoted/Interpreter.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,9 @@ class Interpreter(pos: SrcPos, classLoader0: ClassLoader)(using Context):
171171
val clazz = inst.getClass
172172
val name = fn.name.asTermName
173173
val method = getMethod(clazz, name, paramsSig(fn))
174-
stopIfRuntimeException(method.invoke(inst, args*), method)
174+
ctx.profiler.onMacroExpansion(fn){
175+
stopIfRuntimeException(method.invoke(inst, args*), method)
176+
}
175177
}
176178

177179
private def interpretedStaticFieldAccess(sym: Symbol): Object = {

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,9 +1078,8 @@ trait Implicits:
10781078
* it should be applied, EmptyTree otherwise.
10791079
* @param span The position where errors should be reported.
10801080
*/
1081-
def inferImplicit(pt: Type, argument: Tree, span: Span)(using Context): SearchResult =
1082-
ctx.profiler.beforeImplicitSearch(pt)
1083-
try trace(s"search implicit ${pt.show}, arg = ${argument.show}: ${argument.tpe.show}", implicits, show = true) {
1081+
def inferImplicit(pt: Type, argument: Tree, span: Span)(using Context): SearchResult = ctx.profiler.onImplicitSearch(pt) {
1082+
trace(s"search implicit ${pt.show}, arg = ${argument.show}: ${argument.tpe.show}", implicits, show = true) {
10841083
record("inferImplicit")
10851084
assert(ctx.phase.allowsImplicitSearch,
10861085
if (argument.isEmpty) i"missing implicit parameter of type $pt after typer at phase ${ctx.phase}"
@@ -1147,7 +1146,8 @@ trait Implicits:
11471146
}
11481147
// If we are at the outermost implicit search then emit the implicit dictionary, if any.
11491148
ctx.searchHistory.emitDictionary(span, result)
1150-
} finally ctx.profiler.afterImplicitSearch(pt)
1149+
}
1150+
}
11511151

11521152
/** Try to typecheck an implicit reference */
11531153
def typedImplicit(cand: Candidate, pt: Type, argument: Tree, span: Span)(using Context): SearchResult = trace(i"typed implicit ${cand.ref}, pt = $pt, implicitsEnabled == ${ctx.mode is ImplicitsEnabled}", implicits, show = true) {

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2830,9 +2830,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
28302830
case _ =>
28312831
typed(rhs)
28322832

2833-
def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree =
2834-
ctx.profiler.beforeTypedImplDef(sym)
2835-
try {
2833+
def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree = ctx.profiler.onTypedImplDef(sym) {
28362834
val ValDef(name, tpt, _) = vdef
28372835
checkNonRootName(vdef.name, vdef.nameSpan)
28382836
completeAnnotations(vdef, sym)
@@ -2848,7 +2846,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
28482846
val vdef1 = assignType(cpy.ValDef(vdef)(name, tpt1, rhs1), sym)
28492847
postProcessInfo(vdef1, sym)
28502848
vdef1.setDefTree
2851-
} finally ctx.profiler.afterTypedImplDef(sym)
2849+
}
28522850

28532851
private def retractDefDef(sym: Symbol)(using Context): Tree =
28542852
// it's a discarded method (synthetic case class method or synthetic java record constructor or overridden member), drop it
@@ -2860,7 +2858,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
28602858
sym.owner.info.decls.openForMutations.unlink(sym)
28612859
EmptyTree
28622860

2863-
def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(using Context): Tree = if !sym.info.exists then retractDefDef(sym) else {
2861+
def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(using Context): Tree = if !sym.info.exists then retractDefDef(sym) else ctx.profiler.onTypedImplDef {
28642862

28652863
// TODO: - Remove this when `scala.language.experimental.erasedDefinitions` is no longer experimental.
28662864
// - Modify signature to `erased def erasedValue[T]: T`
@@ -2960,7 +2958,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
29602958
postProcessInfo(ddef2, sym)
29612959
ddef2.setDefTree
29622960
//todo: make sure dependent method types do not depend on implicits or by-name params
2963-
} finally ctx.profiler.afterTypedImplDef(sym)
2961+
}
29642962

29652963
/** (1) Check that the signature of the class member does not return a repeated parameter type
29662964
* (2) If info is an erased class, set erased flag of member
@@ -2972,9 +2970,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
29722970
if !sym.is(Module) && !sym.isConstructor && sym.info.finalResultType.isErasedClass then
29732971
sym.setFlag(Erased)
29742972

2975-
def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(using Context): Tree = {
2976-
ctx.profiler.beforeTypedImplDef(sym)
2977-
try {
2973+
def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(using Context): Tree = ctx.profiler.onTypedImplDef(sym) {
29782974
val TypeDef(name, rhs) = tdef
29792975
completeAnnotations(tdef, sym)
29802976
val rhs1 = tdef.rhs match
@@ -2986,12 +2982,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
29862982
checkFullyAppliedType(rhs1, "Opaque type alias must be fully applied, but ")
29872983
checkNoContextFunctionType(rhs1)
29882984
assignType(cpy.TypeDef(tdef)(name, rhs1), sym)
2989-
} finally ctx.profiler.afterTypedImplDef(sym)
29902985
}
29912986

2992-
def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(using Context): Tree =
2993-
ctx.profiler.beforeTypedImplDef(cls)
2994-
try {
2987+
def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(using Context): Tree = ctx.profiler.onTypedImplDef(cls) {
29952988
if (!cls.info.isInstanceOf[ClassInfo]) return EmptyTree.assertingErrorsReported
29962989

29972990
val TypeDef(name, impl @ Template(constr, _, self, _)) = cdef: @unchecked
@@ -3218,7 +3211,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
32183211

32193212
cdef1
32203213
}
3221-
} finally ctx.profiler.afterTypedImplDef(cls)
3214+
}
32223215

32233216
// todo later: check that
32243217
// 1. If class is non-abstract, it is instantiatable:

0 commit comments

Comments
 (0)