1 /*
2  * Copyright (C) 2008 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 import java.util.List;
18 import java.util.ArrayList;
19 import java.io.Serializable;
20 
21 /**
22  * An operation with a duration. Could represent a class load or initialization.
23  */
24 class Operation implements Serializable {
25 
26     private static final long serialVersionUID = 0;
27 
28     /**
29      * Type of operation.
30      */
31     enum Type {
32         LOAD, INIT
33     }
34 
35     /** Process this operation occurred in. */
36     final Proc process;
37 
38     /** Start time for this operation. */
39     final long startTimeNanos;
40 
41     /** Index of this operation relative to its process. */
42     final int index;
43 
44     /** Type of operation. */
45     final Type type;
46 
47     /** End time for this operation. */
48     long endTimeNanos = -1;
49 
50     /** The class that this operation loaded or initialized. */
51     final LoadedClass loadedClass;
52 
53     /** Other operations that occurred during this one. */
54     final List<Operation> subops = new ArrayList<Operation>();
55 
56     /** Constructs a new operation. */
Operation(Proc process, LoadedClass loadedClass, long startTimeNanos, int index, Type type)57     Operation(Proc process, LoadedClass loadedClass, long startTimeNanos,
58             int index, Type type) {
59         this.process = process;
60         this.loadedClass = loadedClass;
61         this.startTimeNanos = startTimeNanos;
62         this.index = index;
63         this.type = type;
64     }
65 
66     /**
67      * Returns how long this class initialization and all the nested class
68      * initializations took.
69      */
inclusiveTimeNanos()70     private long inclusiveTimeNanos() {
71         if (endTimeNanos == -1) {
72             throw new IllegalStateException("End time hasn't been set yet: "
73                     + loadedClass.name);
74         }
75 
76         return endTimeNanos - startTimeNanos;
77     }
78 
79     /**
80      * Returns how long this class initialization took.
81      */
exclusiveTimeMicros()82     int exclusiveTimeMicros() {
83         long exclusive = inclusiveTimeNanos();
84 
85         for (Operation child : subops) {
86             exclusive -= child.inclusiveTimeNanos();
87         }
88 
89         if (exclusive < 0) {
90             throw new AssertionError(loadedClass.name);
91         }
92 
93         return nanosToMicros(exclusive);
94     }
95 
96     /** Gets the median time that this operation took across all processes. */
medianExclusiveTimeMicros()97     int medianExclusiveTimeMicros() {
98         switch (type) {
99             case LOAD: return loadedClass.medianLoadTimeMicros();
100             case INIT: return loadedClass.medianInitTimeMicros();
101             default: throw new AssertionError();
102         }
103     }
104 
105     /**
106      * Converts nanoseconds to microseconds.
107      *
108      * @throws RuntimeException if overflow occurs
109      */
nanosToMicros(long nanos)110     private static int nanosToMicros(long nanos) {
111         long micros = nanos / 1000;
112         int microsInt = (int) micros;
113         if (microsInt != micros) {
114             throw new RuntimeException("Integer overflow: " + nanos);
115         }
116         return microsInt;
117     }
118 
119     /**
120      * Primarily for debugger support
121      */
122     @Override
toString()123     public String toString() {
124         StringBuilder sb = new StringBuilder();
125         sb.append(type.toString());
126         sb.append(' ');
127         sb.append(loadedClass.toString());
128         if (subops.size() > 0) {
129             sb.append(" (");
130             sb.append(subops.size());
131             sb.append(" sub ops)");
132         }
133         return sb.toString();
134     }
135 
136 }
137