diff options
author | Felipe Leme <felipeal@google.com> | 2019-05-21 11:11:29 -0700 |
---|---|---|
committer | Felipe Leme <felipeal@google.com> | 2019-05-29 11:30:50 -0700 |
commit | bfeeb06ceb8dfd399eae4167c9b03167a8a60c20 (patch) | |
tree | 04dc0c872ccedb81cd2dd17f72eaf122fcfe4bf0 | |
parent | 6e094a8640f34b8452a9d96036f89f06304a8e75 (diff) | |
download | trebuchet-bfeeb06ceb8dfd399eae4167c9b03167a8a60c20.tar.gz |
Created a project that measure starting time of system_server services.
Test: ./gradlew :trebuchet:system-server-analyzer:run --args=/tmp/atrace-ss.txt
Test: ./gradlew :trebuchet:system-server-analyzer:run --args="/tmp/atrace-ss.txt -t 10 -o /tmp/output.csv"
Bug: 133242016
Change-Id: I7792df627a058f97d58d2cef60a0898752af9da4
-rw-r--r-- | settings.gradle | 1 | ||||
-rw-r--r-- | trebuchet/system-server-analyzer/MANIFEST.mf | 2 | ||||
-rw-r--r-- | trebuchet/system-server-analyzer/README.md | 64 | ||||
-rw-r--r-- | trebuchet/system-server-analyzer/build.gradle | 33 | ||||
-rw-r--r-- | trebuchet/system-server-analyzer/src/SystemServerAnalyzer.kt | 129 |
5 files changed, 229 insertions, 0 deletions
diff --git a/settings.gradle b/settings.gradle index 9d6bf96..62d53d5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -27,5 +27,6 @@ include 'trebuchet:analyzer' include 'trebuchet:startup-analyzer' include 'trebuchet:startup-common' include 'trebuchet:startup-summarizer' +include 'trebuchet:system-server-analyzer' include 'trebuchet:traceutils' include 'trebuchet:viewer' diff --git a/trebuchet/system-server-analyzer/MANIFEST.mf b/trebuchet/system-server-analyzer/MANIFEST.mf new file mode 100644 index 0000000..a61b3e9 --- /dev/null +++ b/trebuchet/system-server-analyzer/MANIFEST.mf @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +Main-Class: SystemServerStartupAnalyzerKt diff --git a/trebuchet/system-server-analyzer/README.md b/trebuchet/system-server-analyzer/README.md new file mode 100644 index 0000000..3ba1cea --- /dev/null +++ b/trebuchet/system-server-analyzer/README.md @@ -0,0 +1,64 @@ +# Android System Server Startup Analyzer + +This is a tool for processing systraces and summarizing how long it takes +to start `system_service` services. + +To run the tool, enter the root directory for the +Trebuchet project and use the following command template: +`./gradlew :trebuchet:system-server-analyzer:run --args="<trace_file> [-t threshold_ms] [-o output_file]"`. + +If you do not already have a trace file to analyze you can follow the steps +below: + +1.Stop `system_server`: + `adb shell stop` +2.Capture 10 seconds of tracing information using `atrace`: + `adb shell atrace -o /sdcard/atrace-ss.txt -t 10 ss` +3.In another console, restart `system_server`: + `adb shell start` +4.Pull the generate file: + `adb pull /sdcard/atrace-ss.txt` + +Below is an example of its output: + +``` +Opening `/tmp/atrace-ss.txt` +Progress: 100.00% +Parsing atrace-ss.txt took 171ms + +StartServices: 5982.37ms +StartActivityManager: 87.21ms +StartPowerManager: 5.04ms +StartLightsService: 1012.62ms +StartDisplayManager: 7.08ms +WaitForDisplay: 23.80ms +StartPackageManagerService: 3267.64ms +StartOverlayManagerService: 128.18ms +StartBatteryService: 24.33ms +StartUsageService: 29.94ms +StartRollbackManagerService: 5.24ms +InstallSystemProviders: 55.23ms +StartWindowManagerService: 148.52ms +SetWindowManagerService: 10.88ms +WindowManagerServiceOnInitReady: 18.26ms +NetworkWatchlistService: 5.87ms +StartAccessibilityManagerService: 31.93ms +MakeDisplayReady: 19.62ms +StartStorageManagerService: 7.46ms +StartLockSettingsService: 28.12ms +StartWifi: 65.78ms +StartConnectivityService: 11.89ms +StartNotificationManager: 16.70ms +StartAudioService: 37.19ms +StartUsbService: 17.25ms +StartJobScheduler: 13.70ms +StartMediaSessionService: 8.07ms +MakeLockSettingsServiceReady: 89.10ms +StartBootPhaseLockSettingsReady: 16.21ms +StartBootPhaseSystemServicesReady: 83.95ms +MakeWindowManagerServiceReady: 5.40ms +MakePowerManagerServiceReady: 14.79ms +MakePackageManagerServiceReady: 48.18ms +PhaseActivityManagerReady: 456.15ms +Other: 157.12ms +``` diff --git a/trebuchet/system-server-analyzer/build.gradle b/trebuchet/system-server-analyzer/build.gradle new file mode 100644 index 0000000..3fadfdb --- /dev/null +++ b/trebuchet/system-server-analyzer/build.gradle @@ -0,0 +1,33 @@ +/* + * Copyright 2019 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. + */ + +apply plugin: 'java' +apply plugin: 'application' +apply plugin: 'kotlin-platform-jvm' + +sourceCompatibility = 1.8 +mainClassName = "SystemServerAnalyzerKt" + +sourceSets { + main.kotlin.srcDirs += 'src' +} + +dependencies { + compile project(":core:common") + compile project(":core:model") + compile project(":trebuchet:startup-common") + compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8" +}
\ No newline at end of file diff --git a/trebuchet/system-server-analyzer/src/SystemServerAnalyzer.kt b/trebuchet/system-server-analyzer/src/SystemServerAnalyzer.kt new file mode 100644 index 0000000..1411ba3 --- /dev/null +++ b/trebuchet/system-server-analyzer/src/SystemServerAnalyzer.kt @@ -0,0 +1,129 @@ +/* + * Copyright 2019 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 (felipeal): generate .csv file + * TODO (felipeal): automatically generate atrace / restart system_server + * TODO (felipeal): add mre command-line options, like threshold value + */ + +/* + * Imports + */ + +import java.io.File +import trebuchet.model.Model +import trebuchet.extras.parseTrace +import trebuchet.model.base.Slice +import trebuchet.model.base.SliceGroup +import trebuchet.queries.slices.slices +import java.io.PrintStream + +/* + * Constants + */ + +/* + * Class Definition + */ + +/* + * Class Extensions + */ + +/* + * Helper Functions + */ + +inline fun <reified T> Slice?.ifGroup(func: (SliceGroup) -> T): T? { + if (this is SliceGroup) { + return func(this) + } + return null +} + +fun Double.durationString(): String { + return "%.3f ms".format(this * 1000) +} + +fun printLine(output: PrintStream, name: String, duration: Double, csvFormat: Boolean = false) { + if (csvFormat) { + output.println("${name};${duration * 1000}") + } else { + output.println("${name}: ${duration.durationString()}") + } +} + +fun printLine(output: PrintStream, model: SliceGroup, csvFormat: Boolean = false) { + printLine(output, model.name, model.duration, csvFormat) +} + +fun measureServiceStartup(model: Model, thresholdMs: Int = 0, output: PrintStream = System.out, csvFormat: Boolean = false, otherName: String = "Other") { + model.slices().firstOrNull { + it.name == "StartServices" && it is SliceGroup + }.ifGroup { + printLine(output, "StartServices", it.duration, csvFormat); + val childDurations = it.children.sumByDouble { service -> + if (service.duration * 1000 >= thresholdMs) { + printLine(output, service, csvFormat) + service.duration + } else { + 0.0 + } + } + printLine(output, "Other", it.duration - childDurations, csvFormat); + } +} + +/* + * Main Function + */ + +fun main(args: Array<String>) { + if (args.isEmpty()) { + println("Usage: SystemServerAnalyzerKt <trace_filename> [-t threshold_ms] [-o output_filename]") + return + } + + val input = args[0] + + println("Opening ${input}") + val trace = parseTrace(File(input), verbose = true) + + var csvFormat = false + var output = System.out + var thresholdMs = 5; + + // Parse optional arguments + var nextArg = 1 + while (nextArg < args.size) { + var arg = args[nextArg++] + var value = args[nextArg++] + when (arg) { + "-t" -> thresholdMs = value.toInt() + "-o" -> { + output = PrintStream(File(value).outputStream()) + csvFormat = true + println("Writing CSV output to ${value}") + } + else -> println("invalid option: ${arg}") + } + } + + measureServiceStartup(trace, thresholdMs, output, csvFormat) +}
\ No newline at end of file |