Home | History | Annotate | Download | only in preload
      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. */
     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      */
     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      */
     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. */
     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      */
    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
    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