19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.util; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A utility class to help log timings splits throughout a method call. 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Typical usage is: 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2749afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * <pre> 2849afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * TimingLogger timings = new TimingLogger(TAG, "methodA"); 2949afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * // ... do some work A ... 3049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * timings.addSplit("work A"); 3149afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * // ... do some work B ... 3249afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * timings.addSplit("work B"); 3349afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * // ... do some work C ... 3449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * timings.addSplit("work C"); 3549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * timings.dumpToLog(); 3649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * </pre> 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3849afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * <p>The dumpToLog call would add the following to the log:</p> 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * <pre> 4149afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * D/TAG ( 3459): methodA: begin 4249afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * D/TAG ( 3459): methodA: 9 ms, work A 4349afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * D/TAG ( 3459): methodA: 1 ms, work B 4449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * D/TAG ( 3459): methodA: 6 ms, work C 4549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * D/TAG ( 3459): methodA: end, 16 ms 4649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * </pre> 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class TimingLogger { 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The Log tag to use for checking Log.isLoggable and for 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * logging the timings. 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mTag; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** A label to be included in every log. */ 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mLabel; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Used to track whether Log.isLoggable was enabled at reset time. */ 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mDisabled; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Stores the time of each split. */ 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Long> mSplits; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Stores the labels for each split. */ 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<String> mSplitLabels; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create and initialize a TimingLogger object that will log using 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the specific tag. If the Log.isLoggable is not enabled to at 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * least the Log.VERBOSE level for that tag at creation time then 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the addSplit and dumpToLog call will do nothing. 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param tag the log tag to use while logging the timings 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param label a string to be displayed with each log 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public TimingLogger(String tag, String label) { 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reset(tag, label); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Clear and initialize a TimingLogger object that will log using 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the specific tag. If the Log.isLoggable is not enabled to at 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * least the Log.VERBOSE level for that tag at creation time then 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the addSplit and dumpToLog call will do nothing. 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param tag the log tag to use while logging the timings 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param label a string to be displayed with each log 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void reset(String tag, String label) { 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTag = tag; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLabel = label; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reset(); 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Clear and initialize a TimingLogger object that will log using 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the tag and label that was specified previously, either via 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the constructor or a call to reset(tag, label). If the 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Log.isLoggable is not enabled to at least the Log.VERBOSE 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * level for that tag at creation time then the addSplit and 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * dumpToLog call will do nothing. 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void reset() { 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisabled = !Log.isLoggable(mTag, Log.VERBOSE); 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDisabled) return; 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSplits == null) { 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSplits = new ArrayList<Long>(); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSplitLabels = new ArrayList<String>(); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSplits.clear(); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSplitLabels.clear(); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addSplit(null); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Add a split for the current time, labeled with splitLabel. If 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Log.isLoggable was not enabled to at least the Log.VERBOSE for 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the specified tag at construction or reset() time then this 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * call does nothing. 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param splitLabel a label to associate with this split. 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void addSplit(String splitLabel) { 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDisabled) return; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = SystemClock.elapsedRealtime(); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSplits.add(now); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSplitLabels.add(splitLabel); 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Dumps the timings to the log using Log.d(). If Log.isLoggable was 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not enabled to at least the Log.VERBOSE for the specified tag at 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * construction or reset() time then this call does nothing. 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void dumpToLog() { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDisabled) return; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(mTag, mLabel + ": begin"); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final long first = mSplits.get(0); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = first; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 1; i < mSplits.size(); i++) { 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project now = mSplits.get(i); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final String splitLabel = mSplitLabels.get(i); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final long prev = mSplits.get(i - 1); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(mTag, mLabel + ": " + (now - prev) + " ms, " + splitLabel); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(mTag, mLabel + ": end, " + (now - first) + " ms"); 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 149