FileDocCategorySizeDatePackage
PerfMeasurement.javaAPI DocAndroid 5.1 API10963Thu Mar 12 22:22:10 GMT 2015android.hardware.camera2.legacy

PerfMeasurement

public class PerfMeasurement extends Object
GPU and CPU performance measurement for the legacy implementation.

Measures CPU and GPU processing duration for a set of operations, and dumps the results into a file.

Rough usage:

{@code


mPerfMeasurement.startTimer();
...render a frame...
mPerfMeasurement.stopTimer();

mPerfMeasurement.dumpPerformanceData("/sdcard/my_data.txt");
}

All calls to this object must be made within the same thread, and the same GL context. PerfMeasurement cannot be used outside of a GL context. The only exception is dumpPerformanceData, which can be called outside of a valid GL context.

Fields Summary
private static final String
TAG
public static final int
DEFAULT_MAX_QUERIES
private final long
mNativeContext
private int
mCompletedQueryCount
private ArrayList
mCollectedGpuDurations
Values for completed measurements
private ArrayList
mCollectedCpuDurations
private ArrayList
mCollectedTimestamps
private Queue
mTimestampQueue
Values for in-progress measurements (waiting for async GPU results)
private Queue
mCpuDurationsQueue
private long
mStartTimeNs
private static final long
NO_DURATION_YET
The value returned by {@link #nativeGetNextGlDuration} if no new timing measurement is available since the last call.
private static final long
FAILED_TIMING
The value returned by {@link #nativeGetNextGlDuration} if timing failed for the next timing interval
Constructors Summary
public PerfMeasurement()
Create a performance measurement object with a maximum of {@value #DEFAULT_MAX_QUERIES} in-progess queries.


                      
      
        mNativeContext = nativeCreateContext(DEFAULT_MAX_QUERIES);
    
public PerfMeasurement(int maxQueries)
Create a performance measurement object with maxQueries as the maximum number of in-progress queries.

param
maxQueries maximum in-progress queries, must be larger than 0.
throws
IllegalArgumentException if maxQueries is less than 1.

        if (maxQueries < 1) throw new IllegalArgumentException("maxQueries is less than 1");
        mNativeContext = nativeCreateContext(maxQueries);
    
Methods Summary
public voidaddTimestamp(long timestamp)
Add a timestamp to a timing measurement. These are queued up and matched to completed workload measurements as they become available.

        mTimestampQueue.add(timestamp);
    
public voiddumpPerformanceData(java.lang.String path)
Dump collected data to file, and clear the stored data.

Format is a simple csv-like text file with a header, followed by a 3-column list of values in nanoseconds:

timestamp gpu_duration cpu_duration
  
  
  
....

        try (BufferedWriter dump = new BufferedWriter(new FileWriter(path))) {
            dump.write("timestamp gpu_duration cpu_duration\n");
            for (int i = 0; i < mCollectedGpuDurations.size(); i++) {
                dump.write(String.format("%d %d %d\n",
                                mCollectedTimestamps.get(i),
                                mCollectedGpuDurations.get(i),
                                mCollectedCpuDurations.get(i)));
            }
            mCollectedTimestamps.clear();
            mCollectedGpuDurations.clear();
            mCollectedCpuDurations.clear();
        } catch (IOException e) {
            Log.e(TAG, "Error writing data dump to " + path + ":" + e);
        }
    
protected voidfinalize()

        nativeDeleteContext(mNativeContext);
    
public intgetCompletedQueryCount()
Returns the number of measurements so far that returned a valid duration measurement.

        return mCompletedQueryCount;
    
private longgetNextGlDuration()
Get the next available GPU timing measurement.

Since the GPU works asynchronously, the results of a single start/stopGlTimer measurement will only be available some time after the {@link #stopTimer} call is made. Poll this method until the result becomes available. If multiple start/endTimer measurements are made in a row, the results will be available in FIFO order.

return
The measured duration of the GPU workload for the next pending query, or {@link #NO_DURATION_YET} if no queries are pending or the next pending query has not yet finished, or {@link #FAILED_TIMING} if the GPU was unable to complete the measurement.
throws
IllegalStateException If there is a GPU error.

        long duration = nativeGetNextGlDuration(mNativeContext);
        if (duration > 0) {
            mCompletedQueryCount++;
        }
        return duration;
    
public static booleanisGlTimingSupported()
Returns true if the Gl timing methods will work, false otherwise.

Must be called within a valid GL context.

        return nativeQuerySupport();
    
private static native longnativeCreateContext(int maxQueryCount)
Create a native performance measurement context.

param
maxQueryCount maximum in-progress queries; must be >= 1.

private static native voidnativeDeleteContext(long contextHandle)
Delete the native context.

Not safe to call more than once.

protected static native longnativeGetNextGlDuration(long contextHandle)
Get the next available GL duration measurement, in nanoseconds.

Must be called from the same thread as calls to {@link #nativeStartGlTimer} and {@link #nativeEndGlTimer}.

return
the next GL duration measurement, or {@link #NO_DURATION_YET} if no new measurement is available, or {@link #FAILED_TIMING} if timing failed for the next duration measurement.
throws
IllegalStateException if a GL error occurs

private static native booleannativeQuerySupport()
Query whether the relevant Gl extensions are available for Gl timing

protected static native voidnativeStartGlTimer(long contextHandle)
Start a GL timing section.

All GL commands between this method and the next {@link #nativeEndGlTimer} will be included in the timing.

Must be called from the same thread as calls to {@link #nativeEndGlTimer} and {@link #nativeGetNextGlDuration}.

throws
IllegalStateException if a GL error occurs or start is called repeatedly.

protected static native voidnativeStopGlTimer(long contextHandle)
Finish a GL timing section.

Some time after this call returns, the time the GPU took to execute all work submitted between the latest {@link #nativeStartGlTimer} and this call, will become available from calling {@link #nativeGetNextGlDuration}.

Must be called from the same thread as calls to {@link #nativeStartGlTimer} and {@link #nativeGetNextGlDuration}.

throws
IllegalStateException if a GL error occurs or stop is called before start

public voidstartTimer()
Start a GPU/CPU timing measurement.

Call before starting a rendering pass. Only one timing measurement can be active at once, so {@link #stopTimer} must be called before the next call to this method.

throws
IllegalStateException if the maximum number of queries are in progress already, or the method is called multiple times in a row, or there is a GPU error.

        nativeStartGlTimer(mNativeContext);
        mStartTimeNs = SystemClock.elapsedRealtimeNanos();
    
public voidstopTimer()
Finish a GPU/CPU timing measurement.

Call after finishing all the drawing for a rendering pass. Only one timing measurement can be active at once, so {@link #startTimer} must be called before the next call to this method.

throws
IllegalStateException if no GL timer is currently started, or there is a GPU error.

        // Complete CPU timing
        long endTimeNs = SystemClock.elapsedRealtimeNanos();
        mCpuDurationsQueue.add(endTimeNs - mStartTimeNs);
        // Complete GL timing
        nativeStopGlTimer(mNativeContext);

        // Poll to see if GL timing results have arrived; if so
        // store the results for a frame
        long duration = getNextGlDuration();
        if (duration > 0) {
            mCollectedGpuDurations.add(duration);
            mCollectedTimestamps.add(mTimestampQueue.isEmpty() ?
                    NO_DURATION_YET : mTimestampQueue.poll());
            mCollectedCpuDurations.add(mCpuDurationsQueue.isEmpty() ?
                    NO_DURATION_YET : mCpuDurationsQueue.poll());
        }
        if (duration == FAILED_TIMING) {
            // Discard timestamp and CPU measurement since GPU measurement failed
            if (!mTimestampQueue.isEmpty()) {
                mTimestampQueue.poll();
            }
            if (!mCpuDurationsQueue.isEmpty()) {
                mCpuDurationsQueue.poll();
            }
        }