aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Leme <felipeal@google.com>2019-05-21 11:11:29 -0700
committerFelipe Leme <felipeal@google.com>2019-05-29 11:30:50 -0700
commitbfeeb06ceb8dfd399eae4167c9b03167a8a60c20 (patch)
tree04dc0c872ccedb81cd2dd17f72eaf122fcfe4bf0
parent6e094a8640f34b8452a9d96036f89f06304a8e75 (diff)
downloadtrebuchet-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.gradle1
-rw-r--r--trebuchet/system-server-analyzer/MANIFEST.mf2
-rw-r--r--trebuchet/system-server-analyzer/README.md64
-rw-r--r--trebuchet/system-server-analyzer/build.gradle33
-rw-r--r--trebuchet/system-server-analyzer/src/SystemServerAnalyzer.kt129
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