1cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom/* 2cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Copyright (C) 2010 The Android Open Source Project 3cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * 4cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 5cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * you may not use this file except in compliance with the License. 6cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * You may obtain a copy of the License at 7cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * 8cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 9cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * 10cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Unless required by applicable law or agreed to in writing, software 11cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 12cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * See the License for the specific language governing permissions and 14cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * limitations under the License. 15cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 16cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 17cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrompackage dalvik.system.profiler; 18cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 19cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.ArrayList; 20cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.Arrays; 21cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.Collections; 22cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.HashMap; 23cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.HashSet; 24cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.List; 25cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.Map.Entry; 26cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.Map; 27cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.Set; 28cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 29cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom/** 30cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Represents sampling profiler data. Can be converted to ASCII or 31cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * binary hprof-style output using {@link AsciiHprofWriter} or 32cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * {@link BinaryHprofWriter}. 33cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * <p> 34cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * The data includes: 35cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * <ul> 36cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * <li>the start time of the last sampling period 37cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * <li>the history of thread start and end events 38cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * <li>stack traces with frequency counts 39cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * <ul> 40cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 41cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrompublic final class HprofData { 42cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 43cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public static enum ThreadEventType { START, END }; 44cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 45cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 46cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * ThreadEvent represents thread creation and death events for 47cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * reporting. It provides a record of the thread and thread group 48cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * names for tying samples back to their source thread. 49cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 50cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public static final class ThreadEvent { 51cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 52cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public final ThreadEventType type; 53cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public final int objectId; 54cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public final int threadId; 55cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public final String threadName; 56cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public final String groupName; 57cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public final String parentGroupName; 58cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 59cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public static ThreadEvent start(int objectId, int threadId, String threadName, 60cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String groupName, String parentGroupName) { 61cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return new ThreadEvent(ThreadEventType.START, objectId, threadId, 62cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom threadName, groupName, parentGroupName); 63cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 64cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 65cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public static ThreadEvent end(int threadId) { 66cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return new ThreadEvent(ThreadEventType.END, threadId); 67cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 68cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 69cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private ThreadEvent(ThreadEventType type, int objectId, int threadId, 70cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String threadName, String groupName, String parentGroupName) { 71cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (threadName == null) { 72cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new NullPointerException("threadName == null"); 73cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 74cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.type = ThreadEventType.START; 75cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.objectId = objectId; 76cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.threadId = threadId; 77cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.threadName = threadName; 78cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.groupName = groupName; 79cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.parentGroupName = parentGroupName; 80cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 81cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 82cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private ThreadEvent(ThreadEventType type, int threadId) { 83cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.type = ThreadEventType.END; 84cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.objectId = -1; 85cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.threadId = threadId; 86cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.threadName = null; 87cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.groupName = null; 88cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.parentGroupName = null; 89cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 90cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 91cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom @Override public int hashCode() { 92cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int result = 17; 93cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom result = 31 * result + objectId; 94cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom result = 31 * result + threadId; 95cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom result = 31 * result + hashCode(threadName); 96cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom result = 31 * result + hashCode(groupName); 97cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom result = 31 * result + hashCode(parentGroupName); 98cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return result; 99cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 100cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 101cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private static int hashCode(Object o) { 102cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return (o == null) ? 0 : o.hashCode(); 103cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 104cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 105cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom @Override public boolean equals(Object o) { 106cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (!(o instanceof ThreadEvent)) { 107cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return false; 108cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 109cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom ThreadEvent event = (ThreadEvent) o; 110cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return (this.type == event.type 111cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom && this.objectId == event.objectId 112cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom && this.threadId == event.threadId 113cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom && equal(this.threadName, event.threadName) 114cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom && equal(this.groupName, event.groupName) 115cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom && equal(this.parentGroupName, event.parentGroupName)); 116cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 117cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 118cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private static boolean equal(Object a, Object b) { 119cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return a == b || (a != null && a.equals(b)); 120cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 121cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 122cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom @Override public String toString() { 123cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom switch (type) { 124cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case START: 125cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return String.format( 126cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom "THREAD START (obj=%d, id = %d, name=\"%s\", group=\"%s\")", 127cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom objectId, threadId, threadName, groupName); 128cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case END: 129cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return String.format("THREAD END (id = %d)", threadId); 130cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 131cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new IllegalStateException(type.toString()); 132cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 133cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 134cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 135cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 136cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * A unique stack trace for a specific thread. 137cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 138cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public static final class StackTrace { 139cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 140cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public final int stackTraceId; 141cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int threadId; 142cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom StackTraceElement[] stackFrames; 143cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 144cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom StackTrace() { 145cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.stackTraceId = -1; 146cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 147cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 148cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public StackTrace(int stackTraceId, int threadId, StackTraceElement[] stackFrames) { 149cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (stackFrames == null) { 150cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new NullPointerException("stackFrames == null"); 151cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 152cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.stackTraceId = stackTraceId; 153cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.threadId = threadId; 154cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.stackFrames = stackFrames; 155cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 156cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 157cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public int getThreadId() { 158cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return threadId; 159cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 160cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 161cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public StackTraceElement[] getStackFrames() { 162cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return stackFrames; 163cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 164cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 165cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom @Override public int hashCode() { 166cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int result = 17; 167cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom result = 31 * result + threadId; 168cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom result = 31 * result + Arrays.hashCode(stackFrames); 169cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return result; 170cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 171cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 172cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom @Override public boolean equals(Object o) { 173cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (!(o instanceof StackTrace)) { 174cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return false; 175cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 176cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom StackTrace s = (StackTrace) o; 177cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return threadId == s.threadId && Arrays.equals(stackFrames, s.stackFrames); 178cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 179cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 180cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom @Override public String toString() { 181cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom StringBuilder frames = new StringBuilder(); 182cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (stackFrames.length > 0) { 183cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom frames.append('\n'); 184cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom for (StackTraceElement stackFrame : stackFrames) { 185cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom frames.append("\t at "); 186cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom frames.append(stackFrame); 187cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom frames.append('\n'); 188cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 189cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } else { 190cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom frames.append("<empty>"); 191cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 192cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return "StackTrace[stackTraceId=" + stackTraceId 193cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + ", threadId=" + threadId 194cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + ", frames=" + frames + "]"; 195cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 196cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 197cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 198cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 199cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 200cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * A read only container combining a stack trace with its frequency. 201cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 202cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public static final class Sample { 203cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 204cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public final StackTrace stackTrace; 205cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public final int count; 206cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 207cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private Sample(StackTrace stackTrace, int count) { 208cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (stackTrace == null) { 209cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new NullPointerException("stackTrace == null"); 210cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 211cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (count < 0) { 212cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new IllegalArgumentException("count < 0:" + count); 213cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 214cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.stackTrace = stackTrace; 215cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.count = count; 216cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 217cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 218cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom @Override public int hashCode() { 219cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int result = 17; 220cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom result = 31 * result + stackTrace.hashCode(); 221cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom result = 31 * result + count; 222cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return result; 223cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 224cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 225cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom @Override public boolean equals(Object o) { 226cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (!(o instanceof Sample)) { 227cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return false; 228cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 229cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom Sample s = (Sample) o; 230cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return count == s.count && stackTrace.equals(s.stackTrace); 231cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 232cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 233cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom @Override public String toString() { 234cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return "Sample[count=" + count + " " + stackTrace + "]"; 235cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 236cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 237cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 238cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 239cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 240cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Start of last sampling period. 241cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 242cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private long startMillis; 243cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 244cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 245cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * CONTROL_SETTINGS flags 246cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 247cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private int flags; 248cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 249cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 250cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * stack sampling depth 251cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 252cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private int depth; 253cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 254cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 255cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * List of thread creation and death events. 256cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 257cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final List<ThreadEvent> threadHistory = new ArrayList<ThreadEvent>(); 258cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 259cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 260cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Map of thread id to a start ThreadEvent 261cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 262cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final Map<Integer, ThreadEvent> threadIdToThreadEvent 263cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom = new HashMap<Integer, ThreadEvent>(); 264cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 265cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 266cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Map of stack traces to a mutable sample count. The map is 267cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * provided by the creator of the HprofData so only have 268cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * mutable access to the int[] cells that contain the sample 269cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * count. Only an unmodifiable iterator view is available to 270cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * users of the HprofData. 271cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 272cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final Map<HprofData.StackTrace, int[]> stackTraces; 273cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 274cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public HprofData(Map<StackTrace, int[]> stackTraces) { 275cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (stackTraces == null) { 276cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new NullPointerException("stackTraces == null"); 277cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 278cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.stackTraces = stackTraces; 279cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 280cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 281cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 282cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * The start time in milliseconds of the last profiling period. 283cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 284cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public long getStartMillis() { 285cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return startMillis; 286cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 287cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 288cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 289cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Set the time for the start of the current sampling period. 290cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 291cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public void setStartMillis(long startMillis) { 292cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.startMillis = startMillis; 293cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 294cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 295cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 296cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Get the {@link BinaryHprof.ControlSettings} flags 297cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 298cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public int getFlags() { 299cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return flags; 300cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 301cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 302cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 303cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Set the {@link BinaryHprof.ControlSettings} flags 304cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 305cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public void setFlags(int flags) { 306cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.flags = flags; 307cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 308cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 309cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 310cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Get the stack sampling depth 311cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 312cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public int getDepth() { 313cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return depth; 314cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 315cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 316cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 317cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Set the stack sampling depth 318cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 319cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public void setDepth(int depth) { 320cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.depth = depth; 321cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 322cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 323cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 324cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Return an unmodifiable history of start and end thread events. 325cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 326cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public List<ThreadEvent> getThreadHistory() { 327cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return Collections.unmodifiableList(threadHistory); 328cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 329cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 330cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 331cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Return a new set containing the current sample data. 332cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 333cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public Set<Sample> getSamples() { 334cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom Set<Sample> samples = new HashSet<Sample>(stackTraces.size()); 335cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom for (Entry<StackTrace, int[]> e : stackTraces.entrySet()) { 336cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom StackTrace stackTrace = e.getKey(); 337cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int countCell[] = e.getValue(); 338cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int count = countCell[0]; 339cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom Sample sample = new Sample(stackTrace, count); 340cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom samples.add(sample); 341cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 342cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return samples; 343cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 344cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 345cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 346cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Record an event in the thread history. 347cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 348cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public void addThreadEvent(ThreadEvent event) { 349cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (event == null) { 350cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new NullPointerException("event == null"); 351cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 352cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom ThreadEvent old = threadIdToThreadEvent.put(event.threadId, event); 353cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom switch (event.type) { 354cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case START: 355cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (old != null) { 356cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new IllegalArgumentException("ThreadEvent already registered for id " 357cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + event.threadId); 358cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 359cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom break; 360cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case END: 361cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // Do not assert that the END_THREAD matches a 362cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // START_THREAD unless in strict mode. While thhis 363cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // hold true in the binary hprof BinaryHprofWriter 364cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // produces, it is not true of hprof files created 365cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // by the RI. However, if there is an event 366cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // already registed for a thread id, it should be 367cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // the matching start, not a duplicate end. 368cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (old != null && old.type == ThreadEventType.END) { 369cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new IllegalArgumentException("Duplicate ThreadEvent.end for id " 370cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + event.threadId); 371cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 372cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom break; 373cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 374cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom threadHistory.add(event); 375cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 376cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 377cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 378cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Record an stack trace and an associated int[] cell of 379cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * sample cound for the stack trace. The caller is allowed 380cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * retain a pointer to the cell to update the count. The 381cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * SamplingProfiler intentionally does not present a mutable 382cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * view of the count. 383cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 384cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public void addStackTrace(StackTrace stackTrace, int[] countCell) { 385cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (!threadIdToThreadEvent.containsKey(stackTrace.threadId)) { 386cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new IllegalArgumentException("Unknown thread id " + stackTrace.threadId); 387cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 388cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int[] old = stackTraces.put(stackTrace, countCell); 389cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (old != null) { 390cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new IllegalArgumentException("StackTrace already registered for id " 391cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + stackTrace.stackTraceId + ":\n" + stackTrace); 392cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 393cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 394cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom} 395