Skip to content

Commit 0a5745b

Browse files
committed
Profile more events, make the profiler more Scala3 idiomatic
1 parent da05f95 commit 0a5745b

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
@@ -2823,9 +2823,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
28232823
case _ =>
28242824
typed(rhs)
28252825

2826-
def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree =
2827-
ctx.profiler.beforeTypedImplDef(sym)
2828-
try {
2826+
def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree = ctx.profiler.onTypedImplDef(sym) {
28292827
val ValDef(name, tpt, _) = vdef
28302828
checkNonRootName(vdef.name, vdef.nameSpan)
28312829
completeAnnotations(vdef, sym)
@@ -2841,7 +2839,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
28412839
val vdef1 = assignType(cpy.ValDef(vdef)(name, tpt1, rhs1), sym)
28422840
postProcessInfo(vdef1, sym)
28432841
vdef1.setDefTree
2844-
} finally ctx.profiler.afterTypedImplDef(sym)
2842+
}
28452843

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

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

28582856
// TODO: - Remove this when `scala.language.experimental.erasedDefinitions` is no longer experimental.
28592857
// - Modify signature to `erased def erasedValue[T]: T`
@@ -2953,7 +2951,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
29532951
postProcessInfo(ddef2, sym)
29542952
ddef2.setDefTree
29552953
//todo: make sure dependent method types do not depend on implicits or by-name params
2956-
} finally ctx.profiler.afterTypedImplDef(sym)
2954+
}
29572955

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

2968-
def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(using Context): Tree = {
2969-
ctx.profiler.beforeTypedImplDef(sym)
2970-
try {
2966+
def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(using Context): Tree = ctx.profiler.onTypedImplDef(sym) {
29712967
val TypeDef(name, rhs) = tdef
29722968
completeAnnotations(tdef, sym)
29732969
val rhs1 = tdef.rhs match
@@ -2979,12 +2975,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
29792975
checkFullyAppliedType(rhs1, "Opaque type alias must be fully applied, but ")
29802976
checkNoContextFunctionType(rhs1)
29812977
assignType(cpy.TypeDef(tdef)(name, rhs1), sym)
2982-
} finally ctx.profiler.afterTypedImplDef(sym)
29832978
}
29842979

2985-
def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(using Context): Tree =
2986-
ctx.profiler.beforeTypedImplDef(cls)
2987-
try {
2980+
def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(using Context): Tree = ctx.profiler.onTypedImplDef(cls) {
29882981
if (!cls.info.isInstanceOf[ClassInfo]) return EmptyTree.assertingErrorsReported
29892982

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

32123205
cdef1
32133206
}
3214-
} finally ctx.profiler.afterTypedImplDef(cls)
3207+
}
32153208

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

0 commit comments

Comments
 (0)