@@ -3,8 +3,11 @@ package scala.reflect.internal.util
3
3
import java .io .Closeable
4
4
import java .lang .management .ManagementFactory
5
5
import java .nio .file .{Files , Path }
6
+ import java .util
6
7
import java .util .concurrent .TimeUnit
7
8
9
+ import scala .collection .mutable
10
+
8
11
object ChromeTrace {
9
12
10
13
private object EventType {
@@ -27,24 +30,29 @@ object ChromeTrace {
27
30
final class ChromeTrace (f : Path ) extends Closeable {
28
31
import ChromeTrace .EventType
29
32
private val traceWriter = Files .newBufferedWriter(f)
33
+ private val context = mutable.ArrayStack [JsonContext ](TopContext )
34
+ private val tidCache = new ThreadLocal [String ]() {
35
+ override def initialValue (): String = Thread .currentThread().getId.formatted(" %05d" )
36
+ }
30
37
objStart()
31
38
fld(" traceEvents" )
39
+ context.push(ValueContext )
32
40
arrStart()
33
41
traceWriter.write(" \n " )
34
42
35
- private val pid = ManagementFactory .getRuntimeMXBean().getName()
43
+ private val pid = ManagementFactory .getRuntimeMXBean().getName().replaceAll( " @.* " , " " )
36
44
37
45
override def close (): Unit = {
38
- traceWriter.append(" \n " )
39
46
arrEnd()
40
47
objEnd()
48
+ context.pop()
49
+ tidCache.remove()
41
50
traceWriter.close()
42
51
}
43
52
44
53
def traceDurationEvent (name : String , startNanos : Long , durationNanos : Long , tid : String = this .tid()): Unit = {
45
54
val durationMicros = nanosToMicros(durationNanos)
46
55
val startMicros = nanosToMicros(startNanos)
47
- commaIfFirst()
48
56
objStart()
49
57
str(" cat" , " scalac" )
50
58
str(" name" , name)
@@ -58,7 +66,6 @@ final class ChromeTrace(f: Path) extends Closeable {
58
66
}
59
67
60
68
def traceCounterEvent (name : String , counterName : String , count : Long ): Unit = {
61
- commaIfFirst()
62
69
objStart()
63
70
str(" cat" , " scalac" )
64
71
str(" name" , name)
@@ -78,7 +85,6 @@ final class ChromeTrace(f: Path) extends Closeable {
78
85
def traceDurationEventEnd (name : String , colour : String = " " ): Unit = traceAsyncEvent(EventType .Finished , name, colour)
79
86
80
87
private def traceAsyncEvent (eventType : String , name : String , colour : String ): Unit = {
81
- commaIfFirst()
82
88
objStart()
83
89
str(" cat" , " scalac" )
84
90
str(" name" , name)
@@ -93,20 +99,21 @@ final class ChromeTrace(f: Path) extends Closeable {
93
99
traceWriter.write(" \n " )
94
100
}
95
101
96
- private def tid () = Thread .currentThread().getId.toString
102
+ private def tid (): String = tidCache.get()
97
103
98
104
private def nanosToMicros (t : Long ): Long = TimeUnit .NANOSECONDS .toMicros(t)
99
105
100
106
private def microTime (): Long = nanosToMicros(System .nanoTime())
101
107
102
- private def commaIfFirst () : Unit = {
103
- if (firstEvent) firstEvent = false else traceWriter.write( " , " )
104
- }
105
-
106
- private var firstEvent = true
108
+ sealed abstract class JsonContext
109
+ case class ArrayContext ( var first : Boolean ) extends JsonContext
110
+ case class ObjectContext ( var first : Boolean ) extends JsonContext
111
+ case object ValueContext extends JsonContext
112
+ case object TopContext extends JsonContext
107
113
108
114
private def str (name : String , value : String ): Unit = {
109
115
fld(name)
116
+ traceWriter.write(" \" " )
110
117
traceWriter.write(value) // This assumes no escaping is needed
111
118
traceWriter.write(" \" " )
112
119
}
@@ -115,15 +122,40 @@ final class ChromeTrace(f: Path) extends Closeable {
115
122
traceWriter.write(String .valueOf(value))
116
123
traceWriter.write(" " )
117
124
}
118
- private def objStart (): Unit = traceWriter.write(" {" )
119
- private def objEnd (): Unit = traceWriter.write(" }" )
120
- private def arrStart (): Unit = traceWriter.write(" [" )
121
- private def arrEnd (): Unit = traceWriter.write(" ]" )
125
+ private def objStart (): Unit = {
126
+ context.top match {
127
+ case ac @ ArrayContext (first) =>
128
+ if (first) ac.first = false
129
+ else traceWriter.write(" ," )
130
+ case _ =>
131
+ }
132
+ context.push(ObjectContext (true ))
133
+ traceWriter.write(" {" )
134
+ }
135
+ private def objEnd (): Unit = {
136
+ traceWriter.write(" }" )
137
+ context.pop()
138
+ }
139
+ private def arrStart (): Unit = {
140
+ traceWriter.write(" [" )
141
+ context.push(ArrayContext (true ))
142
+ }
143
+ private def arrEnd (): Unit = {
144
+ traceWriter.write(" ]" )
145
+ context.pop()
146
+ }
122
147
123
148
private def fld (name : String ) = {
149
+ context.top match {
150
+ case oc @ ObjectContext (first) =>
151
+ if (first) oc.first = false
152
+ else traceWriter.write(" ," )
153
+ case context =>
154
+ throw new IllegalStateException (" Wrong context: " + context)
155
+ }
124
156
traceWriter.write(" \" " )
125
157
traceWriter.write(name)
126
158
traceWriter.write(" \" " )
127
- traceWriter.write(" : " )
159
+ traceWriter.write(" :" )
128
160
}
129
161
}
0 commit comments