diff options
author | Eric Holk <eholk@google.com> | 2019-10-11 13:03:57 -0700 |
---|---|---|
committer | Eric Holk <eholk@google.com> | 2019-10-11 16:10:48 -0700 |
commit | 77743f31c89c171131bc6b70c126068b679cc368 (patch) | |
tree | f53422f742f100ea3e8ec8bf40dd7b263d7586ad /startop/apps | |
parent | 963754df145bf23b063e105721cd8d999e1bce33 (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.bp | 1 | ||||
-rw-r--r-- | startop/apps/test/src/SystemServerBenchmarkActivity.java | 185 | ||||
-rw-r--r-- | startop/apps/test/src/SystemServerBenchmarks.java | 205 |
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()); + } +} |