001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.client;
042:
043: import org.netbeans.lib.profiler.TargetAppRunner;
044: import org.netbeans.lib.profiler.global.ProfilingSessionStatus;
045: import org.netbeans.lib.profiler.wireprotocol.MonitoredNumbersResponse;
046:
047: /**
048: * A representation of the monitored data, returned by the server on demand, that is suitable for use by
049: * presentation code.
050: *
051: * @author Tomas Hurka
052: * @author Misha Dmitriev
053: */
054: public class MonitoredData {
055: //~ Instance fields ----------------------------------------------------------------------------------------------------------
056:
057: private long[] gcFinishs;
058: private long[] gcStarts;
059:
060: // The following array contains:
061: // - the amounts of free and total memory in elements 0 and 1
062: // - the number of user and system threads in elements 2 and 3
063: // - number of surviving generations in element 4
064: // - relative time spent in GC, in per mil (1/10th of per cent), and the duration of the last GC pause (in ms) in elements 5 and 6
065: // - timestamp at the moment when this packet was generated (obtained with System.currentTimeMillis()) in element 7
066: private long[] generalMNumbers;
067: private String[] newThreadClassNames;
068: private int[] newThreadIds;
069: private String[] newThreadNames;
070: private long[] stateTimestamps;
071: private int[] threadIds;
072: private byte[][] threadStates = new byte[20][20];
073:
074: // Data on new threads. Any thread that has been created between the previous and the current use of this object
075: // shows up on the list below, but just once. nNewThreads is the real number of threads, which may be shorter than
076: // the size of the following arrays.
077: private int nNewThreads;
078: private int nThreadStates;
079:
080: // Data on thread states. nThreads is the real number of threads (dimension 0 of the following arrays), which
081: // may be shorter than the actual size of the following arrays. nStates is the number of thread states
082: // (dimension 1 of these arrays), and also may be shorter than the actual size.
083: // Thread state timestamps are expressed in milliseconds as obtained by System.currentTimeMillis() on server side.
084: // threadStates use constants defined in CommonConstants for thread states.
085: private int nThreads;
086:
087: //~ Constructors -------------------------------------------------------------------------------------------------------------
088:
089: private MonitoredData(MonitoredNumbersResponse mresp) {
090: long[] gn = mresp.getGeneralMonitoredNumbers();
091: generalMNumbers = new long[gn.length];
092: System.arraycopy(gn, 0, generalMNumbers, 0, gn.length);
093:
094: nThreads = mresp.getNThreads();
095: nThreadStates = mresp.getNThreadStates();
096:
097: int[] ids = mresp.getThreadIds();
098: threadIds = new int[nThreads];
099: System.arraycopy(ids, 0, threadIds, 0, nThreads);
100:
101: long[] ts = mresp.getStateTimestamps();
102: stateTimestamps = new long[nThreadStates];
103: System.arraycopy(ts, 0, stateTimestamps, 0, nThreadStates);
104:
105: setThreadStates(mresp.getThreadStates());
106:
107: nNewThreads = mresp.getNNewThreads();
108:
109: if (nNewThreads > 0) {
110: int[] newIds = mresp.getNewThreadIds();
111: newThreadIds = new int[nNewThreads];
112: System.arraycopy(newIds, 0, newThreadIds, 0, nNewThreads);
113: newThreadNames = new String[nNewThreads];
114: System.arraycopy(mresp.getNewThreadNames(), 0,
115: newThreadNames, 0, nNewThreads);
116: newThreadClassNames = new String[nNewThreads];
117: System.arraycopy(mresp.getNewThreadClassNames(), 0,
118: newThreadClassNames, 0, nNewThreads);
119: }
120:
121: gcStarts = mresp.getGCStarts();
122: convertToTimeInMillis(gcStarts);
123: gcFinishs = mresp.getGCFinishs();
124: convertToTimeInMillis(gcFinishs);
125: }
126:
127: //~ Methods ------------------------------------------------------------------------------------------------------------------
128:
129: public long getFreeMemory() {
130: return generalMNumbers[MonitoredNumbersResponse.FREE_MEMORY_IDX];
131: }
132:
133: public long[] getGCFinishs() {
134: return gcFinishs;
135: }
136:
137: public long[] getGCStarts() {
138: return gcStarts;
139: }
140:
141: public long getLastGCPauseInMS() {
142: return generalMNumbers[MonitoredNumbersResponse.GC_PAUSE_IDX];
143: }
144:
145: public long getLoadedClassesCount() {
146: return generalMNumbers[MonitoredNumbersResponse.LOADED_CLASSES_IDX];
147: }
148:
149: /**
150: * With mresp, the same instance is reused all the time to save memory. However, with MonitoredData we
151: * generally can't afford that, so here we create a new object every time and copy data into it.
152: */
153: public static MonitoredData getMonitoredData(
154: MonitoredNumbersResponse mresp) {
155: return new MonitoredData(mresp);
156: }
157:
158: public int getNNewThreads() {
159: return nNewThreads;
160: }
161:
162: public long getNSurvivingGenerations() {
163: return generalMNumbers[MonitoredNumbersResponse.SURVIVING_GENERATIONS_IDX];
164: }
165:
166: public long getNSystemThreads() {
167: return generalMNumbers[MonitoredNumbersResponse.SYSTEM_THREADS_IDX];
168: }
169:
170: public int getNThreadStates() {
171: return nThreadStates;
172: }
173:
174: public int getNThreads() {
175: return nThreads;
176: }
177:
178: public long getNUserThreads() {
179: return generalMNumbers[MonitoredNumbersResponse.USER_THREADS_IDX];
180: }
181:
182: public String[] getNewThreadClassNames() {
183: return newThreadClassNames;
184: }
185:
186: public int[] getNewThreadIds() {
187: return newThreadIds;
188: }
189:
190: public String[] getNewThreadNames() {
191: return newThreadNames;
192: }
193:
194: public long getRelativeGCTimeInPerMil() {
195: return generalMNumbers[MonitoredNumbersResponse.GC_TIME_IDX];
196: }
197:
198: public long[] getStateTimestamps() {
199: return stateTimestamps;
200: }
201:
202: public int[] getThreadIds() {
203: return threadIds;
204: }
205:
206: public byte[][] getThreadStates() {
207: return threadStates;
208: }
209:
210: public long getTimestamp() {
211: return generalMNumbers[MonitoredNumbersResponse.TIMESTAMP_IDX];
212: }
213:
214: public long getTotalMemory() {
215: return generalMNumbers[MonitoredNumbersResponse.TOTAL_MEMORY_IDX];
216: }
217:
218: private static void convertToTimeInMillis(
219: final long[] hiResTimeStamp) {
220: ProfilingSessionStatus session = TargetAppRunner.getDefault()
221: .getProfilingSessionStatus();
222: long statupInCounts = session.startupTimeInCounts;
223: long startupMillis = session.startupTimeMillis;
224:
225: for (int i = 0; i < hiResTimeStamp.length; i++) {
226: hiResTimeStamp[i] = startupMillis
227: + ((hiResTimeStamp[i] - statupInCounts) / (1000000000 / 1000L)); // 1 ms has 1000000000/1000 ns
228: }
229: }
230:
231: private void setThreadStates(byte[] packedStates) {
232: threadStates = new byte[nThreads][nThreadStates];
233:
234: int idx = 0;
235:
236: for (int i = 0; i < nThreads; i++) {
237: System.arraycopy(packedStates, idx, threadStates[i], 0,
238: nThreadStates);
239: idx += nThreadStates;
240: }
241: }
242:
243: /** Debugging support */
244: private void print() {
245: for (int i = 0; i < nThreads; i++) {
246: System.err.print("id = ");
247: System.err.print(threadIds[i]); // NOI18N
248: System.err.print(", states = "); // NOI18N
249:
250: for (int j = 0; j < nThreadStates; j++) {
251: System.err.print(threadStates[i][j]);
252: }
253:
254: System.err.println();
255: }
256:
257: if (nNewThreads > 0) {
258: System.err.println("New threads added: " + nNewThreads); // NOI18N
259:
260: for (int i = 0; i < nNewThreads; i++) {
261: System.err.println(" id = " + newThreadIds[i]
262: + ", name = " + newThreadNames[i]
263: + ", classname = " + newThreadClassNames[i]); // NOI18N
264: }
265: }
266:
267: System.err.println();
268: }
269: }
|