/* * Copyright 2018 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Notes * * TODO (chriswailes): Support JSON output */ /* * Imports */ import java.io.File import trebuchet.model.Model import trebuchet.extras.parseTrace import trebuchet.util.time.* /* * Constants */ /* * Class Definition */ /* * Class Extensions */ /* * Helper Functions */ fun measureStartup(model: Model) { val startupEvents = model.getStartupEvents() println("Found ${startupEvents.count()} startup events.") startupEvents.forEach { startupEvent -> println() println("App Startup summary for ${startupEvent.name} (${startupEvent.proc.id}):") println("\tStart offset: ${(startupEvent.startTime - model.beginTimestamp).secondValueToMillisecondString()}") println("\tLaunch duration: ${(startupEvent.endTime - startupEvent.startTime).secondValueToMillisecondString()}") if (startupEvent.reportFullyDrawnTime == null) { println("\tRFD duration: N/A") } else { println("\tRFD duration: ${(startupEvent.reportFullyDrawnTime!! - startupEvent.startTime).secondValueToMillisecondString()}") } println("\tServer fork time: ${startupEvent.serverSideForkTime.secondValueToMillisecondString()}") println("\tTime to first slice: ${(startupEvent.firstSliceTime - startupEvent.startTime).secondValueToMillisecondString()}") println("\tUndifferentiated time: ${startupEvent.undifferentiatedTime.secondValueToMillisecondString()}") println() println("\tScheduling timings:") startupEvent.schedTimings.toSortedMap().forEach { schedState, timing -> println("\t\t${schedState.friendlyName}: ${timing.secondValueToMillisecondString()}") } println() println("\tTop-level slice information:") startupEvent.topLevelSliceInfo.toSortedMap(java.lang.String.CASE_INSENSITIVE_ORDER).forEach { sliceName, aggInfo -> println("\t\t$sliceName") println("\t\t\tEvent count: ${aggInfo.count}") println("\t\t\tTotal duration: ${aggInfo.totalTime.secondValueToMillisecondString()}") } println() println("\tAll slice information:") startupEvent.allSlicesInfo.toSortedMap(java.lang.String.CASE_INSENSITIVE_ORDER).forEach { sliceName, aggInfo-> println("\t\t$sliceName") println("\t\t\tEvent count: ${aggInfo.count}") println("\t\t\tTotal duration: ${aggInfo.totalTime.secondValueToMillisecondString()}") if (aggInfo.values.count() > 0) { println("\t\t\tEvent details:") aggInfo.values.toSortedMap(java.lang.String.CASE_INSENSITIVE_ORDER).forEach { value, (count, duration) -> println("\t\t\t\t$value ${if (count > 1) "x $count " else ""}@ ${duration.secondValueToMillisecondString()}") } } } println() } } /* * Main Function */ fun main(args: Array) { if (args.isEmpty()) { println("Usage: StartAnalyzerKt ") return } val filename = args[0] println("Opening `$filename`") val trace = parseTrace(File(filename), verbose = false) measureStartup(trace) }