1 /*
<lambda>null2 * Copyright 2018 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*
18 * Notes
19 *
20 * TODO (chriswailes): Support JSON output
21 */
22
23 /*
24 * Imports
25 */
26
27 import java.io.File
28 import trebuchet.model.Model
29 import trebuchet.extras.parseTrace
30 import trebuchet.util.time.*
31
32 /*
33 * Constants
34 */
35
36 /*
37 * Class Definition
38 */
39
40 /*
41 * Class Extensions
42 */
43
44 /*
45 * Helper Functions
46 */
47
48 fun measureStartup(model: Model) {
49 val startupEvents = model.getStartupEvents()
50
51 println("Found ${startupEvents.count()} startup events.")
52
53 startupEvents.forEach { startupEvent ->
54 println()
55 println("App Startup summary for ${startupEvent.name} (${startupEvent.proc.id}):")
56 println("\tStart offset: ${(startupEvent.startTime - model.beginTimestamp).secondValueToMillisecondString()}")
57 println("\tLaunch duration: ${(startupEvent.endTime - startupEvent.startTime).secondValueToMillisecondString()}")
58
59 if (startupEvent.reportFullyDrawnTime == null) {
60 println("\tRFD duration: N/A")
61 } else {
62 println("\tRFD duration: ${(startupEvent.reportFullyDrawnTime!! - startupEvent.startTime).secondValueToMillisecondString()}")
63 }
64
65 println("\tServer fork time: ${startupEvent.serverSideForkTime.secondValueToMillisecondString()}")
66 println("\tTime to first slice: ${(startupEvent.firstSliceTime - startupEvent.startTime).secondValueToMillisecondString()}")
67 println("\tUndifferentiated time: ${startupEvent.undifferentiatedTime.secondValueToMillisecondString()}")
68 println()
69 println("\tScheduling timings:")
70 startupEvent.schedTimings.toSortedMap().forEach { schedState, timing ->
71 println("\t\t${schedState.friendlyName}: ${timing.secondValueToMillisecondString()}")
72 }
73 println()
74 println("\tTop-level slice information:")
75 startupEvent.topLevelSliceInfo.toSortedMap(java.lang.String.CASE_INSENSITIVE_ORDER).forEach { sliceName, aggInfo ->
76 println("\t\t$sliceName")
77 println("\t\t\tEvent count: ${aggInfo.count}")
78 println("\t\t\tTotal duration: ${aggInfo.totalTime.secondValueToMillisecondString()}")
79 }
80 println()
81 println("\tAll slice information:")
82 startupEvent.allSlicesInfo.toSortedMap(java.lang.String.CASE_INSENSITIVE_ORDER).forEach { sliceName, aggInfo->
83 println("\t\t$sliceName")
84 println("\t\t\tEvent count: ${aggInfo.count}")
85
86 println("\t\t\tTotal duration: ${aggInfo.totalTime.secondValueToMillisecondString()}")
87
88 if (aggInfo.values.count() > 0) {
89 println("\t\t\tEvent details:")
90 aggInfo.values.toSortedMap(java.lang.String.CASE_INSENSITIVE_ORDER).forEach { value, (count, duration) ->
91 println("\t\t\t\t$value ${if (count > 1) "x $count " else ""}@ ${duration.secondValueToMillisecondString()}")
92 }
93 }
94 }
95 println()
96 }
97 }
98
99 /*
100 * Main Function
101 */
102
mainnull103 fun main(args: Array<String>) {
104 if (args.isEmpty()) {
105 println("Usage: StartAnalyzerKt <trace filename>")
106 return
107 }
108
109 val filename = args[0]
110
111 println("Opening `$filename`")
112 val trace = parseTrace(File(filename), verbose = false)
113
114 measureStartup(trace)
115 }