xref: /aosp_15_r20/frameworks/base/tools/preload/Operation.java (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
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