123d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu/*
223d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu * Copyright (C) 2016 The Android Open Source Project
323d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu *
423d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu * Licensed under the Apache License, Version 2.0 (the "License");
523d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu * you may not use this file except in compliance with the License.
623d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu * You may obtain a copy of the License at
723d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu *
823d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu *      http://www.apache.org/licenses/LICENSE-2.0
923d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu *
1023d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu * Unless required by applicable law or agreed to in writing, software
1123d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu * distributed under the License is distributed on an "AS IS" BASIS,
1223d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1323d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu * See the License for the specific language governing permissions and
1423d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu * limitations under the License.
1523d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu */
1623d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu
1723d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhupackage android.perftests.utils;
1823d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu
1923d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhuimport android.app.Activity;
2023d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhuimport android.app.Instrumentation;
2123d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhuimport android.os.Bundle;
223acf0382da22cda88234e599cd81b1ff5441cc35John Reckimport android.os.Debug;
233acf0382da22cda88234e599cd81b1ff5441cc35John Reckimport android.support.test.InstrumentationRegistry;
2423d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhuimport android.util.Log;
2523d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu
263acf0382da22cda88234e599cd81b1ff5441cc35John Reckimport java.io.File;
2723d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhuimport java.util.ArrayList;
2862e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reckimport java.util.concurrent.TimeUnit;
2923d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu
3023d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu/**
3123d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu * Provides a benchmark framework.
3223d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu *
3323d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu * Example usage:
3423d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu * // Executes the code while keepRunning returning true.
3523d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu *
3623d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu * public void sampleMethod() {
3723d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu *     BenchmarkState state = new BenchmarkState();
3823d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu *
3923d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu *     int[] src = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
4023d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu *     while (state.keepRunning()) {
4123d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu *         int[] dest = new int[src.length];
4223d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu *         System.arraycopy(src, 0, dest, 0, src.length);
4323d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu *     }
4423d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu *     System.out.println(state.summaryLine());
4523d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu * }
4623d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu */
4762e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reckpublic final class BenchmarkState {
48c1d6ba4053b4d5f7a9c3c255073d22fbe4af392fJohn Reck
4923d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    private static final String TAG = "BenchmarkState";
503acf0382da22cda88234e599cd81b1ff5441cc35John Reck    private static final boolean ENABLE_PROFILING = false;
5123d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu
5262e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private static final int NOT_STARTED = 0;  // The benchmark has not started yet.
5362e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private static final int WARMUP = 1; // The benchmark is warming up.
5423d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    private static final int RUNNING = 2;  // The benchmark is running.
55c1d6ba4053b4d5f7a9c3c255073d22fbe4af392fJohn Reck    private static final int FINISHED = 3;  // The benchmark has stopped.
5623d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu
5723d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    private int mState = NOT_STARTED;  // Current benchmark state.
5823d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu
5962e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private static final long WARMUP_DURATION_NS = ms2ns(250); // warm-up for at least 250ms
6062e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private static final int WARMUP_MIN_ITERATIONS = 16; // minimum iterations to warm-up for
6162e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck
6262e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    // TODO: Tune these values.
6362e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private static final long TARGET_TEST_DURATION_NS = ms2ns(500); // target testing for 500 ms
6462e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private static final int MAX_TEST_ITERATIONS = 1000000;
6524e98b7667da2ba7718e111c4b6d5d739e67e4f4John Reck    private static final int MIN_TEST_ITERATIONS = 10;
6662e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private static final int REPEAT_COUNT = 5;
6762e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck
6862e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private long mStartTimeNs = 0;  // Previously captured System.nanoTime().
69c1d6ba4053b4d5f7a9c3c255073d22fbe4af392fJohn Reck    private boolean mPaused;
7062e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private long mPausedTimeNs = 0; // The System.nanoTime() when the pauseTiming() is called.
7162e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private long mPausedDurationNs = 0;  // The duration of paused state in nano sec.
7262e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck
7362e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private int mIteration = 0;
7462e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private int mMaxIterations = 0;
7562e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck
7662e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private int mRepeatCount = 0;
7723d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu
7823d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    // Statistics. These values will be filled when the benchmark has finished.
7923d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    // The computation needs double precision, but long int is fine for final reporting.
80263d674d598f77a1f91bdfc73be808efd3446133Arthur Eubanks    private Stats mStats;
8153c23fdd5cf454c0f035e307ed5fda673b8b62ddSudheer Shanka
8223d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    // Individual duration in nano seconds.
8323d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    private ArrayList<Long> mResults = new ArrayList<>();
8423d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu
8562e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private static final long ms2ns(long ms) {
8662e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        return TimeUnit.MILLISECONDS.toNanos(ms);
8753c23fdd5cf454c0f035e307ed5fda673b8b62ddSudheer Shanka    }
8853c23fdd5cf454c0f035e307ed5fda673b8b62ddSudheer Shanka
892a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka    // Stops the benchmark timer.
902a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka    // This method can be called only when the timer is running.
912a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka    public void pauseTiming() {
92c1d6ba4053b4d5f7a9c3c255073d22fbe4af392fJohn Reck        if (mPaused) {
932a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka            throw new IllegalStateException(
942a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka                    "Unable to pause the benchmark. The benchmark has already paused.");
952a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka        }
9662e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mPausedTimeNs = System.nanoTime();
97c1d6ba4053b4d5f7a9c3c255073d22fbe4af392fJohn Reck        mPaused = true;
982a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka    }
992a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka
1002a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka    // Starts the benchmark timer.
1012a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka    // This method can be called only when the timer is stopped.
1022a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka    public void resumeTiming() {
103c1d6ba4053b4d5f7a9c3c255073d22fbe4af392fJohn Reck        if (!mPaused) {
1042a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka            throw new IllegalStateException(
1052a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka                    "Unable to resume the benchmark. The benchmark is already running.");
1062a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka        }
10762e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mPausedDurationNs += System.nanoTime() - mPausedTimeNs;
10862e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mPausedTimeNs = 0;
109c1d6ba4053b4d5f7a9c3c255073d22fbe4af392fJohn Reck        mPaused = false;
11062e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    }
11162e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck
11262e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private void beginWarmup() {
11362e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mStartTimeNs = System.nanoTime();
11462e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mIteration = 0;
11562e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mState = WARMUP;
11662e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    }
11762e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck
11862e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private void beginBenchmark(long warmupDuration, int iterations) {
1193acf0382da22cda88234e599cd81b1ff5441cc35John Reck        if (ENABLE_PROFILING) {
1203acf0382da22cda88234e599cd81b1ff5441cc35John Reck            File f = new File(InstrumentationRegistry.getContext().getDataDir(), "benchprof");
1213acf0382da22cda88234e599cd81b1ff5441cc35John Reck            Log.d(TAG, "Tracing to: " + f.getAbsolutePath());
1223acf0382da22cda88234e599cd81b1ff5441cc35John Reck            Debug.startMethodTracingSampling(f.getAbsolutePath(), 16 * 1024 * 1024, 100);
1233acf0382da22cda88234e599cd81b1ff5441cc35John Reck        }
12462e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mMaxIterations = (int) (TARGET_TEST_DURATION_NS / (warmupDuration / iterations));
12562e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mMaxIterations = Math.min(MAX_TEST_ITERATIONS,
12662e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck                Math.max(mMaxIterations, MIN_TEST_ITERATIONS));
12762e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mPausedDurationNs = 0;
12862e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mIteration = 0;
12962e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mRepeatCount = 0;
1302a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka        mState = RUNNING;
13162e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mStartTimeNs = System.nanoTime();
13262e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    }
13362e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck
13462e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private boolean startNextTestRun() {
13562e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        final long currentTime = System.nanoTime();
13662e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mResults.add((currentTime - mStartTimeNs - mPausedDurationNs) / mMaxIterations);
13762e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mRepeatCount++;
13862e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        if (mRepeatCount >= REPEAT_COUNT) {
1393acf0382da22cda88234e599cd81b1ff5441cc35John Reck            if (ENABLE_PROFILING) {
1403acf0382da22cda88234e599cd81b1ff5441cc35John Reck                Debug.stopMethodTracing();
1413acf0382da22cda88234e599cd81b1ff5441cc35John Reck            }
142263d674d598f77a1f91bdfc73be808efd3446133Arthur Eubanks            mStats = new Stats(mResults);
14362e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck            mState = FINISHED;
14462e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck            return false;
14562e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        }
14662e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mPausedDurationNs = 0;
14762e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mIteration = 0;
14862e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        mStartTimeNs = System.nanoTime();
14962e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        return true;
1502a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka    }
1512a154e2940e79f694ff95b93012e56c5ade70234Seigo Nonaka
15223d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    /**
15323d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu     * Judges whether the benchmark needs more samples.
15423d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu     *
15523d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu     * For the usage, see class comment.
15623d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu     */
15723d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    public boolean keepRunning() {
15823d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        switch (mState) {
15923d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu            case NOT_STARTED:
16062e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck                beginWarmup();
16162e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck                return true;
16262e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck            case WARMUP:
16362e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck                mIteration++;
16462e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck                // Only check nanoTime on every iteration in WARMUP since we
16562e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck                // don't yet have a target iteration count.
16662e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck                final long duration = System.nanoTime() - mStartTimeNs;
16762e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck                if (mIteration >= WARMUP_MIN_ITERATIONS && duration >= WARMUP_DURATION_NS) {
16862e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck                    beginBenchmark(duration, mIteration);
16962e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck                }
17023d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu                return true;
17123d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu            case RUNNING:
17262e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck                mIteration++;
17362e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck                if (mIteration >= mMaxIterations) {
17462e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck                    return startNextTestRun();
17523d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu                }
176c1d6ba4053b4d5f7a9c3c255073d22fbe4af392fJohn Reck                if (mPaused) {
177c1d6ba4053b4d5f7a9c3c255073d22fbe4af392fJohn Reck                    throw new IllegalStateException(
178c1d6ba4053b4d5f7a9c3c255073d22fbe4af392fJohn Reck                            "Benchmark step finished with paused state. " +
179c1d6ba4053b4d5f7a9c3c255073d22fbe4af392fJohn Reck                            "Resume the benchmark before finishing each step.");
180c1d6ba4053b4d5f7a9c3c255073d22fbe4af392fJohn Reck                }
18123d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu                return true;
18223d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu            case FINISHED:
18323d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu                throw new IllegalStateException("The benchmark has finished.");
18423d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu            default:
18523d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu                throw new IllegalStateException("The benchmark is in unknown state.");
18623d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        }
18723d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    }
18823d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu
18962e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private long mean() {
19023d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        if (mState != FINISHED) {
19123d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu            throw new IllegalStateException("The benchmark hasn't finished");
19223d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        }
193263d674d598f77a1f91bdfc73be808efd3446133Arthur Eubanks        return (long) mStats.getMean();
19423d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    }
19523d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu
19662e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private long median() {
19723d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        if (mState != FINISHED) {
19823d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu            throw new IllegalStateException("The benchmark hasn't finished");
19923d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        }
200263d674d598f77a1f91bdfc73be808efd3446133Arthur Eubanks        return mStats.getMedian();
20123d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    }
20223d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu
20362e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private long min() {
20462e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        if (mState != FINISHED) {
20562e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck            throw new IllegalStateException("The benchmark hasn't finished");
20662e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        }
207263d674d598f77a1f91bdfc73be808efd3446133Arthur Eubanks        return mStats.getMin();
20862e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    }
20962e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck
21062e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck    private long standardDeviation() {
21123d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        if (mState != FINISHED) {
21223d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu            throw new IllegalStateException("The benchmark hasn't finished");
21323d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        }
214263d674d598f77a1f91bdfc73be808efd3446133Arthur Eubanks        return (long) mStats.getStandardDeviation();
21523d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    }
21623d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu
21723d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    private String summaryLine() {
21823d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        StringBuilder sb = new StringBuilder();
21923d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        sb.append("Summary: ");
220a9cebd628c53b900d48600a5e7ced546c91522e6Teng-Hui Zhu        sb.append("median=").append(median()).append("ns, ");
221a9cebd628c53b900d48600a5e7ced546c91522e6Teng-Hui Zhu        sb.append("mean=").append(mean()).append("ns, ");
22262e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        sb.append("min=").append(min()).append("ns, ");
223a9cebd628c53b900d48600a5e7ced546c91522e6Teng-Hui Zhu        sb.append("sigma=").append(standardDeviation()).append(", ");
224a9cebd628c53b900d48600a5e7ced546c91522e6Teng-Hui Zhu        sb.append("iteration=").append(mResults.size()).append(", ");
225a9cebd628c53b900d48600a5e7ced546c91522e6Teng-Hui Zhu        // print out the first few iterations' number for double checking.
22662e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        int sampleNumber = Math.min(mResults.size(), 16);
227a9cebd628c53b900d48600a5e7ced546c91522e6Teng-Hui Zhu        for (int i = 0; i < sampleNumber; i++) {
228a9cebd628c53b900d48600a5e7ced546c91522e6Teng-Hui Zhu            sb.append("No ").append(i).append(" result is ").append(mResults.get(i)).append(", ");
229a9cebd628c53b900d48600a5e7ced546c91522e6Teng-Hui Zhu        }
23023d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        return sb.toString();
23123d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    }
23223d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu
23323d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    public void sendFullStatusReport(Instrumentation instrumentation, String key) {
23423d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        Log.i(TAG, key + summaryLine());
23523d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        Bundle status = new Bundle();
23623d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        status.putLong(key + "_median", median());
23723d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        status.putLong(key + "_mean", mean());
23862e5fea8554aa61bbf691e8084b8ddd68e69c78eJohn Reck        status.putLong(key + "_min", min());
23923d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        status.putLong(key + "_standardDeviation", standardDeviation());
24023d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu        instrumentation.sendStatus(Activity.RESULT_OK, status);
24123d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu    }
24223d1fdded5fe78024927137ddfb82401fd9e3344Teng-Hui Zhu}
243