From 3fc37deca8cf51fe3c1b98b8527de750c0a2f2e6 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Thu, 12 Apr 2018 10:43:19 -0600 Subject: [PATCH] Benchmarks for streams. We've been advocating as little usage of streams as possible inside the system_server, and this is a benchmark showing the costs of using streams compared to rolling manual logic. Results on a taimen show that direct route is 2.2x faster (!). Trial Report (1 of 2): Experiment {instrument=runtime, benchmarkMethod=timeDirect, vm=app_process, parameters={}} Results: runtime(ns): min=47234.28, 1st qu.=47234.28, median=47234.28, mean=47234.28, 3rd qu.=47234.28, max=47234.28 Trial Report (2 of 2): Experiment {instrument=runtime, benchmarkMethod=timeStreams, vm=app_process, parameters={}} Results: runtime(ns): min=105660.39, 1st qu.=105660.39, median=105660.39, mean=105660.39, 3rd qu.=105660.39, max=105660.39 Bug: 77808546 Test: vogar --mode app_process --benchmark frameworks/base/core/tests/benchmarks/src/android/util/StreamsBenchmark.java Change-Id: Iac43a75970eee2c91593316a1b5a45d2c96c476b --- .../src/android/util/StreamsBenchmark.java | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 core/tests/benchmarks/src/android/util/StreamsBenchmark.java diff --git a/core/tests/benchmarks/src/android/util/StreamsBenchmark.java b/core/tests/benchmarks/src/android/util/StreamsBenchmark.java new file mode 100644 index 0000000000000..a4f8abb820b2c --- /dev/null +++ b/core/tests/benchmarks/src/android/util/StreamsBenchmark.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2018 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 android.util; + +import com.android.internal.util.FastPrintWriter; + +import com.google.caliper.AfterExperiment; +import com.google.caliper.BeforeExperiment; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; + +public class StreamsBenchmark { + private OutputStream dummy = new OutputStream() { + @Override + public void write(int b) throws IOException { + } + + @Override + public void write(byte b[], int off, int len) throws IOException { + } + }; + + private SparseIntArray calls; + + @BeforeExperiment + protected void setUp() { + calls = new SparseIntArray(); + final Random r = new Random(1); + for (int i = 0; i < 100; i++) { + calls.put(i, r.nextInt(Integer.MAX_VALUE)); + } + } + + @AfterExperiment + protected void tearDown() { + calls = null; + } + + public void timeDirect(int reps) { + for (int i = 0; i < reps; i++) { + final int N = calls.size(); + final long[] values = new long[N]; + for (int j = 0; j < N; j++) { + values[j] = ((long) calls.valueAt(j) << 32) | calls.keyAt(j); + } + Arrays.sort(values); + + final FastPrintWriter pw = new FastPrintWriter(dummy); + pw.println("Top openSession callers (uid=count):"); + final int end = Math.max(0, N - 20); + for (int j = N - 1; j >= end; j--) { + final int uid = (int) (values[j] & 0xffffffff); + final int count = (int) (values[j] >> 32); + pw.print(uid); + pw.print("="); + pw.println(count); + } + pw.println(); + pw.flush(); + } + } + + public void timeStreams(int reps) { + for (int i = 0; i < reps; i++) { + List> callsList = + getOpenSessionCallsList(calls).stream().sorted( + Comparator.comparing( + (Pair pair) -> pair.second).reversed()) + .limit(20) + .collect(Collectors.toList()); + + final FastPrintWriter pw = new FastPrintWriter(dummy); + pw.println("Top openSession callers (uid=count):"); + for (Pair uidCalls : callsList) { + pw.print(uidCalls.first); + pw.print("="); + pw.println(uidCalls.second); + } + pw.println(); + pw.flush(); + } + } + + private static List> getOpenSessionCallsList( + SparseIntArray openSessionCalls) { + ArrayList> list = new ArrayList<>(openSessionCalls.size()); + for (int i=0; i(uid, openSessionCalls.get(uid))); + } + + return list; + } +}