From 23d1fdded5fe78024927137ddfb82401fd9e3344 Mon Sep 17 00:00:00 2001 From: Teng-Hui Zhu Date: Mon, 20 Jun 2016 14:42:35 -0700 Subject: [PATCH] Refactor the java side APCT perf test Relocate everything into apct-tests/ Setup the share static java lib for the common code and use it. b/28980976 Change-Id: I74c80c0b54ad18ee5fc44da43249d3c88fb926e2 --- .../perftests/core}/Android.mk | 2 +- .../perftests/core}/AndroidManifest.xml | 0 .../src/android/widget/StubActivity.java | 0 .../widget/TextViewSetTextLocalePerfTest.java | 8 +- .../perftests/graphics}/Android.mk | 2 + .../perftests/graphics}/AndroidManifest.xml | 0 .../res/drawable/vector_drawable01.xml | 0 .../graphics/perftests/StubActivity.java | 0 .../perftests/VectorDrawablePerfTest.java | 23 +-- apct-tests/perftests/utils/Android.mk | 14 ++ .../perftests/utils/BenchmarkState.java | 163 ++++++++++++++++++ .../src/android/perftest/BenchmarkState.java | 147 ---------------- 12 files changed, 190 insertions(+), 169 deletions(-) rename {core/tests/perftests => apct-tests/perftests/core}/Android.mk (73%) rename {core/tests/perftests => apct-tests/perftests/core}/AndroidManifest.xml (100%) rename {core/tests/perftests => apct-tests/perftests/core}/src/android/widget/StubActivity.java (100%) rename {core/tests/perftests => apct-tests/perftests/core}/src/android/widget/TextViewSetTextLocalePerfTest.java (88%) rename {graphics/tests/perftests => apct-tests/perftests/graphics}/Android.mk (84%) rename {graphics/tests/perftests => apct-tests/perftests/graphics}/AndroidManifest.xml (100%) rename {graphics/tests/perftests => apct-tests/perftests/graphics}/res/drawable/vector_drawable01.xml (100%) rename {graphics/tests/perftests => apct-tests/perftests/graphics}/src/android/graphics/perftests/StubActivity.java (100%) rename {graphics/tests/perftests => apct-tests/perftests/graphics}/src/android/graphics/perftests/VectorDrawablePerfTest.java (83%) create mode 100644 apct-tests/perftests/utils/Android.mk create mode 100644 apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java delete mode 100644 core/tests/perftests/src/android/perftest/BenchmarkState.java diff --git a/core/tests/perftests/Android.mk b/apct-tests/perftests/core/Android.mk similarity index 73% rename from core/tests/perftests/Android.mk rename to apct-tests/perftests/core/Android.mk index fb2fabaf84151..e9f18fd7d0ec5 100644 --- a/core/tests/perftests/Android.mk +++ b/apct-tests/perftests/core/Android.mk @@ -5,7 +5,7 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under, src) -LOCAL_STATIC_JAVA_LIBRARIES := android-support-test +LOCAL_STATIC_JAVA_LIBRARIES := android-support-test apct-perftests-utils LOCAL_PACKAGE_NAME := CorePerfTests diff --git a/core/tests/perftests/AndroidManifest.xml b/apct-tests/perftests/core/AndroidManifest.xml similarity index 100% rename from core/tests/perftests/AndroidManifest.xml rename to apct-tests/perftests/core/AndroidManifest.xml diff --git a/core/tests/perftests/src/android/widget/StubActivity.java b/apct-tests/perftests/core/src/android/widget/StubActivity.java similarity index 100% rename from core/tests/perftests/src/android/widget/StubActivity.java rename to apct-tests/perftests/core/src/android/widget/StubActivity.java diff --git a/core/tests/perftests/src/android/widget/TextViewSetTextLocalePerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewSetTextLocalePerfTest.java similarity index 88% rename from core/tests/perftests/src/android/widget/TextViewSetTextLocalePerfTest.java rename to apct-tests/perftests/core/src/android/widget/TextViewSetTextLocalePerfTest.java index fecb2d8ea3b39..c5e8db0225764 100644 --- a/core/tests/perftests/src/android/widget/TextViewSetTextLocalePerfTest.java +++ b/apct-tests/perftests/core/src/android/widget/TextViewSetTextLocalePerfTest.java @@ -20,8 +20,7 @@ import android.app.Activity; import android.os.Bundle; import android.util.Log; -import android.perftest.BenchmarkState; - +import android.perftests.utils.BenchmarkState; import android.support.test.filters.LargeTest; import android.support.test.runner.AndroidJUnit4; import android.support.test.rule.ActivityTestRule; @@ -74,9 +73,6 @@ public class TextViewSetTextLocalePerfTest { textView.setTextLocale(mSecondLocale); } - Log.i("TextViewSetTextLocalePerfTest", mMetricKey + ": " + state.summaryLine()); - final Bundle status = new Bundle(); - status.putLong(mMetricKey, state.median()); - InstrumentationRegistry.getInstrumentation().sendStatus(Activity.RESULT_OK, status); + state.sendFullStatusReport(InstrumentationRegistry.getInstrumentation(), mMetricKey); } } diff --git a/graphics/tests/perftests/Android.mk b/apct-tests/perftests/graphics/Android.mk similarity index 84% rename from graphics/tests/perftests/Android.mk rename to apct-tests/perftests/graphics/Android.mk index c35c3b7027180..ee0bdc19e797e 100644 --- a/graphics/tests/perftests/Android.mk +++ b/apct-tests/perftests/graphics/Android.mk @@ -3,6 +3,8 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests +LOCAL_STATIC_JAVA_LIBRARIES := apct-perftests-utils + LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res LOCAL_SRC_FILES := $(call all-java-files-under, src) diff --git a/graphics/tests/perftests/AndroidManifest.xml b/apct-tests/perftests/graphics/AndroidManifest.xml similarity index 100% rename from graphics/tests/perftests/AndroidManifest.xml rename to apct-tests/perftests/graphics/AndroidManifest.xml diff --git a/graphics/tests/perftests/res/drawable/vector_drawable01.xml b/apct-tests/perftests/graphics/res/drawable/vector_drawable01.xml similarity index 100% rename from graphics/tests/perftests/res/drawable/vector_drawable01.xml rename to apct-tests/perftests/graphics/res/drawable/vector_drawable01.xml diff --git a/graphics/tests/perftests/src/android/graphics/perftests/StubActivity.java b/apct-tests/perftests/graphics/src/android/graphics/perftests/StubActivity.java similarity index 100% rename from graphics/tests/perftests/src/android/graphics/perftests/StubActivity.java rename to apct-tests/perftests/graphics/src/android/graphics/perftests/StubActivity.java diff --git a/graphics/tests/perftests/src/android/graphics/perftests/VectorDrawablePerfTest.java b/apct-tests/perftests/graphics/src/android/graphics/perftests/VectorDrawablePerfTest.java similarity index 83% rename from graphics/tests/perftests/src/android/graphics/perftests/VectorDrawablePerfTest.java rename to apct-tests/perftests/graphics/src/android/graphics/perftests/VectorDrawablePerfTest.java index 2774f4a6d958e..6f17369d80a6e 100644 --- a/graphics/tests/perftests/src/android/graphics/perftests/VectorDrawablePerfTest.java +++ b/apct-tests/perftests/graphics/src/android/graphics/perftests/VectorDrawablePerfTest.java @@ -17,12 +17,12 @@ package android.graphics.perftests; import android.app.Activity; -import android.app.Instrumentation; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.VectorDrawable; import android.os.Bundle; +import android.perftests.utils.BenchmarkState; import android.test.ActivityInstrumentationTestCase2; import android.test.suitebuilder.annotation.LargeTest; import android.util.Log; @@ -37,19 +37,19 @@ import java.io.IOException; public class VectorDrawablePerfTest extends ActivityInstrumentationTestCase2 { private static final String TAG = "PathPerfTest"; - private static final int REPEAT_TIMES = 200; private static final boolean DBG_PERF = false; private int[] mTestWidths = {1024, 512}; private int[] mTestHeights = {512, 1024}; - private String KEY_VECTORDRAWABLE_DRAW_TIME = "VectorDrawable_Draw_Time_MicroSec"; + private String KEY_VECTORDRAWABLE_DRAW_TIME = "VectorDrawable_Draw_Time_NanoSec"; public VectorDrawablePerfTest() { super(StubActivity.class); } // Save a bitmap into a PNG, only for debugging purpose. + // TODO: move into utility class. private void saveBitmapIntoPNG(Bitmap bitmap, int resId) throws IOException { // Save the image to the disk. FileOutputStream out = null; @@ -87,14 +87,14 @@ public class VectorDrawablePerfTest extends ActivityInstrumentationTestCase2 mResults = new ArrayList<>(); + + /** + * Calculates statistics. + */ + private void calculateSatistics() { + final int size = mResults.size(); + if (size <= 1) { + throw new IllegalStateException("At least two results are necessary."); + } + + Collections.sort(mResults); + mMedian = size % 2 == 0 ? (mResults.get(size / 2) + mResults.get(size / 2 + 1)) / 2 : + mResults.get(size / 2); + + for (int i = 0; i < size; ++i) { + mMean += mResults.get(i); + } + mMean /= (double) size; + + for (int i = 0; i < size; ++i) { + final double tmp = mResults.get(i) - mMean; + mStandardDeviation += tmp * tmp; + } + mStandardDeviation = Math.sqrt(mStandardDeviation / (double) (size - 1)); + } + + /** + * Judges whether the benchmark needs more samples. + * + * For the usage, see class comment. + */ + public boolean keepRunning() { + switch (mState) { + case NOT_STARTED: + mNanoPreviousTime = System.nanoTime(); + mNanoFinishTime = mNanoPreviousTime + mNanoTimeLimit; + mState = RUNNING; + return true; + case RUNNING: + final long currentTime = System.nanoTime(); + mResults.add(currentTime - mNanoPreviousTime); + + // To calculate statistics, needs two or more samples. + if (mResults.size() > MIN_REPEAT_TIMES && currentTime > mNanoFinishTime) { + calculateSatistics(); + mState = FINISHED; + return false; + } + + mNanoPreviousTime = currentTime; + return true; + case FINISHED: + throw new IllegalStateException("The benchmark has finished."); + default: + throw new IllegalStateException("The benchmark is in unknown state."); + } + } + + public long mean() { + if (mState != FINISHED) { + throw new IllegalStateException("The benchmark hasn't finished"); + } + return (long) mMean; + } + + public long median() { + if (mState != FINISHED) { + throw new IllegalStateException("The benchmark hasn't finished"); + } + return mMedian; + } + + public long standardDeviation() { + if (mState != FINISHED) { + throw new IllegalStateException("The benchmark hasn't finished"); + } + return (long) mStandardDeviation; + } + + private String summaryLine() { + StringBuilder sb = new StringBuilder(); + sb.append("Summary: "); + sb.append("median=" + median() + "ns, "); + sb.append("mean=" + mean() + "ns, "); + sb.append("sigma=" + standardDeviation() + ", "); + sb.append("iteration=" + mResults.size()); + return sb.toString(); + } + + public void sendFullStatusReport(Instrumentation instrumentation, String key) { + Log.i(TAG, key + summaryLine()); + Bundle status = new Bundle(); + status.putLong(key + "_median", median()); + status.putLong(key + "_mean", mean()); + status.putLong(key + "_standardDeviation", standardDeviation()); + instrumentation.sendStatus(Activity.RESULT_OK, status); + } +} diff --git a/core/tests/perftests/src/android/perftest/BenchmarkState.java b/core/tests/perftests/src/android/perftest/BenchmarkState.java deleted file mode 100644 index 146582c87b910..0000000000000 --- a/core/tests/perftests/src/android/perftest/BenchmarkState.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2016 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.perftest; - -import java.util.ArrayList; -import java.util.Collections; - -/** - * Provides a benchmark framework. - * - * Example usage: - * // Executes the code while keepRunning returning true. - * - * public void sampleMethod() { - * BenchmarkState state = new BenchmarkState(); - * - * int[] src = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - * while (state.keepRunning()) { - * int[] dest = new int[src.length]; - * System.arraycopy(src, 0, dest, 0, src.length); - * } - * - * System.out.println(state.summaryLine()); - * } - */ -public class BenchmarkState { - private static final int NOT_STARTED = 1; // The benchmark has not started yet. - private static final int RUNNING = 2; // The benchmark is running. - private static final int FINISHED = 3; // The benchmark has stopped. - - private int mState = NOT_STARTED; // Current benchmark state. - - private long mNanoPreviousTime = 0; // Previously captured System.nanoTime(). - private long mNanoFinishTime = 0; // Finish if System.nanoTime() returns after than this value. - private long mNanoTimeLimit = 1 * 1000 * 1000 * 1000; // 1 sec. Default time limit. - - // Statistics. These values will be filled when the benchmark has finished. - private long mMedian = 0; - private double mMean = 0.0; - private double mStandardDeviation = 0.0; - - // Individual duration in nano seconds. - private ArrayList mResults = new ArrayList<>(); - - /** - * Calculates statistics. - */ - private void calculateSatistics() { - final int size = mResults.size(); - if (size <= 1) { - throw new IllegalStateException("At least two results are necessary."); - } - - Collections.sort(mResults); - mMedian = size % 2 == 0 ? (mResults.get(size / 2) + mResults.get(size / 2 + 1)) / 2 : - mResults.get(size / 2); - - for (int i = 0; i < size; ++i) { - mMean += mResults.get(i); - } - mMean /= (double)size; - - for (int i = 0; i < size; ++i) { - final double tmp = mResults.get(i) - mMean; - mStandardDeviation += tmp * tmp; - } - mStandardDeviation = Math.sqrt(mStandardDeviation / (double)(size - 1)); - } - - /** - * Judges whether the benchmark needs more samples. - * - * For the usage, see class comment. - */ - public boolean keepRunning() { - switch (mState) { - case NOT_STARTED: - mNanoPreviousTime = System.nanoTime(); - mNanoFinishTime = mNanoPreviousTime + mNanoTimeLimit; - mState = RUNNING; - return true; - case RUNNING: - final long currentTime = System.nanoTime(); - mResults.add(currentTime - mNanoPreviousTime); - - // To calculate statistics, needs two or more samples. - if (mResults.size() > 2 && currentTime > mNanoFinishTime) { - calculateSatistics(); - mState = FINISHED; - return false; - } - - mNanoPreviousTime = currentTime; - return true; - case FINISHED: - throw new IllegalStateException("The benchmark has finished."); - default: - throw new IllegalStateException("The benchmark is in unknown state."); - } - } - - public double mean() { - if (mState != FINISHED) { - throw new IllegalStateException("The benchmark hasn't finished"); - } - return mMean; - } - - public long median() { - if (mState != FINISHED) { - throw new IllegalStateException("The benchmark hasn't finished"); - } - return mMedian; - } - - public double standardDeviation() { - if (mState != FINISHED) { - throw new IllegalStateException("The benchmark hasn't finished"); - } - return mStandardDeviation; - } - - public String summaryLine() { - StringBuilder sb = new StringBuilder(); - sb.append("Summary: "); - sb.append("median=" + median() + "ns, "); - sb.append("mean=" + mean() + "ns, "); - sb.append("sigma=" + standardDeviation() + ", "); - sb.append("iteration=" + mResults.size()); - return sb.toString(); - } - -}