alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Android example source code file (PerformanceCollector.java)

This example Android source code file (PerformanceCollector.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Android by Example" TM.

Java - Android tags/keywords

bundle, metric_key_cpu_time, metric_key_gc_invocation_count, metric_key_iterations, metric_key_java_private_dirty, metric_key_java_shared_dirty, metric_key_java_size, metric_key_native_free, metric_key_native_shared_dirty, metric_key_native_size, metric_key_received_transactions, performancecollector, performanceresultswriter, string, util

The PerformanceCollector.java Android example source code

/*
 * Copyright (C) 2009 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.os;


import java.util.ArrayList;

/**
 * Collects performance data between two function calls in Bundle objects and
 * outputs the results using writer of type {@link PerformanceResultsWriter}.
 * <p>
 * {@link #beginSnapshot(String)} and {@link #endSnapshot()} functions collect
 * memory usage information and measure runtime between calls to begin and end.
 * These functions logically wrap around an entire test, and should be called
 * with name of test as the label, e.g. EmailPerformanceTest.
 * <p>
 * {@link #startTiming(String)} and {@link #stopTiming(String)} functions
 * measure runtime between calls to start and stop. These functions logically
 * wrap around a single test case or a small block of code, and should be called
 * with the name of test case as the label, e.g. testSimpleSendMailSequence.
 * <p>
 * {@link #addIteration(String)} inserts intermediate measurement point which
 * can be labeled with a String, e.g. Launch email app, compose, send, etc.
 * <p>
 * Snapshot and timing functions do not interfere with each other, and thus can
 * be called in any order. The intended structure is to wrap begin/endSnapshot
 * around calls to start/stopTiming, for example:
 * <p>
 * <code>beginSnapshot("EmailPerformanceTest");
 * startTiming("testSimpleSendSequence");
 * addIteration("Launch email app");
 * addIteration("Compose");
 * stopTiming("Send");
 * startTiming("testComplexSendSequence");
 * stopTiming("");
 * startTiming("testAddLabel");
 * stopTiming("");
 * endSnapshot();</code>
 * <p>
 * Structure of results output is up to implementor of
 * {@link PerformanceResultsWriter }.
 *
 * {@hide} Pending approval for public API.
 */
public class PerformanceCollector {

    /**
     * Interface for reporting performance data.
     */
    public interface PerformanceResultsWriter {

        /**
         * Callback invoked as first action in
         * PerformanceCollector#beginSnapshot(String) for reporting the start of
         * a performance snapshot.
         *
         * @param label description of code block between beginSnapshot and
         *              PerformanceCollector#endSnapshot()
         * @see PerformanceCollector#beginSnapshot(String)
         */
        public void writeBeginSnapshot(String label);

        /**
         * Callback invoked as last action in PerformanceCollector#endSnapshot()
         * for reporting performance data collected in the snapshot.
         *
         * @param results memory and runtime metrics stored as key/value pairs,
         *        in the same structure as returned by
         *        PerformanceCollector#endSnapshot()
         * @see PerformanceCollector#endSnapshot()
         */
        public void writeEndSnapshot(Bundle results);

        /**
         * Callback invoked as first action in
         * PerformanceCollector#startTiming(String) for reporting the start of
         * a timing measurement.
         *
         * @param label description of code block between startTiming and
         *              PerformanceCollector#stopTiming(String)
         * @see PerformanceCollector#startTiming(String)
         */
        public void writeStartTiming(String label);

        /**
         * Callback invoked as last action in
         * {@link PerformanceCollector#stopTiming(String)} for reporting the
         * sequence of timings measured.
         *
         * @param results runtime metrics of code block between calls to
         *                startTiming and stopTiming, in the same structure as
         *                returned by PerformanceCollector#stopTiming(String)
         * @see PerformanceCollector#stopTiming(String)
         */
        public void writeStopTiming(Bundle results);

        /**
         * Callback invoked as last action in
         * {@link PerformanceCollector#addMeasurement(String, long)} for
         * reporting an integer type measurement.
         *
         * @param label short description of the metric that was measured
         * @param value long value of the measurement
         */
        public void writeMeasurement(String label, long value);

        /**
         * Callback invoked as last action in
         * {@link PerformanceCollector#addMeasurement(String, float)} for
         * reporting a float type measurement.
         *
         * @param label short description of the metric that was measured
         * @param value float value of the measurement
         */
        public void writeMeasurement(String label, float value);

        /**
         * Callback invoked as last action in
         * {@link PerformanceCollector#addMeasurement(String, String)} for
         * reporting a string field.
         *
         * @param label short description of the metric that was measured
         * @param value string summary of the measurement
         */
        public void writeMeasurement(String label, String value);
    }

    /**
     * In a results Bundle, this key references a List of iteration Bundles.
     */
    public static final String METRIC_KEY_ITERATIONS = "iterations";
    /**
     * In an iteration Bundle, this key describes the iteration.
     */
    public static final String METRIC_KEY_LABEL = "label";
    /**
     * In a results Bundle, this key reports the cpu time of the code block
     * under measurement.
     */
    public static final String METRIC_KEY_CPU_TIME = "cpu_time";
    /**
     * In a results Bundle, this key reports the execution time of the code
     * block under measurement.
     */
    public static final String METRIC_KEY_EXECUTION_TIME = "execution_time";
    /**
     * In a snapshot Bundle, this key reports the number of received
     * transactions from the binder driver before collection started.
     */
    public static final String METRIC_KEY_PRE_RECEIVED_TRANSACTIONS = "pre_received_transactions";
    /**
     * In a snapshot Bundle, this key reports the number of transactions sent by
     * the running program before collection started.
     */
    public static final String METRIC_KEY_PRE_SENT_TRANSACTIONS = "pre_sent_transactions";
    /**
     * In a snapshot Bundle, this key reports the number of received
     * transactions from the binder driver.
     */
    public static final String METRIC_KEY_RECEIVED_TRANSACTIONS = "received_transactions";
    /**
     * In a snapshot Bundle, this key reports the number of transactions sent by
     * the running program.
     */
    public static final String METRIC_KEY_SENT_TRANSACTIONS = "sent_transactions";
    /**
     * In a snapshot Bundle, this key reports the number of garbage collection
     * invocations.
     */
    public static final String METRIC_KEY_GC_INVOCATION_COUNT = "gc_invocation_count";
    /**
     * In a snapshot Bundle, this key reports the amount of allocated memory
     * used by the running program.
     */
    public static final String METRIC_KEY_JAVA_ALLOCATED = "java_allocated";
    /**
     * In a snapshot Bundle, this key reports the amount of free memory
     * available to the running program.
     */
    public static final String METRIC_KEY_JAVA_FREE = "java_free";
    /**
     * In a snapshot Bundle, this key reports the number of private dirty pages
     * used by dalvik.
     */
    public static final String METRIC_KEY_JAVA_PRIVATE_DIRTY = "java_private_dirty";
    /**
     * In a snapshot Bundle, this key reports the proportional set size for
     * dalvik.
     */
    public static final String METRIC_KEY_JAVA_PSS = "java_pss";
    /**
     * In a snapshot Bundle, this key reports the number of shared dirty pages
     * used by dalvik.
     */
    public static final String METRIC_KEY_JAVA_SHARED_DIRTY = "java_shared_dirty";
    /**
     * In a snapshot Bundle, this key reports the total amount of memory
     * available to the running program.
     */
    public static final String METRIC_KEY_JAVA_SIZE = "java_size";
    /**
     * In a snapshot Bundle, this key reports the amount of allocated memory in
     * the native heap.
     */
    public static final String METRIC_KEY_NATIVE_ALLOCATED = "native_allocated";
    /**
     * In a snapshot Bundle, this key reports the amount of free memory in the
     * native heap.
     */
    public static final String METRIC_KEY_NATIVE_FREE = "native_free";
    /**
     * In a snapshot Bundle, this key reports the number of private dirty pages
     * used by the native heap.
     */
    public static final String METRIC_KEY_NATIVE_PRIVATE_DIRTY = "native_private_dirty";
    /**
     * In a snapshot Bundle, this key reports the proportional set size for the
     * native heap.
     */
    public static final String METRIC_KEY_NATIVE_PSS = "native_pss";
    /**
     * In a snapshot Bundle, this key reports the number of shared dirty pages
     * used by the native heap.
     */
    public static final String METRIC_KEY_NATIVE_SHARED_DIRTY = "native_shared_dirty";
    /**
     * In a snapshot Bundle, this key reports the size of the native heap.
     */
    public static final String METRIC_KEY_NATIVE_SIZE = "native_size";
    /**
     * In a snapshot Bundle, this key reports the number of objects allocated
     * globally.
     */
    public static final String METRIC_KEY_GLOBAL_ALLOC_COUNT = "global_alloc_count";
    /**
     * In a snapshot Bundle, this key reports the size of all objects allocated
     * globally.
     */
    public static final String METRIC_KEY_GLOBAL_ALLOC_SIZE = "global_alloc_size";
    /**
     * In a snapshot Bundle, this key reports the number of objects freed
     * globally.
     */
    public static final String METRIC_KEY_GLOBAL_FREED_COUNT = "global_freed_count";
    /**
     * In a snapshot Bundle, this key reports the size of all objects freed
     * globally.
     */
    public static final String METRIC_KEY_GLOBAL_FREED_SIZE = "global_freed_size";
    /**
     * In a snapshot Bundle, this key reports the number of private dirty pages
     * used by everything else.
     */
    public static final String METRIC_KEY_OTHER_PRIVATE_DIRTY = "other_private_dirty";
    /**
     * In a snapshot Bundle, this key reports the proportional set size for
     * everything else.
     */
    public static final String METRIC_KEY_OTHER_PSS = "other_pss";
    /**
     * In a snapshot Bundle, this key reports the number of shared dirty pages
     * used by everything else.
     */
    public static final String METRIC_KEY_OTHER_SHARED_DIRTY = "other_shared_dirty";

    private PerformanceResultsWriter mPerfWriter;
    private Bundle mPerfSnapshot;
    private Bundle mPerfMeasurement;
    private long mSnapshotCpuTime;
    private long mSnapshotExecTime;
    private long mCpuTime;
    private long mExecTime;

    public PerformanceCollector() {
    }

    public PerformanceCollector(PerformanceResultsWriter writer) {
        setPerformanceResultsWriter(writer);
    }

    public void setPerformanceResultsWriter(PerformanceResultsWriter writer) {
        mPerfWriter = writer;
    }

    /**
     * Begin collection of memory usage information.
     *
     * @param label description of code block between beginSnapshot and
     *              endSnapshot, used to label output
     */
    public void beginSnapshot(String label) {
        if (mPerfWriter != null)
            mPerfWriter.writeBeginSnapshot(label);
        startPerformanceSnapshot();
    }

    /**
     * End collection of memory usage information. Returns collected data in a
     * Bundle object.
     *
     * @return Memory and runtime metrics stored as key/value pairs. Values are
     *         of type long, and keys include:
     *         <ul>
     *         <li>{@link #METRIC_KEY_CPU_TIME cpu_time}
     *         <li>{@link #METRIC_KEY_EXECUTION_TIME execution_time}
     *         <li>{@link #METRIC_KEY_PRE_RECEIVED_TRANSACTIONS
     *         pre_received_transactions}
     *         <li>{@link #METRIC_KEY_PRE_SENT_TRANSACTIONS
     *         pre_sent_transactions}
     *         <li>{@link #METRIC_KEY_RECEIVED_TRANSACTIONS
     *         received_transactions}
     *         <li>{@link #METRIC_KEY_SENT_TRANSACTIONS sent_transactions}
     *         <li>{@link #METRIC_KEY_GC_INVOCATION_COUNT gc_invocation_count}
     *         <li>{@link #METRIC_KEY_JAVA_ALLOCATED java_allocated}
     *         <li>{@link #METRIC_KEY_JAVA_FREE java_free}
     *         <li>{@link #METRIC_KEY_JAVA_PRIVATE_DIRTY java_private_dirty}
     *         <li>{@link #METRIC_KEY_JAVA_PSS java_pss}
     *         <li>{@link #METRIC_KEY_JAVA_SHARED_DIRTY java_shared_dirty}
     *         <li>{@link #METRIC_KEY_JAVA_SIZE java_size}
     *         <li>{@link #METRIC_KEY_NATIVE_ALLOCATED native_allocated}
     *         <li>{@link #METRIC_KEY_NATIVE_FREE native_free}
     *         <li>{@link #METRIC_KEY_NATIVE_PRIVATE_DIRTY native_private_dirty}
     *         <li>{@link #METRIC_KEY_NATIVE_PSS native_pss}
     *         <li>{@link #METRIC_KEY_NATIVE_SHARED_DIRTY native_shared_dirty}
     *         <li>{@link #METRIC_KEY_NATIVE_SIZE native_size}
     *         <li>{@link #METRIC_KEY_GLOBAL_ALLOC_COUNT global_alloc_count}
     *         <li>{@link #METRIC_KEY_GLOBAL_ALLOC_SIZE global_alloc_size}
     *         <li>{@link #METRIC_KEY_GLOBAL_FREED_COUNT global_freed_count}
     *         <li>{@link #METRIC_KEY_GLOBAL_FREED_SIZE global_freed_size}
     *         <li>{@link #METRIC_KEY_OTHER_PRIVATE_DIRTY other_private_dirty}
     *         <li>{@link #METRIC_KEY_OTHER_PSS other_pss}
     *         <li>{@link #METRIC_KEY_OTHER_SHARED_DIRTY other_shared_dirty}
     *         </ul>
     */
    public Bundle endSnapshot() {
        endPerformanceSnapshot();
        if (mPerfWriter != null)
            mPerfWriter.writeEndSnapshot(mPerfSnapshot);
        return mPerfSnapshot;
    }

    /**
     * Start measurement of user and cpu time.
     *
     * @param label description of code block between startTiming and
     *        stopTiming, used to label output
     */
    public void startTiming(String label) {
        if (mPerfWriter != null)
            mPerfWriter.writeStartTiming(label);
        mPerfMeasurement = new Bundle();
        mPerfMeasurement.putParcelableArrayList(
                METRIC_KEY_ITERATIONS, new ArrayList<Parcelable>());
        mExecTime = SystemClock.uptimeMillis();
        mCpuTime = Process.getElapsedCpuTime();
    }

    /**
     * Add a measured segment, and start measuring the next segment. Returns
     * collected data in a Bundle object.
     *
     * @param label description of code block between startTiming and
     *              addIteration, and between two calls to addIteration, used
     *              to label output
     * @return Runtime metrics stored as key/value pairs. Values are of type
     *         long, and keys include:
     *         <ul>
     *         <li>{@link #METRIC_KEY_LABEL label}
     *         <li>{@link #METRIC_KEY_CPU_TIME cpu_time}
     *         <li>{@link #METRIC_KEY_EXECUTION_TIME execution_time}
     *         </ul>
     */
    public Bundle addIteration(String label) {
        mCpuTime = Process.getElapsedCpuTime() - mCpuTime;
        mExecTime = SystemClock.uptimeMillis() - mExecTime;

        Bundle iteration = new Bundle();
        iteration.putString(METRIC_KEY_LABEL, label);
        iteration.putLong(METRIC_KEY_EXECUTION_TIME, mExecTime);
        iteration.putLong(METRIC_KEY_CPU_TIME, mCpuTime);
        mPerfMeasurement.getParcelableArrayList(METRIC_KEY_ITERATIONS).add(iteration);

        mExecTime = SystemClock.uptimeMillis();
        mCpuTime = Process.getElapsedCpuTime();
        return iteration;
    }

    /**
     * Stop measurement of user and cpu time.
     *
     * @param label description of code block between addIteration or
     *              startTiming and stopTiming, used to label output
     * @return Runtime metrics stored in a bundle, including all iterations
     *         between calls to startTiming and stopTiming. List of iterations
     *         is keyed by {@link #METRIC_KEY_ITERATIONS iterations}.
     */
    public Bundle stopTiming(String label) {
        addIteration(label);
        if (mPerfWriter != null)
            mPerfWriter.writeStopTiming(mPerfMeasurement);
        return mPerfMeasurement;
    }

    /**
     * Add an integer type measurement to the collector.
     *
     * @param label short description of the metric that was measured
     * @param value long value of the measurement
     */
    public void addMeasurement(String label, long value) {
        if (mPerfWriter != null)
            mPerfWriter.writeMeasurement(label, value);
    }

    /**
     * Add a float type measurement to the collector.
     *
     * @param label short description of the metric that was measured
     * @param value float value of the measurement
     */
    public void addMeasurement(String label, float value) {
        if (mPerfWriter != null)
            mPerfWriter.writeMeasurement(label, value);
    }

    /**
     * Add a string field to the collector.
     *
     * @param label short description of the metric that was measured
     * @param value string summary of the measurement
     */
    public void addMeasurement(String label, String value) {
        if (mPerfWriter != null)
            mPerfWriter.writeMeasurement(label, value);
    }

    /*
     * Starts tracking memory usage, binder transactions, and real & cpu timing.
     */
    private void startPerformanceSnapshot() {
        // Create new snapshot
        mPerfSnapshot = new Bundle();

        // Add initial binder counts
        Bundle binderCounts = getBinderCounts();
        for (String key : binderCounts.keySet()) {
            mPerfSnapshot.putLong("pre_" + key, binderCounts.getLong(key));
        }

        // Force a GC and zero out the performance counters. Do this
        // before reading initial CPU/wall-clock times so we don't include
        // the cost of this setup in our final metrics.
        startAllocCounting();

        // Record CPU time up to this point, and start timing. Note: this
        // must happen at the end of this method, otherwise the timing will
        // include noise.
        mSnapshotExecTime = SystemClock.uptimeMillis();
        mSnapshotCpuTime = Process.getElapsedCpuTime();
    }

    /*
     * Stops tracking memory usage, binder transactions, and real & cpu timing.
     * Stores collected data as type long into Bundle object for reporting.
     */
    private void endPerformanceSnapshot() {
        // Stop the timing. This must be done first before any other counting is
        // stopped.
        mSnapshotCpuTime = Process.getElapsedCpuTime() - mSnapshotCpuTime;
        mSnapshotExecTime = SystemClock.uptimeMillis() - mSnapshotExecTime;

        stopAllocCounting();

        long nativeMax = Debug.getNativeHeapSize() / 1024;
        long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
        long nativeFree = Debug.getNativeHeapFreeSize() / 1024;

        Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
        Debug.getMemoryInfo(memInfo);

        Runtime runtime = Runtime.getRuntime();

        long dalvikMax = runtime.totalMemory() / 1024;
        long dalvikFree = runtime.freeMemory() / 1024;
        long dalvikAllocated = dalvikMax - dalvikFree;

        // Add final binder counts
        Bundle binderCounts = getBinderCounts();
        for (String key : binderCounts.keySet()) {
            mPerfSnapshot.putLong(key, binderCounts.getLong(key));
        }

        // Add alloc counts
        Bundle allocCounts = getAllocCounts();
        for (String key : allocCounts.keySet()) {
            mPerfSnapshot.putLong(key, allocCounts.getLong(key));
        }

        mPerfSnapshot.putLong(METRIC_KEY_EXECUTION_TIME, mSnapshotExecTime);
        mPerfSnapshot.putLong(METRIC_KEY_CPU_TIME, mSnapshotCpuTime);

        mPerfSnapshot.putLong(METRIC_KEY_NATIVE_SIZE, nativeMax);
        mPerfSnapshot.putLong(METRIC_KEY_NATIVE_ALLOCATED, nativeAllocated);
        mPerfSnapshot.putLong(METRIC_KEY_NATIVE_FREE, nativeFree);
        mPerfSnapshot.putLong(METRIC_KEY_NATIVE_PSS, memInfo.nativePss);
        mPerfSnapshot.putLong(METRIC_KEY_NATIVE_PRIVATE_DIRTY, memInfo.nativePrivateDirty);
        mPerfSnapshot.putLong(METRIC_KEY_NATIVE_SHARED_DIRTY, memInfo.nativeSharedDirty);

        mPerfSnapshot.putLong(METRIC_KEY_JAVA_SIZE, dalvikMax);
        mPerfSnapshot.putLong(METRIC_KEY_JAVA_ALLOCATED, dalvikAllocated);
        mPerfSnapshot.putLong(METRIC_KEY_JAVA_FREE, dalvikFree);
        mPerfSnapshot.putLong(METRIC_KEY_JAVA_PSS, memInfo.dalvikPss);
        mPerfSnapshot.putLong(METRIC_KEY_JAVA_PRIVATE_DIRTY, memInfo.dalvikPrivateDirty);
        mPerfSnapshot.putLong(METRIC_KEY_JAVA_SHARED_DIRTY, memInfo.dalvikSharedDirty);

        mPerfSnapshot.putLong(METRIC_KEY_OTHER_PSS, memInfo.otherPss);
        mPerfSnapshot.putLong(METRIC_KEY_OTHER_PRIVATE_DIRTY, memInfo.otherPrivateDirty);
        mPerfSnapshot.putLong(METRIC_KEY_OTHER_SHARED_DIRTY, memInfo.otherSharedDirty);
    }

    /*
     * Starts allocation counting. This triggers a gc and resets the counts.
     */
    private static void startAllocCounting() {
        // Before we start trigger a GC and reset the debug counts. Run the
        // finalizers and another GC before starting and stopping the alloc
        // counts. This will free up any objects that were just sitting around
        // waiting for their finalizers to be run.
        Runtime.getRuntime().gc();
        Runtime.getRuntime().runFinalization();
        Runtime.getRuntime().gc();

        Debug.resetAllCounts();

        // start the counts
        Debug.startAllocCounting();
    }

    /*
     * Stops allocation counting.
     */
    private static void stopAllocCounting() {
        Runtime.getRuntime().gc();
        Runtime.getRuntime().runFinalization();
        Runtime.getRuntime().gc();
        Debug.stopAllocCounting();
    }

    /*
     * Returns a bundle with the current results from the allocation counting.
     */
    private static Bundle getAllocCounts() {
        Bundle results = new Bundle();
        results.putLong(METRIC_KEY_GLOBAL_ALLOC_COUNT, Debug.getGlobalAllocCount());
        results.putLong(METRIC_KEY_GLOBAL_ALLOC_SIZE, Debug.getGlobalAllocSize());
        results.putLong(METRIC_KEY_GLOBAL_FREED_COUNT, Debug.getGlobalFreedCount());
        results.putLong(METRIC_KEY_GLOBAL_FREED_SIZE, Debug.getGlobalFreedSize());
        results.putLong(METRIC_KEY_GC_INVOCATION_COUNT, Debug.getGlobalGcInvocationCount());
        return results;
    }

    /*
     * Returns a bundle with the counts for various binder counts for this
     * process. Currently the only two that are reported are the number of send
     * and the number of received transactions.
     */
    private static Bundle getBinderCounts() {
        Bundle results = new Bundle();
        results.putLong(METRIC_KEY_SENT_TRANSACTIONS, Debug.getBinderSentTransactions());
        results.putLong(METRIC_KEY_RECEIVED_TRANSACTIONS, Debug.getBinderReceivedTransactions());
        return results;
    }
}

Other Android examples (source code examples)

Here is a short list of links related to this Android PerformanceCollector.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.