Skip to content

Commit 718af3a

Browse files
committed
Reduce ammount of allocations, increase ammontof counters tracing and other cleanups
1 parent e76fce4 commit 718af3a

File tree

7 files changed

+98
-95
lines changed

7 files changed

+98
-95
lines changed

Diff for: compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ private sealed trait YSettings:
444444
val YprofileDestination: Setting[String] = StringSetting(ForkSetting, "Yprofile-destination", "file", "Where to send profiling output - specify a file, default is to the console.", "", depends = List(YprofileEnabled -> true))
445445
val YprofileExternalTool: Setting[List[String]] = PhasesSetting(ForkSetting, "Yprofile-external-tool", "Enable profiling for a phase using an external tool hook. Generally only useful for a single phase.", "typer", depends = List(YprofileEnabled -> true))
446446
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 *", "_", depends = List(YprofileEnabled -> true))
447-
val YprofileTrace: Setting[String] = StringSetting(ForkSetting, "Yprofile-trace", "file", s"Capture trace of compilation in Chrome Trace format, requires ${YprofileEnabled.name}", "", depends = List(YprofileEnabled -> true))
447+
val YprofileTrace: Setting[String] = StringSetting(ForkSetting, "Yprofile-trace", "file", s"Capture trace of compilation in JSON Chrome Trace format to the specified file. This option requires ${YprofileEnabled.name}. The output file can be visualized using https://ui.perfetto.dev/.", "", depends = List(YprofileEnabled -> true))
448448

449449
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.")
450450
val YwithBestEffortTasty: Setting[Boolean] = BooleanSetting(ForkSetting, "Ywith-best-effort-tasty", "Allow to compile using best-effort tasty files. If such file is used, the compiler will stop after the pickler phase.")

Diff for: compiler/src/dotty/tools/dotc/config/Settings.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,8 @@ object Settings:
390390
def BooleanSetting(category: SettingCategory, name: String, descr: String, initialValue: Boolean = false, aliases: List[String] = Nil, preferPrevious: Boolean = false, deprecation: Option[Deprecation] = None, ignoreInvalidArgs: Boolean = false): Setting[Boolean] =
391391
publish(Setting(category, prependName(name), descr, initialValue, aliases = aliases, preferPrevious = preferPrevious, deprecation = deprecation, ignoreInvalidArgs = ignoreInvalidArgs))
392392

393-
def StringSetting(category: SettingCategory, name: String, helpArg: String, descr: String, default: String, aliases: List[String] = Nil): Setting[String] =
394-
publish(Setting(category, prependName(name), descr, default, helpArg, aliases = aliases))
393+
def StringSetting(category: SettingCategory, name: String, helpArg: String, descr: String, default: String, aliases: List[String] = Nil, deprecation: Option[Deprecation] = None, depends: SettingDependencies = Nil): Setting[String] =
394+
publish(Setting(category, prependName(name), descr, default, helpArg, aliases = aliases, deprecation = deprecation, depends = depends))
395395

396396
def ChoiceSetting(category: SettingCategory, name: String, helpArg: String, descr: String, choices: List[String], default: String, aliases: List[String] = Nil, legacyArgs: Boolean = false, deprecation: Option[Deprecation] = None): Setting[String] =
397397
publish(Setting(category, prependName(name), descr, default, helpArg, Some(choices), aliases = aliases, legacyArgs = legacyArgs, deprecation = deprecation))
@@ -417,8 +417,8 @@ object Settings:
417417
def PathSetting(category: SettingCategory, name: String, descr: String, default: String, aliases: List[String] = Nil, deprecation: Option[Deprecation] = None): Setting[String] =
418418
publish(Setting(category, prependName(name), descr, default, aliases = aliases, deprecation = deprecation))
419419

420-
def PhasesSetting(category: SettingCategory, name: String, descr: String, default: String = "", aliases: List[String] = Nil): Setting[List[String]] =
421-
publish(Setting(category, prependName(name), descr, if (default.isEmpty) Nil else List(default), aliases = aliases))
420+
def PhasesSetting(category: SettingCategory, name: String, descr: String, default: String = "", aliases: List[String] = Nil, deprecation: Option[Deprecation] = None, depends: SettingDependencies = Nil): Setting[List[String]] =
421+
publish(Setting(category, prependName(name), descr, if (default.isEmpty) Nil else List(default), aliases = aliases, deprecation = deprecation, depends = depends))
422422

423423
def PrefixSetting(category: SettingCategory, name0: String, descr: String, deprecation: Option[Deprecation] = None): Setting[List[String]] =
424424
val name = prependName(name0)

Diff for: compiler/src/dotty/tools/dotc/profile/ChromeTrace.scala

+7-7
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ object ChromeTrace {
3838
}
3939
}
4040

41-
/** Allows writing a subset of https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview#
42-
* for use in Chrome's about://tracing or the tooling in https://www.google.com.au/search?q=catapult+tracing&oq=catapult+tracing+&aqs=chrome..69i57.3974j0j4&sourceid=chrome&ie=UTF-8 */
41+
/** Allows writing a subset of captrue traces based on https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview#
42+
* Can be visualized using https://ui.perfetto.dev/, Chrome's about://tracing (outdated) or the tooling in https://www.google.com.au/search?q=catapult+tracing&oq=catapult+tracing+&aqs=chrome..69i57.3974j0j4&sourceid=chrome&ie=UTF-8 */
4343
final class ChromeTrace(f: Path) extends Closeable {
4444
import ChromeTrace.EventType
4545
private val traceWriter = FileUtils.newAsyncBufferedWriter(f)
@@ -125,11 +125,11 @@ final class ChromeTrace(f: Path) extends Closeable {
125125

126126
private def microTime(): Long = nanosToMicros(System.nanoTime())
127127

128-
sealed abstract class JsonContext
129-
case class ArrayContext(var first: Boolean) extends JsonContext
130-
case class ObjectContext(var first: Boolean) extends JsonContext
131-
case object ValueContext extends JsonContext
132-
case object TopContext extends JsonContext
128+
private sealed abstract class JsonContext
129+
private case class ArrayContext(var first: Boolean) extends JsonContext
130+
private case class ObjectContext(var first: Boolean) extends JsonContext
131+
private case object ValueContext extends JsonContext
132+
private case object TopContext extends JsonContext
133133

134134
private def str(name: String, value: String): Unit = {
135135
fld(name)

Diff for: compiler/src/dotty/tools/dotc/profile/FileUtils.scala

+3-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import java.util.concurrent.atomic.AtomicBoolean
2727
import scala.concurrent.duration.Duration
2828
import scala.concurrent.{Await, Promise}
2929
import scala.util.{Failure, Success}
30+
import scala.annotation.internal.sharable
3031

3132
object FileUtils {
3233
def newAsyncBufferedWriter(path: Path, charset: Charset = StandardCharsets.UTF_8.nn, options: Array[OpenOption] = NO_OPTIONS, threadsafe: Boolean = false): LineWriter = {
@@ -72,8 +73,8 @@ object FileUtils {
7273
}
7374

7475
private object AsyncBufferedWriter {
75-
private val Close = CharBuffer.allocate(0)
76-
private val Flush = CharBuffer.allocate(0)
76+
@sharable private val Close = CharBuffer.allocate(0)
77+
@sharable private val Flush = CharBuffer.allocate(0)
7778
}
7879
private class AsyncBufferedWriter(val underlying: Writer, bufferSize : Int = 4096) extends LineWriter {
7980
private var current: CharBuffer = allocate

Diff for: compiler/src/dotty/tools/dotc/profile/Profiler.scala

+36-35
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ sealed trait Profiler {
9292
val (event, snapshot) = beforePhase(phase)
9393
try body
9494
finally afterPhase(event, phase, snapshot)
95-
protected def beforePhase(phase: Phase): (TracedEventId, ProfileSnap) = (TracedEventId.Empty, Profiler.emptySnap)
95+
protected final val EmptyPhaseEvent = (TracedEventId.Empty, Profiler.emptySnap)
96+
protected def beforePhase(phase: Phase): (TracedEventId, ProfileSnap) = EmptyPhaseEvent
9697
protected def afterPhase(event: TracedEventId, phase: Phase, profileBefore: ProfileSnap): Unit = ()
9798

9899
inline def onUnit[T](phase: Phase, unit: CompilationUnit)(inline body: T): T =
@@ -127,13 +128,14 @@ sealed trait Profiler {
127128
val (event, completionName) = beforeCompletion(root, associatedFile)
128129
try body
129130
finally afterCompletion(event, completionName)
130-
protected def beforeCompletion(root: Symbol, associatedFile: => AbstractFile): (TracedEventId, String) = (TracedEventId.Empty, "")
131+
protected final val EmptyCompletionEvent = (TracedEventId.Empty, "")
132+
protected def beforeCompletion(root: Symbol, associatedFile: => AbstractFile): (TracedEventId, String) = EmptyCompletionEvent
131133
protected def afterCompletion(event: TracedEventId, completionName: String): Unit = ()
132134
}
133135
private [profile] object NoOpProfiler extends Profiler {
134-
135136
override def finished(): Unit = ()
136137
}
138+
137139
private [profile] object RealProfiler {
138140
import scala.jdk.CollectionConverters.*
139141
val runtimeMx: RuntimeMXBean = ManagementFactory.getRuntimeMXBean
@@ -234,10 +236,7 @@ private [profile] class RealProfiler(reporter : ProfileReporter)(using Context)
234236
import java.lang.{Integer => jInt}
235237
val reportNs = System.nanoTime()
236238
val data = notification.getUserData
237-
// val seq = notification.getSequenceNumber
238-
// val message = notification.getMessage
239239
val tpe = notification.getType
240-
// val time= notification.getTimeStamp
241240
data match {
242241
case cd: CompositeData if tpe == "com.sun.management.gc.notification" =>
243242
val name = cd.get("gcName").toString
@@ -267,12 +266,13 @@ private [profile] class RealProfiler(reporter : ProfileReporter)(using Context)
267266
}
268267
else initialSnap
269268
traceDurationEnd(Category.Phase, event)
270-
269+
traceThreadSnapshotCounters()
271270
reporter.reportForeground(this, ProfileRange(snapBefore, finalSnap, phase, "", 0, Thread.currentThread))
272271
}
273272

274273
override def beforePhase(phase: Phase): (TracedEventId, ProfileSnap) = {
275274
assert(mainThread eq Thread.currentThread())
275+
traceThreadSnapshotCounters()
276276
val eventId = traceDurationStart(Category.Phase, phase.phaseName)
277277
if (ctx.settings.YprofileRunGcBetweenPhases.value.contains(phase.toString))
278278
doGC()
@@ -285,26 +285,32 @@ private [profile] class RealProfiler(reporter : ProfileReporter)(using Context)
285285

286286
override def beforeUnit(phase: Phase, unit: CompilationUnit): TracedEventId = {
287287
assert(mainThread eq Thread.currentThread())
288-
traceDurationStart(Category.File, unit.source.name)
288+
if chromeTrace != null then
289+
traceThreadSnapshotCounters()
290+
traceDurationStart(Category.File, unit.source.name)
291+
else TracedEventId.Empty
289292
}
290293

291294
override def afterUnit(event: TracedEventId): Unit = {
292295
assert(mainThread eq Thread.currentThread())
293296
if chromeTrace != null then
294-
val now = System.nanoTime()
295297
traceDurationEnd(Category.File, event)
296-
if now > nextAfterUnitSnap then
297-
val initialSnap = RealProfiler.snapThread(0)
298-
chromeTrace.traceCounterEvent("allocBytes", "allocBytes", initialSnap.allocatedBytes, processWide = false)
299-
chromeTrace.traceCounterEvent("heapBytes", "heapBytes", initialSnap.heapBytes, processWide = true)
300-
chromeTrace.traceCounterEvent("classesLoaded", "classesLoaded", initialSnap.totalClassesLoaded, processWide = true)
301-
chromeTrace.traceCounterEvent("jitCompilationTime", "jitCompilationTime", initialSnap.totalJITCompilationTime, processWide = true)
302-
chromeTrace.traceCounterEvent("userTime", "userTime", initialSnap.userTimeNanos, processWide = false)
303-
chromeTrace.traceCounterEvent("cpuTime", "cpuTime", initialSnap.cpuTimeNanos, processWide = false)
304-
chromeTrace.traceCounterEvent("idleTime", "idleTime", initialSnap.idleTimeNanos, processWide = false)
305-
nextAfterUnitSnap = System.nanoTime() + 10 * 1000 * 1000
298+
traceThreadSnapshotCounters()
306299
}
307300

301+
private def traceThreadSnapshotCounters(initialSnap: => ProfileSnap = RealProfiler.snapThread(0)) =
302+
if chromeTrace != null && System.nanoTime() > nextAfterUnitSnap then {
303+
val snap = initialSnap
304+
chromeTrace.traceCounterEvent("allocBytes", "allocBytes", snap.allocatedBytes, processWide = false)
305+
chromeTrace.traceCounterEvent("heapBytes", "heapBytes", snap.heapBytes, processWide = true)
306+
chromeTrace.traceCounterEvent("classesLoaded", "classesLoaded", snap.totalClassesLoaded, processWide = true)
307+
chromeTrace.traceCounterEvent("jitCompilationTime", "jitCompilationTime", snap.totalJITCompilationTime, processWide = true)
308+
chromeTrace.traceCounterEvent("userTime", "userTime", snap.userTimeNanos, processWide = false)
309+
chromeTrace.traceCounterEvent("cpuTime", "cpuTime", snap.cpuTimeNanos, processWide = false)
310+
chromeTrace.traceCounterEvent("idleTime", "idleTime", snap.idleTimeNanos, processWide = false)
311+
nextAfterUnitSnap = System.nanoTime() + 10 * 1000 * 1000
312+
}
313+
308314
override def beforeTypedDef(sym: Symbol): TracedEventId = traceDurationStart(Category.TypeCheck, symbolName(sym))
309315
override def afterTypedDef(event: TracedEventId): Unit = traceDurationEnd(Category.TypeCheck, event)
310316

@@ -316,9 +322,9 @@ private [profile] class RealProfiler(reporter : ProfileReporter)(using Context)
316322

317323
override def beforeCompletion(root: Symbol, associatedFile: => AbstractFile): (TracedEventId, String) =
318324
if chromeTrace == null
319-
then (TracedEventId.Empty, "")
325+
then EmptyCompletionEvent
320326
else
321-
val completionName= this.completionName(root, associatedFile)
327+
val completionName = this.completionName(root, associatedFile)
322328
val event = TracedEventId(associatedFile.name)
323329
chromeTrace.traceDurationEventStart(Category.Completion.name, "", colour = "thread_state_sleeping")
324330
chromeTrace.traceDurationEventStart(Category.File.name, event)
@@ -332,7 +338,6 @@ private [profile] class RealProfiler(reporter : ProfileReporter)(using Context)
332338
chromeTrace.traceDurationEventEnd(Category.File.name, event)
333339
chromeTrace.traceDurationEventEnd(Category.Completion.name, "", colour = "thread_state_sleeping")
334340

335-
336341
private inline def traceDurationStart(category: Category, inline eventName: String, colour: String = ""): TracedEventId =
337342
if chromeTrace == null
338343
then TracedEventId.Empty
@@ -342,9 +347,8 @@ private [profile] class RealProfiler(reporter : ProfileReporter)(using Context)
342347
event
343348

344349
private inline def traceDurationEnd(category: Category, event: TracedEventId, colour: String = ""): Unit =
345-
if chromeTrace != null
346-
then chromeTrace.traceDurationEventEnd(category.name, event, colour)
347-
350+
if chromeTrace != null then
351+
chromeTrace.traceDurationEventEnd(category.name, event, colour)
348352

349353
private def symbolName(sym: Symbol): String = s"${sym.showKind} ${sym.showName}"
350354
private def completionName(root: Symbol, associatedFile: AbstractFile): String =
@@ -356,15 +360,13 @@ private [profile] class RealProfiler(reporter : ProfileReporter)(using Context)
356360
s"${enclosing.javaBinaryName}::${root.name}"
357361
}
358362

359-
case class EventType(name: String)
360-
object EventType {
361-
//main thread with other tasks
362-
val MAIN: EventType = EventType("main")
363-
//other task ( background thread)
364-
val BACKGROUND: EventType = EventType("background")
365-
//total for compile
366-
val GC: EventType = EventType("GC")
367-
}
363+
enum EventType(name: String):
364+
// main thread with other tasks
365+
case MAIN extends EventType("main")
366+
// other task ( background thread)
367+
case BACKGROUND extends EventType("background")
368+
// total for compile
369+
case GC extends EventType("GC")
368370

369371
sealed trait ProfileReporter {
370372
def reportBackground(profiler: RealProfiler, threadRange: ProfileRange): Unit
@@ -418,7 +420,6 @@ class StreamProfileReporter(out:PrintWriter) extends ProfileReporter {
418420
out.println(s"${EventType.GC},$start,${data.reportTimeNs},${data.gcStartMillis}, ${data.gcEndMillis},${data.name},${data.action},${data.cause},${data.threads}")
419421
}
420422

421-
422423
override def close(profiler: RealProfiler): Unit = {
423424
out.flush()
424425
out.close()

0 commit comments

Comments
 (0)