Skip to content

Commit be989fd

Browse files
committed
Put the completion back on the same slice as the main thread, more concise output
1 parent 22a1f22 commit be989fd

File tree

3 files changed

+53
-65
lines changed

3 files changed

+53
-65
lines changed

src/compiler/scala/tools/nsc/profile/Profiler.scala

Lines changed: 49 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -113,52 +113,52 @@ private [profile] object RealProfiler {
113113
val threadMx = ExtendedThreadMxBean.proxy
114114
if (threadMx.isThreadCpuTimeSupported) threadMx.setThreadCpuTimeEnabled(true)
115115
private val idGen = new AtomicInteger()
116+
private val baselineSnap = snapThread(0)
117+
116118
lazy val allPlugins = ServiceLoader.load(classOf[ProfilerPlugin]).iterator().asScala.toList
119+
120+
private[profile] def snapThread( idleTimeNanos:Long): ProfileSnap = {
121+
val current = Thread.currentThread()
122+
val allocatedBytes = threadMx.getThreadAllocatedBytes(Thread.currentThread().getId)
123+
ProfileSnap(
124+
threadId = current.getId,
125+
threadName = current.getName,
126+
snapTimeNanos = System.nanoTime(),
127+
idleTimeNanos = idleTimeNanos,
128+
cpuTimeNanos = threadMx.getCurrentThreadCpuTime,
129+
userTimeNanos = threadMx.getCurrentThreadUserTime,
130+
allocatedBytes = allocatedBytes,
131+
heapBytes = readHeapUsage(),
132+
totalClassesLoaded = classLoaderMx.getTotalLoadedClassCount,
133+
totalJITCompilationTime = compileMx.getTotalCompilationTime
134+
)
135+
}
136+
private def readHeapUsage() = RealProfiler.memoryMx.getHeapMemoryUsage.getUsed
117137
}
118138

119139
private [profile] class RealProfiler(reporter : ProfileReporter, val settings: Settings) extends Profiler with NotificationListener {
120140
private val mainThread = Thread.currentThread()
141+
val id = RealProfiler.idGen.incrementAndGet()
121142
val tracePath = {
122143
if (settings.YprofileDestination.isSetByUser) new File(new java.io.File(settings.YprofileDestination.value)).changeExtension("trace").jfile.toPath
123144
else Files.createTempFile("scalac-", ".trace")
124145
}
125146
private val chromeTrace = new ChromeTrace(tracePath)
126-
chromeTrace.traceAsyncEventStart("scalac-" + mainThread.getId, mainThread.getId, "0")
147+
chromeTrace.traceAsyncEventStart("scalac-" + id, id, "0")
127148

128149
def completeBackground(threadRange: ProfileRange): Unit = {
129150
reporter.reportBackground(this, threadRange)
130151
}
131152

132153
def outDir = settings.outputDirs.getSingleOutput.getOrElse(settings.outputDirs.outputs.head._2.file).toString
133154

134-
val id = RealProfiler.idGen.incrementAndGet()
135155
RealProfiler.gcMx foreach {
136156
case emitter: NotificationEmitter => emitter.addNotificationListener(this, null, null)
137157
case gc => println(s"Cant connect gcListener to ${gc.getClass}")
138158
}
139159

140160
val active = RealProfiler.allPlugins map (_.generate(this, settings))
141161

142-
143-
private[profile] def snapThread( idleTimeNanos:Long): ProfileSnap = {
144-
import RealProfiler._
145-
val current = Thread.currentThread()
146-
val allocatedBytes = threadMx.getThreadAllocatedBytes(Thread.currentThread().getId)
147-
ProfileSnap(
148-
threadId = current.getId,
149-
threadName = current.getName,
150-
snapTimeNanos = System.nanoTime(),
151-
idleTimeNanos = idleTimeNanos,
152-
cpuTimeNanos = threadMx.getCurrentThreadCpuTime,
153-
userTimeNanos = threadMx.getCurrentThreadUserTime,
154-
allocatedBytes = allocatedBytes,
155-
heapBytes = readHeapUsage(),
156-
totalClassesLoaded = classLoaderMx.getTotalLoadedClassCount,
157-
totalJITCompilationTime = compileMx.getTotalCompilationTime
158-
)
159-
}
160-
private def readHeapUsage() = RealProfiler.memoryMx.getHeapMemoryUsage.getUsed
161-
162162
private def doGC: Unit = {
163163
System.gc()
164164
System.runFinalization()
@@ -179,7 +179,7 @@ private [profile] class RealProfiler(reporter : ProfileReporter, val settings: S
179179
val startNanos = gcEvent.endNanos - durationNanos
180180
chromeTrace.traceDurationEvent(gcEvent.name, startNanos, durationNanos, GcThreadId)
181181
}
182-
chromeTrace.traceAsyncEventEnd("scalac-" + mainThread.getId, 0, "0")
182+
chromeTrace.traceAsyncEventEnd("scalac-" + id, 0, "0")
183183

184184
println("Trace file: " + tracePath)
185185
chromeTrace.close()
@@ -215,97 +215,84 @@ private [profile] class RealProfiler(reporter : ProfileReporter, val settings: S
215215

216216
override def beforePhase(phase: Phase): ProfileSnap = {
217217
assert(mainThread eq Thread.currentThread())
218-
chromeTrace.traceAsyncEventStart(phase.name, mainThread.getId, "0")
218+
chromeTrace.traceAsyncEventStart(phase.name, id, "0")
219219
if (settings.YprofileRunGcBetweenPhases.containsPhase(phase))
220220
doGC
221221
if (settings.YprofileExternalTool.containsPhase(phase)) {
222222
println("Profile hook start")
223223
ExternalToolHook.before()
224224
}
225225
active foreach {_.beforePhase(phase)}
226-
val snap = snapThread(0)
227-
if (phase.prev eq null) baseline = snap
228-
snap
226+
RealProfiler.snapThread(0)
229227
}
230228

231229
override def afterPhase(phase: Phase, snapBefore: ProfileSnap): Unit = {
232230
assert(mainThread eq Thread.currentThread())
233-
val initialSnap = snapThread(0)
231+
val initialSnap = RealProfiler.snapThread(0)
234232
active foreach {_.afterPhase(phase)}
235233
if (settings.YprofileExternalTool.containsPhase(phase)) {
236234
println("Profile hook stop")
237235
ExternalToolHook.after()
238236
}
239237
val finalSnap = if (settings.YprofileRunGcBetweenPhases.containsPhase(phase)) {
240238
doGC
241-
initialSnap.updateHeap(readHeapUsage())
239+
initialSnap.updateHeap(RealProfiler.readHeapUsage())
242240
} else initialSnap
243-
chromeTrace.traceAsyncEventEnd(phase.name, mainThread.getId, "0")
241+
chromeTrace.traceAsyncEventEnd(phase.name, id, "-GC")
244242

245243
reporter.reportForeground(this, ProfileRange(snapBefore, finalSnap, phase, "", 0, Thread.currentThread))
246244
}
247245

248246
override def beforeUnit(phase: Phase, file: AbstractFile): ProfileSnap = {
249247
assert(mainThread eq Thread.currentThread())
250-
chromeTrace.traceAsyncEventStart(file.name, mainThread.getId, "0")
251-
snapThread(0)
248+
chromeTrace.traceAsyncEventStart(file.name, id, "0")
249+
RealProfiler.snapThread(0)
252250
}
253251

254252
override def afterUnit(phase: Phase, file: AbstractFile, snapBefore: ProfileSnap): Unit = {
255253
assert(mainThread eq Thread.currentThread())
256-
val initialSnap = snapThread(0)
257-
chromeTrace.traceAsyncEventEnd(file.name, mainThread.getId, "0")
258-
chromeTrace.traceCounterEvent("allocBytes", "allocBytes", initialSnap.allocatedBytes - this.baseline.allocatedBytes)
259-
chromeTrace.traceCounterEvent("heapBytes", "heapBytes", initialSnap.heapBytes - this.baseline.heapBytes)
260-
chromeTrace.traceCounterEvent("classesLoaded", "classesLoaded", initialSnap.totalClassesLoaded - this.baseline.totalClassesLoaded)
261-
chromeTrace.traceCounterEvent("jitCompilationTime", "jitCompilationTime", initialSnap.totalJITCompilationTime - this.baseline.totalJITCompilationTime)
262-
chromeTrace.traceCounterEvent("userTime", "userTime", initialSnap.userTimeNanos - this.baseline.userTimeNanos)
263-
chromeTrace.traceCounterEvent("cpuTime", "cpuTime", initialSnap.cpuTimeNanos - this.baseline.cpuTimeNanos)
264-
chromeTrace.traceCounterEvent("idleTime", "idleTime", initialSnap.idleTimeNanos - this.baseline.idleTimeNanos)
254+
val initialSnap = RealProfiler.snapThread(0)
255+
chromeTrace.traceAsyncEventEnd(file.name, id, "0")
256+
chromeTrace.traceCounterEvent("allocBytes", "allocBytes", initialSnap.allocatedBytes - RealProfiler.baselineSnap.allocatedBytes)
257+
chromeTrace.traceCounterEvent("heapBytes", "heapBytes", initialSnap.heapBytes - RealProfiler.baselineSnap.heapBytes)
258+
chromeTrace.traceCounterEvent("classesLoaded", "classesLoaded", initialSnap.totalClassesLoaded - RealProfiler.baselineSnap.totalClassesLoaded)
259+
chromeTrace.traceCounterEvent("jitCompilationTime", "jitCompilationTime", initialSnap.totalJITCompilationTime - RealProfiler.baselineSnap.totalJITCompilationTime)
260+
chromeTrace.traceCounterEvent("userTime", "userTime", initialSnap.userTimeNanos - RealProfiler.baselineSnap.userTimeNanos)
261+
chromeTrace.traceCounterEvent("cpuTime", "cpuTime", initialSnap.cpuTimeNanos - RealProfiler.baselineSnap.cpuTimeNanos)
262+
chromeTrace.traceCounterEvent("idleTime", "idleTime", initialSnap.idleTimeNanos - RealProfiler.baselineSnap.idleTimeNanos)
265263
}
266264

267-
private var baseline: ProfileSnap = _
268-
269-
private val completingStack = new mutable.ArrayStack[Global#Symbol]
270-
private val stringsOf = (0 to 128).map(_.toString).toArray
271-
def intToString(i: Int) = if (i < 128) stringsOf(i) else i.toString
272-
273-
private def traceId = if (completingStack.isEmpty) mainThread.getId else mainThread.getId << 32 | (completingStack.top.id.toLong & 0xffffffffL)
274265
override def beforeTypedImplDef(sym: Global#Symbol): Unit = {
275-
chromeTrace.traceAsyncEventStart(sym.rawname.toString, traceId, intToString(completingStack.length))
266+
chromeTrace.traceAsyncEventStart(sym.rawname.toString, id, "")
276267
}
277268
override def afterTypedImplDef(sym: Global#Symbol): Unit = {
278-
chromeTrace.traceAsyncEventEnd(sym.rawname.toString, traceId, intToString(completingStack.length))
269+
chromeTrace.traceAsyncEventEnd(sym.rawname.toString, id, "")
279270
}
280271

281272
override def beforeImplicitSearch(pt: Global#Symbol): Unit = {
282-
chromeTrace.traceAsyncEventStart("<implicit> " + pt.rawname, traceId, intToString(completingStack.length), colour = "yellow")
273+
chromeTrace.traceAsyncEventStart("?[" + pt.rawname + "]", id, "", colour = "yellow")
283274
}
284275

285276
override def afterImplicitSearch(pt: Global#Symbol): Unit = {
286-
chromeTrace.traceAsyncEventEnd("<implicit> " + pt.rawname, traceId, intToString(completingStack.length), colour = "yellow")
277+
chromeTrace.traceAsyncEventEnd("?[" + pt.rawname + "]", id, "", colour = "yellow")
287278
}
288279

289280
override def beforeMacroExpansion(macroSym: Global#Symbol): Unit = {
290-
chromeTrace.traceAsyncEventStart("<macro> " + macroSym.rawname, traceId, intToString(completingStack.length), colour = "olive")
281+
chromeTrace.traceAsyncEventStart("«" + macroSym.rawname + "»", id, "", colour = "olive")
291282
}
292283

293284
override def afterMacroExpansion(macroSym: Global#Symbol): Unit = {
294-
chromeTrace.traceAsyncEventEnd("<macro> " + macroSym.rawname, traceId, intToString(completingStack.length), colour = "olive")
285+
chromeTrace.traceAsyncEventEnd("«" + macroSym.rawname + "»", id, "", colour = "olive")
295286
}
296287

297288
override def beforeCompletion(root: Global#Symbol): Unit = {
298-
chromeTrace.traceAsyncEventStart("<wait>", traceId, intToString(completingStack.length), colour = "thread_state_sleeping")
299-
completingStack.push(root)
300-
chromeTrace.traceAsyncEventStart("<completion>", traceId, intToString(completingStack.length))
301-
chromeTrace.traceAsyncEventStart(root.rawname.toString, traceId, intToString(completingStack.length))
289+
chromeTrace.traceAsyncEventStart("", id, "", colour = "thread_state_sleeping")
290+
chromeTrace.traceAsyncEventStart(root.rawname.toString, id, "")
302291
}
303292

304293
override def afterCompletion(root: Global#Symbol): Unit = {
305-
chromeTrace.traceAsyncEventEnd(root.rawname.toString, traceId, intToString(completingStack.length))
306-
chromeTrace.traceAsyncEventEnd("<completion>", traceId, intToString(completingStack.length))
307-
completingStack.pop()
308-
chromeTrace.traceAsyncEventEnd("<wait>", traceId, intToString(completingStack.length))
294+
chromeTrace.traceAsyncEventEnd(root.rawname.toString, id, "")
295+
chromeTrace.traceAsyncEventEnd("", id, "", colour = "thread_state_sleeping")
309296
}
310297
}
311298

src/compiler/scala/tools/nsc/profile/ThreadPoolFactory.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ object ThreadPoolFactory {
8686
val data = new ThreadProfileData
8787
localData.set(data)
8888

89-
val profileStart = profiler.snapThread(0)
89+
val profileStart = RealProfiler.snapThread(0)
9090
try worker.run finally {
91-
val snap = profiler.snapThread(data.idleNs)
91+
val snap = RealProfiler.snapThread(data.idleNs)
9292
val threadRange = ProfileRange(profileStart, snap, phase, shortId, data.taskCount, Thread.currentThread())
9393
profiler.completeBackground(threadRange)
9494
}

src/reflect/scala/reflect/internal/util/ChromeTrace.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ final class ChromeTrace(f: Path) extends Closeable {
2727
import ChromeTrace.EventType
2828
private val traceWriter = Files.newBufferedWriter(f)
2929
traceWriter.write("""{"traceEvents": [""")
30+
traceWriter.write("\n")
3031

3132
override def close(): Unit = {
32-
traceWriter.append("]}")
33+
traceWriter.append("\n]}")
3334
traceWriter.close()
3435
}
3536

0 commit comments

Comments
 (0)