summaryrefslogtreecommitdiff
path: root/startop/apps
diff options
context:
space:
mode:
authorEric Holk <eholk@google.com>2019-10-11 13:03:57 -0700
committerEric Holk <eholk@google.com>2019-10-11 16:10:48 -0700
commit77743f31c89c171131bc6b70c126068b679cc368 (patch)
treef53422f742f100ea3e8ec8bf40dd7b263d7586ad /startop/apps
parent963754df145bf23b063e105721cd8d999e1bce33 (diff)
Refactor system server benchmarks
This change does a better job of separating the UI code from the benchmark running code, with the goal of enabling a non-interactive version of the benchmarks. Change-Id: Id7a673b9abca69cd9643a487f7b05f965e1f2614
Diffstat (limited to 'startop/apps')
-rw-r--r--startop/apps/test/Android.bp1
-rw-r--r--startop/apps/test/src/SystemServerBenchmarkActivity.java185
-rw-r--r--startop/apps/test/src/SystemServerBenchmarks.java205
3 files changed, 229 insertions, 162 deletions
diff --git a/startop/apps/test/Android.bp b/startop/apps/test/Android.bp
index a8063209b56f..d949f74bec70 100644
--- a/startop/apps/test/Android.bp
+++ b/startop/apps/test/Android.bp
@@ -23,6 +23,7 @@ android_app {
"src/ComplexLayoutInflationActivity.java",
"src/FrameLayoutInflationActivity.java",
"src/SystemServerBenchmarkActivity.java",
+ "src/SystemServerBenchmarks.java",
"src/TextViewInflationActivity.java",
],
sdk_version: "26", // Android O (8.0) and higher
diff --git a/startop/apps/test/src/SystemServerBenchmarkActivity.java b/startop/apps/test/src/SystemServerBenchmarkActivity.java
index c8d9fde0bdaf..75ea69b81e02 100644
--- a/startop/apps/test/src/SystemServerBenchmarkActivity.java
+++ b/startop/apps/test/src/SystemServerBenchmarkActivity.java
@@ -31,13 +31,25 @@ import android.widget.Button;
import android.widget.GridLayout;
import android.widget.TextView;
+public class SystemServerBenchmarkActivity extends Activity implements BenchmarkRunner {
+ private GridLayout benchmarkList;
-class Benchmark {
- // Time limit to run benchmarks in seconds
- public static final int TIME_LIMIT = 5;
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.system_server_benchmark_page);
+
+ benchmarkList = findViewById(R.id.benchmark_list);
- public Benchmark(ViewGroup parent, CharSequence name, Runnable thunk) {
- Context context = parent.getContext();
+ SystemServerBenchmarks.initializeBenchmarks(this, this);
+ }
+
+ /**
+ * Adds a benchmark to the set to run.
+ *
+ * @param name A short name that shows up in the UI or benchmark results
+ */
+ public void addBenchmark(CharSequence name, Runnable thunk) {
+ Context context = benchmarkList.getContext();
Button button = new Button(context);
TextView mean = new TextView(context);
TextView stdev = new TextView(context);
@@ -50,165 +62,14 @@ class Benchmark {
mean.setText("Running...");
stdev.setText("");
- new AsyncTask() {
- double resultMean = 0;
- double resultStdev = 0;
-
- @Override
- protected Object doInBackground(Object... _args) {
- long startTime = System.nanoTime();
- int count = 0;
-
- // Run benchmark
- while (true) {
- long elapsed = -System.nanoTime();
- thunk.run();
- elapsed += System.nanoTime();
-
- count++;
- double elapsedVariance = (double) elapsed - resultMean;
- resultMean += elapsedVariance / count;
- resultStdev += elapsedVariance * ((double) elapsed - resultMean);
-
- if (System.nanoTime() - startTime > TIME_LIMIT * 1e9) {
- break;
- }
- }
- resultStdev = Math.sqrt(resultStdev / (count - 1));
-
- return null;
- }
-
- @Override
- protected void onPostExecute(Object _result) {
- mean.setText(String.format("%.3f", resultMean / 1e6));
- stdev.setText(String.format("%.3f", resultStdev / 1e6));
- }
- }.execute(new Object());
- });
-
- parent.addView(button);
- parent.addView(mean);
- parent.addView(stdev);
- }
-}
-
-public class SystemServerBenchmarkActivity extends Activity {
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.system_server_benchmark_page);
-
- GridLayout benchmarkList = findViewById(R.id.benchmark_list);
-
- new Benchmark(benchmarkList, "Empty", () -> {
- });
-
- new Benchmark(benchmarkList, "CPU Intensive (1 thread)", () -> {
- CPUIntensive.doSomeWork(1);
- });
-
- new Benchmark(benchmarkList, "CPU Intensive (2 thread)", () -> {
- CPUIntensive.doSomeWork(2);
- });
-
- new Benchmark(benchmarkList, "CPU Intensive (4 thread)", () -> {
- CPUIntensive.doSomeWork(4);
- });
-
- new Benchmark(benchmarkList, "CPU Intensive (8 thread)", () -> {
- CPUIntensive.doSomeWork(8);
- });
-
- PackageManager pm = getPackageManager();
- new Benchmark(benchmarkList, "getInstalledApplications", () -> {
- pm.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY);
- });
-
- new Benchmark(benchmarkList, "getInstalledPackages", () -> {
- pm.getInstalledPackages(PackageManager.GET_ACTIVITIES);
- });
-
- new Benchmark(benchmarkList, "getPackageInfo", () -> {
- try {
- pm.getPackageInfo("com.android.startop.test", 0);
- } catch (NameNotFoundException e) {
- throw new RuntimeException(e);
- }
- });
-
- new Benchmark(benchmarkList, "getApplicationInfo", () -> {
- try {
- pm.getApplicationInfo("com.android.startop.test", 0);
- } catch (NameNotFoundException e) {
- throw new RuntimeException(e);
- }
- });
-
- try {
- ApplicationInfo app = pm.getApplicationInfo("com.android.startop.test", 0);
- new Benchmark(benchmarkList, "getResourcesForApplication", () -> {
- try {
- pm.getResourcesForApplication(app);
- } catch (NameNotFoundException e) {
- throw new RuntimeException(e);
- }
- });
-
- new Benchmark(benchmarkList, "getPackagesForUid", () -> {
- pm.getPackagesForUid(app.uid);
+ SystemServerBenchmarks.runBenchmarkInBackground(thunk, (resultMean, resultStdev) -> {
+ mean.setText(String.format("%.3f", resultMean / 1e6));
+ stdev.setText(String.format("%.3f", resultStdev / 1e6));
});
- } catch (NameNotFoundException e) {
- throw new RuntimeException(e);
- }
-
- ComponentName component = new ComponentName(this, this.getClass());
- new Benchmark(benchmarkList, "getActivityInfo", () -> {
- try {
- pm.getActivityInfo(component, PackageManager.GET_META_DATA);
- } catch (NameNotFoundException e) {
- throw new RuntimeException(e);
- }
- });
-
- new Benchmark(benchmarkList, "getLaunchIntentForPackage", () -> {
- pm.getLaunchIntentForPackage("com.android.startop.test");
- });
-
- new Benchmark(benchmarkList, "getPackageUid", () -> {
- try {
- pm.getPackageUid("com.android.startop.test", 0);
- } catch (NameNotFoundException e) {
- throw new RuntimeException(e);
- }
- });
-
- new Benchmark(benchmarkList, "checkPermission", () -> {
- // Check for the first permission I could find.
- pm.checkPermission("android.permission.SEND_SMS", "com.android.startop.test");
- });
-
- new Benchmark(benchmarkList, "checkSignatures", () -> {
- // Compare with settings, since settings is on both AOSP and Master builds
- pm.checkSignatures("com.android.settings", "com.android.startop.test");
- });
-
- Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
- new Benchmark(benchmarkList, "queryBroadcastReceivers", () -> {
- pm.queryBroadcastReceivers(intent, 0);
- });
-
- new Benchmark(benchmarkList, "hasSystemFeature", () -> {
- pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
- });
-
- new Benchmark(benchmarkList, "resolveService", () -> {
- pm.resolveService(intent, 0);
- });
-
- ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
- new Benchmark(benchmarkList, "getRunningAppProcesses", () -> {
- am.getRunningAppProcesses();
});
+ benchmarkList.addView(button);
+ benchmarkList.addView(mean);
+ benchmarkList.addView(stdev);
}
}
diff --git a/startop/apps/test/src/SystemServerBenchmarks.java b/startop/apps/test/src/SystemServerBenchmarks.java
new file mode 100644
index 000000000000..818f1788335e
--- /dev/null
+++ b/startop/apps/test/src/SystemServerBenchmarks.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+package com.android.startop.test;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.AsyncTask;
+
+/**
+ * An interface for running benchmarks and collecting results. Used so we can have both an
+ * interactive runner and a non-interactive runner.
+ */
+interface BenchmarkRunner {
+ void addBenchmark(CharSequence name, Runnable thunk);
+}
+
+interface ResultListener {
+ /**
+ * Called when a benchmark result is ready
+ *
+ * @param mean The average iteration time in nanoseconds
+ * @param stdev The standard deviation of iteration times in nanoseconds
+ */
+ void onResult(double mean, double stdev);
+}
+
+class SystemServerBenchmarks {
+ // Time limit to run benchmarks in seconds
+ public static final int TIME_LIMIT = 5;
+
+ static void initializeBenchmarks(BenchmarkRunner benchmarks, Activity parent) {
+ benchmarks.addBenchmark("Empty", () -> {
+ });
+
+ benchmarks.addBenchmark("CPU Intensive (1 thread)", () -> {
+ CPUIntensive.doSomeWork(1);
+ });
+
+ benchmarks.addBenchmark("CPU Intensive (2 thread)", () -> {
+ CPUIntensive.doSomeWork(2);
+ });
+
+ benchmarks.addBenchmark("CPU Intensive (4 thread)", () -> {
+ CPUIntensive.doSomeWork(4);
+ });
+
+ benchmarks.addBenchmark("CPU Intensive (8 thread)", () -> {
+ CPUIntensive.doSomeWork(8);
+ });
+
+ PackageManager pm = parent.getPackageManager();
+ benchmarks.addBenchmark("getInstalledApplications", () -> {
+ pm.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY);
+ });
+
+ benchmarks.addBenchmark("getInstalledPackages", () -> {
+ pm.getInstalledPackages(PackageManager.GET_ACTIVITIES);
+ });
+
+ benchmarks.addBenchmark("getPackageInfo", () -> {
+ try {
+ pm.getPackageInfo("com.android.startop.test", 0);
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ benchmarks.addBenchmark("getApplicationInfo", () -> {
+ try {
+ pm.getApplicationInfo("com.android.startop.test", 0);
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ try {
+ ApplicationInfo app = pm.getApplicationInfo("com.android.startop.test", 0);
+ benchmarks.addBenchmark("getResourcesForApplication", () -> {
+ try {
+ pm.getResourcesForApplication(app);
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ benchmarks.addBenchmark("getPackagesForUid", () -> {
+ pm.getPackagesForUid(app.uid);
+ });
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+
+ ComponentName component = new ComponentName(parent, parent.getClass());
+ benchmarks.addBenchmark("getActivityInfo", () -> {
+ try {
+ pm.getActivityInfo(component, PackageManager.GET_META_DATA);
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ benchmarks.addBenchmark("getLaunchIntentForPackage", () -> {
+ pm.getLaunchIntentForPackage("com.android.startop.test");
+ });
+
+ benchmarks.addBenchmark("getPackageUid", () -> {
+ try {
+ pm.getPackageUid("com.android.startop.test", 0);
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ benchmarks.addBenchmark("checkPermission", () -> {
+ // Check for the first permission I could find.
+ pm.checkPermission("android.permission.SEND_SMS", "com.android.startop.test");
+ });
+
+ benchmarks.addBenchmark("checkSignatures", () -> {
+ // Compare with settings, since settings is on both AOSP and Master builds
+ pm.checkSignatures("com.android.settings", "com.android.startop.test");
+ });
+
+ Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
+ benchmarks.addBenchmark("queryBroadcastReceivers", () -> {
+ pm.queryBroadcastReceivers(intent, 0);
+ });
+
+ benchmarks.addBenchmark("hasSystemFeature", () -> {
+ pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
+ });
+
+ benchmarks.addBenchmark("resolveService", () -> {
+ pm.resolveService(intent, 0);
+ });
+
+ ActivityManager am = (ActivityManager) parent.getSystemService(Context.ACTIVITY_SERVICE);
+ benchmarks.addBenchmark("getRunningAppProcesses", () -> {
+ am.getRunningAppProcesses();
+ });
+ }
+
+ /**
+ * A helper method for benchark runners to actually run the benchmark and gather stats
+ *
+ * @param thunk The code whose performance we want to measure
+ * @param reporter What to do with the results
+ */
+ static void runBenchmarkInBackground(Runnable thunk, ResultListener reporter) {
+ new AsyncTask() {
+ double resultMean = 0;
+ double resultStdev = 0;
+
+ @Override
+ protected Object doInBackground(Object... _args) {
+ long startTime = System.nanoTime();
+ int count = 0;
+
+ // Run benchmark
+ while (true) {
+ long elapsed = -System.nanoTime();
+ thunk.run();
+ elapsed += System.nanoTime();
+
+ count++;
+ double elapsedVariance = (double) elapsed - resultMean;
+ resultMean += elapsedVariance / count;
+ resultStdev += elapsedVariance * ((double) elapsed - resultMean);
+
+ if (System.nanoTime() - startTime > TIME_LIMIT * 1e9) {
+ break;
+ }
+ }
+ resultStdev = Math.sqrt(resultStdev / (count - 1));
+
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Object _result) {
+ reporter.onResult(resultMean, resultStdev);
+ }
+ }.execute(new Object());
+ }
+}