1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2008 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License.
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License.
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.List;
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.ArrayList;
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.Serializable;
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/**
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * An operation with a duration. Could represent a class load or initialization.
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass Operation implements Serializable {
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static final long serialVersionUID = 0;
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Type of operation.
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    enum Type {
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        LOAD, INIT
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** Process this operation occurred in. */
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final Proc process;
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** Start time for this operation. */
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final long startTimeNanos;
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** Index of this operation relative to its process. */
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final int index;
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** Type of operation. */
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final Type type;
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** End time for this operation. */
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    long endTimeNanos = -1;
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** The class that this operation loaded or initialized. */
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final LoadedClass loadedClass;
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** Other operations that occurred during this one. */
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    final List<Operation> subops = new ArrayList<Operation>();
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** Constructs a new operation. */
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Operation(Proc process, LoadedClass loadedClass, long startTimeNanos,
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int index, Type type) {
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.process = process;
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.loadedClass = loadedClass;
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.startTimeNanos = startTimeNanos;
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.index = index;
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this.type = type;
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns how long this class initialization and all the nested class
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * initializations took.
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private long inclusiveTimeNanos() {
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (endTimeNanos == -1) {
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            throw new IllegalStateException("End time hasn't been set yet: "
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    + loadedClass.name);
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return endTimeNanos - startTimeNanos;
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns how long this class initialization took.
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int exclusiveTimeMicros() {
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        long exclusive = inclusiveTimeNanos();
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (Operation child : subops) {
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            exclusive -= child.inclusiveTimeNanos();
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (exclusive < 0) {
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            throw new AssertionError(loadedClass.name);
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return nanosToMicros(exclusive);
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /** Gets the median time that this operation took across all processes. */
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int medianExclusiveTimeMicros() {
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        switch (type) {
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            case LOAD: return loadedClass.medianLoadTimeMicros();
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            case INIT: return loadedClass.medianInitTimeMicros();
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            default: throw new AssertionError();
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Converts nanoseconds to microseconds.
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @throws RuntimeException if overflow occurs
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static int nanosToMicros(long nanos) {
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        long micros = nanos / 1000;
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int microsInt = (int) micros;
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (microsInt != micros) {
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            throw new RuntimeException("Integer overflow: " + nanos);
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return microsInt;
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Primarily for debugger support
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public String toString() {
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        StringBuilder sb = new StringBuilder();
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sb.append(type.toString());
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sb.append(' ');
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sb.append(loadedClass.toString());
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (subops.size() > 0) {
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sb.append(" (");
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sb.append(subops.size());
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sb.append(" sub ops)");
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return sb.toString();
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
137