Home | History | Annotate | Download | only in os
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.os;
     18 
     19 import android.util.Log;
     20 
     21 import java.util.HashMap;
     22 
     23 /**
     24  * A class to help with measuring latency in your code.
     25  *
     26  * Suggested usage:
     27  * 1) Instanciate a LatencyTimer as a class field.
     28  *      private [static] LatencyTimer mLt = new LatencyTimer(100, 1000);
     29  * 2) At various points in the code call sample with a string and the time delta to some fixed time.
     30  *    The string should be unique at each point of the code you are measuring.
     31  *      mLt.sample("before processing event", System.nanoTime() - event.getEventTimeNano());
     32  *      processEvent(event);
     33  *      mLt.sample("after processing event ", System.nanoTime() - event.getEventTimeNano());
     34  *
     35  * @hide
     36  */
     37 public final class LatencyTimer
     38 {
     39     final String TAG = "LatencyTimer";
     40     final int mSampleSize;
     41     final int mScaleFactor;
     42     volatile HashMap<String, long[]> store = new HashMap<String, long[]>();
     43 
     44     /**
     45     * Creates a LatencyTimer object
     46     * @param sampleSize number of samples to collect before printing out the average
     47     * @param scaleFactor divisor used to make each sample smaller to prevent overflow when
     48     *        (sampleSize * average sample value)/scaleFactor > Long.MAX_VALUE
     49     */
     50     public LatencyTimer(int sampleSize, int scaleFactor) {
     51         if (scaleFactor == 0) {
     52             scaleFactor = 1;
     53         }
     54         mScaleFactor = scaleFactor;
     55         mSampleSize = sampleSize;
     56     }
     57 
     58     /**
     59      * Add a sample delay for averaging.
     60      * @param tag string used for printing out the result. This should be unique at each point of
     61      *  this called.
     62      * @param delta time difference from an unique point of reference for a particular iteration
     63      */
     64     public void sample(String tag, long delta) {
     65         long[] array = getArray(tag);
     66 
     67         // array[mSampleSize] holds the number of used entries
     68         final int index = (int) array[mSampleSize]++;
     69         array[index] = delta;
     70         if (array[mSampleSize] == mSampleSize) {
     71             long totalDelta = 0;
     72             for (long d : array) {
     73                 totalDelta += d/mScaleFactor;
     74             }
     75             array[mSampleSize] = 0;
     76             Log.i(TAG, tag + " average = " + totalDelta / mSampleSize);
     77         }
     78     }
     79 
     80     private long[] getArray(String tag) {
     81         long[] data = store.get(tag);
     82         if (data == null) {
     83             synchronized(store) {
     84                 data = store.get(tag);
     85                 if (data == null) {
     86                     data = new long[mSampleSize + 1];
     87                     store.put(tag, data);
     88                     data[mSampleSize] = 0;
     89                 }
     90             }
     91         }
     92         return data;
     93     }
     94 }
     95