1*d57664e9SAndroid Build Coastguard Worker /* 2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2008 The Android Open Source Project 3*d57664e9SAndroid Build Coastguard Worker * 4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*d57664e9SAndroid Build Coastguard Worker * 8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*d57664e9SAndroid Build Coastguard Worker * 10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*d57664e9SAndroid Build Coastguard Worker * limitations under the License. 15*d57664e9SAndroid Build Coastguard Worker */ 16*d57664e9SAndroid Build Coastguard Worker 17*d57664e9SAndroid Build Coastguard Worker import java.util.List; 18*d57664e9SAndroid Build Coastguard Worker import java.util.ArrayList; 19*d57664e9SAndroid Build Coastguard Worker import java.io.Serializable; 20*d57664e9SAndroid Build Coastguard Worker 21*d57664e9SAndroid Build Coastguard Worker /** 22*d57664e9SAndroid Build Coastguard Worker * An operation with a duration. Could represent a class load or initialization. 23*d57664e9SAndroid Build Coastguard Worker */ 24*d57664e9SAndroid Build Coastguard Worker class Operation implements Serializable { 25*d57664e9SAndroid Build Coastguard Worker 26*d57664e9SAndroid Build Coastguard Worker private static final long serialVersionUID = 0; 27*d57664e9SAndroid Build Coastguard Worker 28*d57664e9SAndroid Build Coastguard Worker /** 29*d57664e9SAndroid Build Coastguard Worker * Type of operation. 30*d57664e9SAndroid Build Coastguard Worker */ 31*d57664e9SAndroid Build Coastguard Worker enum Type { 32*d57664e9SAndroid Build Coastguard Worker LOAD, INIT 33*d57664e9SAndroid Build Coastguard Worker } 34*d57664e9SAndroid Build Coastguard Worker 35*d57664e9SAndroid Build Coastguard Worker /** Process this operation occurred in. */ 36*d57664e9SAndroid Build Coastguard Worker final Proc process; 37*d57664e9SAndroid Build Coastguard Worker 38*d57664e9SAndroid Build Coastguard Worker /** Start time for this operation. */ 39*d57664e9SAndroid Build Coastguard Worker final long startTimeNanos; 40*d57664e9SAndroid Build Coastguard Worker 41*d57664e9SAndroid Build Coastguard Worker /** Index of this operation relative to its process. */ 42*d57664e9SAndroid Build Coastguard Worker final int index; 43*d57664e9SAndroid Build Coastguard Worker 44*d57664e9SAndroid Build Coastguard Worker /** Type of operation. */ 45*d57664e9SAndroid Build Coastguard Worker final Type type; 46*d57664e9SAndroid Build Coastguard Worker 47*d57664e9SAndroid Build Coastguard Worker /** End time for this operation. */ 48*d57664e9SAndroid Build Coastguard Worker long endTimeNanos = -1; 49*d57664e9SAndroid Build Coastguard Worker 50*d57664e9SAndroid Build Coastguard Worker /** The class that this operation loaded or initialized. */ 51*d57664e9SAndroid Build Coastguard Worker final LoadedClass loadedClass; 52*d57664e9SAndroid Build Coastguard Worker 53*d57664e9SAndroid Build Coastguard Worker /** Other operations that occurred during this one. */ 54*d57664e9SAndroid Build Coastguard Worker final List<Operation> subops = new ArrayList<Operation>(); 55*d57664e9SAndroid Build Coastguard Worker 56*d57664e9SAndroid Build Coastguard Worker /** Constructs a new operation. */ Operation(Proc process, LoadedClass loadedClass, long startTimeNanos, int index, Type type)57*d57664e9SAndroid Build Coastguard Worker Operation(Proc process, LoadedClass loadedClass, long startTimeNanos, 58*d57664e9SAndroid Build Coastguard Worker int index, Type type) { 59*d57664e9SAndroid Build Coastguard Worker this.process = process; 60*d57664e9SAndroid Build Coastguard Worker this.loadedClass = loadedClass; 61*d57664e9SAndroid Build Coastguard Worker this.startTimeNanos = startTimeNanos; 62*d57664e9SAndroid Build Coastguard Worker this.index = index; 63*d57664e9SAndroid Build Coastguard Worker this.type = type; 64*d57664e9SAndroid Build Coastguard Worker } 65*d57664e9SAndroid Build Coastguard Worker 66*d57664e9SAndroid Build Coastguard Worker /** 67*d57664e9SAndroid Build Coastguard Worker * Returns how long this class initialization and all the nested class 68*d57664e9SAndroid Build Coastguard Worker * initializations took. 69*d57664e9SAndroid Build Coastguard Worker */ inclusiveTimeNanos()70*d57664e9SAndroid Build Coastguard Worker private long inclusiveTimeNanos() { 71*d57664e9SAndroid Build Coastguard Worker if (endTimeNanos == -1) { 72*d57664e9SAndroid Build Coastguard Worker throw new IllegalStateException("End time hasn't been set yet: " 73*d57664e9SAndroid Build Coastguard Worker + loadedClass.name); 74*d57664e9SAndroid Build Coastguard Worker } 75*d57664e9SAndroid Build Coastguard Worker 76*d57664e9SAndroid Build Coastguard Worker return endTimeNanos - startTimeNanos; 77*d57664e9SAndroid Build Coastguard Worker } 78*d57664e9SAndroid Build Coastguard Worker 79*d57664e9SAndroid Build Coastguard Worker /** 80*d57664e9SAndroid Build Coastguard Worker * Returns how long this class initialization took. 81*d57664e9SAndroid Build Coastguard Worker */ exclusiveTimeMicros()82*d57664e9SAndroid Build Coastguard Worker int exclusiveTimeMicros() { 83*d57664e9SAndroid Build Coastguard Worker long exclusive = inclusiveTimeNanos(); 84*d57664e9SAndroid Build Coastguard Worker 85*d57664e9SAndroid Build Coastguard Worker for (Operation child : subops) { 86*d57664e9SAndroid Build Coastguard Worker exclusive -= child.inclusiveTimeNanos(); 87*d57664e9SAndroid Build Coastguard Worker } 88*d57664e9SAndroid Build Coastguard Worker 89*d57664e9SAndroid Build Coastguard Worker if (exclusive < 0) { 90*d57664e9SAndroid Build Coastguard Worker throw new AssertionError(loadedClass.name); 91*d57664e9SAndroid Build Coastguard Worker } 92*d57664e9SAndroid Build Coastguard Worker 93*d57664e9SAndroid Build Coastguard Worker return nanosToMicros(exclusive); 94*d57664e9SAndroid Build Coastguard Worker } 95*d57664e9SAndroid Build Coastguard Worker 96*d57664e9SAndroid Build Coastguard Worker /** Gets the median time that this operation took across all processes. */ medianExclusiveTimeMicros()97*d57664e9SAndroid Build Coastguard Worker int medianExclusiveTimeMicros() { 98*d57664e9SAndroid Build Coastguard Worker switch (type) { 99*d57664e9SAndroid Build Coastguard Worker case LOAD: return loadedClass.medianLoadTimeMicros(); 100*d57664e9SAndroid Build Coastguard Worker case INIT: return loadedClass.medianInitTimeMicros(); 101*d57664e9SAndroid Build Coastguard Worker default: throw new AssertionError(); 102*d57664e9SAndroid Build Coastguard Worker } 103*d57664e9SAndroid Build Coastguard Worker } 104*d57664e9SAndroid Build Coastguard Worker 105*d57664e9SAndroid Build Coastguard Worker /** 106*d57664e9SAndroid Build Coastguard Worker * Converts nanoseconds to microseconds. 107*d57664e9SAndroid Build Coastguard Worker * 108*d57664e9SAndroid Build Coastguard Worker * @throws RuntimeException if overflow occurs 109*d57664e9SAndroid Build Coastguard Worker */ nanosToMicros(long nanos)110*d57664e9SAndroid Build Coastguard Worker private static int nanosToMicros(long nanos) { 111*d57664e9SAndroid Build Coastguard Worker long micros = nanos / 1000; 112*d57664e9SAndroid Build Coastguard Worker int microsInt = (int) micros; 113*d57664e9SAndroid Build Coastguard Worker if (microsInt != micros) { 114*d57664e9SAndroid Build Coastguard Worker throw new RuntimeException("Integer overflow: " + nanos); 115*d57664e9SAndroid Build Coastguard Worker } 116*d57664e9SAndroid Build Coastguard Worker return microsInt; 117*d57664e9SAndroid Build Coastguard Worker } 118*d57664e9SAndroid Build Coastguard Worker 119*d57664e9SAndroid Build Coastguard Worker /** 120*d57664e9SAndroid Build Coastguard Worker * Primarily for debugger support 121*d57664e9SAndroid Build Coastguard Worker */ 122*d57664e9SAndroid Build Coastguard Worker @Override toString()123*d57664e9SAndroid Build Coastguard Worker public String toString() { 124*d57664e9SAndroid Build Coastguard Worker StringBuilder sb = new StringBuilder(); 125*d57664e9SAndroid Build Coastguard Worker sb.append(type.toString()); 126*d57664e9SAndroid Build Coastguard Worker sb.append(' '); 127*d57664e9SAndroid Build Coastguard Worker sb.append(loadedClass.toString()); 128*d57664e9SAndroid Build Coastguard Worker if (subops.size() > 0) { 129*d57664e9SAndroid Build Coastguard Worker sb.append(" ("); 130*d57664e9SAndroid Build Coastguard Worker sb.append(subops.size()); 131*d57664e9SAndroid Build Coastguard Worker sb.append(" sub ops)"); 132*d57664e9SAndroid Build Coastguard Worker } 133*d57664e9SAndroid Build Coastguard Worker return sb.toString(); 134*d57664e9SAndroid Build Coastguard Worker } 135*d57664e9SAndroid Build Coastguard Worker 136*d57664e9SAndroid Build Coastguard Worker } 137