blob: 6b3d3454cfc98b8ed43728cadaf6b52d96579733 [file] [log] [blame]
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001/*
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
17import java.util.List;
18import java.util.ArrayList;
19import java.util.Arrays;
20import java.util.Set;
21import java.util.HashSet;
22import java.io.Serializable;
23
24/**
25 * A loaded class.
26 */
27class LoadedClass implements Serializable, Comparable<LoadedClass> {
28
29 private static final long serialVersionUID = 0;
30
31 /** Class name. */
32 final String name;
33
34 /** Load operations. */
35 final List<Operation> loads = new ArrayList<Operation>();
36
37 /** Static initialization operations. */
38 final List<Operation> initializations = new ArrayList<Operation>();
39
40 /** Memory usage gathered by loading only this class in its own VM. */
41 MemoryUsage memoryUsage = MemoryUsage.NOT_AVAILABLE;
42
43 /**
44 * Whether or not this class was loaded in the system class loader.
45 */
46 final boolean systemClass;
47
48 /** Whether or not this class will be preloaded. */
49 boolean preloaded;
50
51 /** Constructs a new class. */
52 LoadedClass(String name, boolean systemClass) {
53 this.name = name;
54 this.systemClass = systemClass;
55 }
56
57 void measureMemoryUsage() {
58 this.memoryUsage = MemoryUsage.forClass(name);
59 }
60
61 int mlt = -1;
62
63 /** Median time to load this class. */
64 int medianLoadTimeMicros() {
65 if (mlt != -1) {
66 return mlt;
67 }
68
69 return mlt = calculateMedian(loads);
70 }
71
72 int mit = -1;
73
74 /** Median time to initialize this class. */
75 int medianInitTimeMicros() {
76 if (mit != -1) {
77 return mit;
78 }
79
80 return mit = calculateMedian(initializations);
81 }
82
83 /** Calculates the median duration for a list of operations. */
84 private static int calculateMedian(List<Operation> operations) {
85 int size = operations.size();
86 if (size == 0) {
87 return 0;
88 }
89
90 int[] times = new int[size];
91 for (int i = 0; i < size; i++) {
92 times[i] = operations.get(i).exclusiveTimeMicros();
93 }
94
95 Arrays.sort(times);
96 int middle = size / 2;
97 if (size % 2 == 1) {
98 // Odd
99 return times[middle];
100 } else {
101 // Even -- average the two.
102 return (times[middle - 1] + times[middle]) / 2;
103 }
104 }
105
106 /**
107 * Counts loads by apps.
108 */
109 int appLoads() {
110 return operationsByApps(loads);
111 }
112
113 /**
114 * Counts inits by apps.
115 */
116 int appInits() {
117 return operationsByApps(initializations);
118 }
119
120 /**
121 * Counts number of app operations in the given list.
122 */
123 private static int operationsByApps(List<Operation> operations) {
124 int byApps = 0;
125 for (Operation operation : operations) {
126 if (operation.process.isApplication()) {
127 byApps++;
128 }
129 }
130 return byApps;
131 }
132
133 public int compareTo(LoadedClass o) {
134 return name.compareTo(o.name);
135 }
136
137 public String toString() {
138 return name;
139 }
140
141 /**
142 * Returns true if this class's initialization causes the given class to
143 * initialize.
144 */
145 public boolean initializes(LoadedClass clazz, Set<LoadedClass> visited) {
146 // Avoid infinite recursion.
147 if (!visited.add(this)) {
148 return false;
149 }
150
151 if (clazz == this) {
152 return true;
153 }
154
155 for (Operation initialization : initializations) {
156 if (initialization.loadedClass.initializes(clazz, visited)) {
157 return true;
158 }
159 }
160
161 return false;
162 }
163}