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: /*
042: * CPUSnapshotTestCase.java
043: *
044: * Created on July 19, 2005, 5:20 PM
045: *
046: * To change this template, choose Tools | Options and locate the template under
047: * the Source Creation and Management node. Right-click the template and choose
048: * Open. You can then make changes to the template in the Source Editor.
049: */
050: package org.netbeans.lib.profiler.tests.jfluid.cpu;
051:
052: import org.netbeans.lib.profiler.ProfilerEngineSettings;
053: import org.netbeans.lib.profiler.TargetAppRunner;
054: import org.netbeans.lib.profiler.global.CommonConstants;
055: import org.netbeans.lib.profiler.results.EventBufferResultsProvider;
056: import org.netbeans.lib.profiler.results.ProfilingResultsDispatcher;
057: import org.netbeans.lib.profiler.results.RuntimeCCTNode;
058: import org.netbeans.lib.profiler.results.cpu.CPUCCTProvider;
059: import org.netbeans.lib.profiler.results.cpu.CPUCallGraphBuilder;
060: import org.netbeans.lib.profiler.results.cpu.CPUResultsSnapshot;
061: import org.netbeans.lib.profiler.results.cpu.FlatProfileBuilder;
062: import org.netbeans.lib.profiler.results.cpu.FlatProfileContainer;
063: import org.netbeans.lib.profiler.results.cpu.FlatProfileContainerFree;
064: import org.netbeans.lib.profiler.results.cpu.PrestimeCPUCCTNode;
065: import org.netbeans.lib.profiler.tests.jfluid.*;
066: import org.netbeans.lib.profiler.tests.jfluid.utils.*;
067: import org.netbeans.lib.profiler.utils.StringUtils;
068: import java.io.ByteArrayInputStream;
069: import java.io.ByteArrayOutputStream;
070: import java.io.DataInputStream;
071: import java.io.DataOutputStream;
072:
073: /**
074: *
075: * @author ehucka
076: */
077: public abstract class CPUSnapshotTestCase extends
078: CommonProfilerTestCase {
079: //~ Inner Classes ------------------------------------------------------------------------------------------------------------
080:
081: private class CPUResultListener implements CPUCCTProvider.Listener {
082: //~ Instance fields ------------------------------------------------------------------------------------------------------
083:
084: private final Object resultsLock = new Object();
085: private boolean hasResults = false;
086:
087: //~ Methods --------------------------------------------------------------------------------------------------------------
088:
089: public void cctEstablished(RuntimeCCTNode appRootNode) {
090: log("CCT Results established");
091:
092: synchronized (resultsLock) {
093: hasResults = true;
094: resultsLock.notify();
095: }
096: }
097:
098: public void cctReset() {
099: log("CCT Results reset");
100:
101: synchronized (resultsLock) {
102: hasResults = false;
103: resultsLock.notify();
104: }
105: }
106:
107: public boolean wait4results(long timeout) {
108: synchronized (resultsLock) {
109: if (!hasResults) {
110: try {
111: resultsLock.wait(timeout);
112: } catch (InterruptedException e) {
113: }
114: }
115:
116: return hasResults;
117: }
118: }
119: }
120:
121: //~ Constructors -------------------------------------------------------------------------------------------------------------
122:
123: /**
124: * Creates a new instance of CPUSnapshotTestCase
125: */
126: public CPUSnapshotTestCase(String name) {
127: super (name);
128: }
129:
130: //~ Methods ------------------------------------------------------------------------------------------------------------------
131:
132: protected boolean checkSerialization(CPUResultsSnapshot snapshot) {
133: try {
134: ByteArrayOutputStream baos = new ByteArrayOutputStream();
135: DataOutputStream dos = new DataOutputStream(baos);
136: snapshot.writeToStream(dos);
137: dos.close();
138:
139: byte[] bytes = baos.toByteArray();
140: ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
141: DataInputStream dis = new DataInputStream(bais);
142: CPUResultsSnapshot snapshot2 = new CPUResultsSnapshot();
143: snapshot2.readFromStream(dis);
144: dis.close();
145:
146: baos = new ByteArrayOutputStream();
147: dos = new DataOutputStream(baos);
148: snapshot2.writeToStream(dos);
149: dos.close();
150:
151: byte[] bytes2 = baos.toByteArray();
152:
153: //compare
154: if (bytes.length != bytes2.length) {
155: return false;
156: }
157:
158: for (int i = 0; i < bytes.length; i++) {
159: if (bytes[i] != bytes2[i]) {
160: return false;
161: }
162: }
163:
164: return true;
165: } catch (Exception ex) {
166: ex.printStackTrace();
167: }
168:
169: return false;
170: }
171:
172: protected void checkSumsOfCCTNodes(PrestimeCPUCCTNode node,
173: String pre, double tolerance, String[] filterout, int level) {
174: log(complete(pre + node.getNodeName(), 62)
175: + complete(StringUtils.mcsTimeToString(node
176: .getTotalTime0()), 9)
177: + " ms ("
178: + complete(StringUtils.floatPerCentToString(node
179: .getTotalTime0InPerCent()), 7) + " %) "
180: + complete(String.valueOf(node.getNCalls()), 3));
181:
182: boolean exclude = false;
183:
184: if (filterout != null) {
185: for (int i = 0; i < filterout.length; i++) {
186: if (node.getNodeName().startsWith(filterout[i])) {
187: exclude = true;
188:
189: break;
190: }
191: }
192: }
193:
194: if (!exclude) {
195: long time = 0;
196: float percent = 0.0f;
197:
198: for (int i = 0; i < node.getNChildren(); i++) {
199: PrestimeCPUCCTNode pnode = (PrestimeCPUCCTNode) (node
200: .getChild(i));
201: checkSumsOfCCTNodes(pnode, pre + " ", tolerance,
202: filterout, level + 1);
203: time += pnode.getTotalTime0();
204: percent += pnode.getTotalTime0InPerCent();
205: }
206:
207: if ((level > 1) && (node.getNChildren() > 0)) {
208: double timediff = (Math
209: .abs(time - node.getTotalTime0()) * 100.0)
210: / node.getTotalTime0();
211: double percentdiff = (Math.abs(percent
212: - node.getTotalTime0InPerCent()) * 100.0)
213: / node.getTotalTime0InPerCent();
214:
215: if ((timediff > tolerance) || (percentdiff > tolerance)) {
216: log("Time diff: " + timediff + " %");
217: log("Percent diff: " + percentdiff + " %");
218: assertTrue(
219: "Node's and sum of subnodes values differ",
220: false);
221: }
222: }
223: }
224: }
225:
226: protected int[] findThreadAndMethod(PrestimeCPUCCTNode node,
227: String[] method, String[] filterout) {
228: boolean exclude = false;
229:
230: if (filterout != null) {
231: for (int i = 0; i < filterout.length; i++) {
232: if (node.getNodeName().startsWith(filterout[i])) {
233: exclude = true;
234:
235: break;
236: }
237: }
238: }
239:
240: if (!exclude) {
241: String[] nmethod = node.getMethodClassNameAndSig();
242: boolean found = true;
243:
244: for (int i = 0; i < nmethod.length; i++) {
245: if (!nmethod[i].equals(method[i])) {
246: found = false;
247: }
248: }
249:
250: if (found) {
251: return new int[] { node.getThreadId(),
252: node.getMethodId() };
253: }
254:
255: for (int i = 0; i < node.getNChildren(); i++) {
256: PrestimeCPUCCTNode pnode = (PrestimeCPUCCTNode) (node
257: .getChild(i));
258: int[] ret = findThreadAndMethod(pnode, method,
259: filterout);
260:
261: if (ret != null) {
262: return ret;
263: }
264: }
265: }
266:
267: return null;
268: }
269:
270: protected ProfilerEngineSettings initSnapshotTest(
271: String projectName, String mainClass, String[][] rootMethods) {
272: ProfilerEngineSettings settings = initTest(projectName,
273: mainClass, rootMethods);
274: //defaults
275: settings.setCPUProfilingType(CommonConstants.CPU_INSTR_FULL);
276: settings.setInstrScheme(CommonConstants.INSTRSCHEME_TOTAL);
277: settings.setInstrumentEmptyMethods(false);
278: settings.setInstrumentGetterSetterMethods(false);
279: settings.setInstrumentMethodInvoke(true);
280: settings.setInstrumentSpawnedThreads(true);
281: settings.setExcludeWaitTime(true);
282: //addJVMArgs(settings, "-Dorg.netbeans.lib.profiler.wireprotocol.WireIO=true");
283: settings.setThreadCPUTimerOn(false);
284: settings.setCPUProfilingType(CommonConstants.CPU_INSTR_FULL);
285:
286: return settings;
287: }
288:
289: protected void refOfCCTNodes(PrestimeCPUCCTNode node, String pre,
290: boolean time, boolean percent, boolean invocations) {
291: ref(complete(pre + node.getNodeName(), 62)
292: + ((!time) ? "" : (complete(String.valueOf(node
293: .getTotalTime0() / 1000.0), 9) + " ms "))
294: + ((!percent) ? "" : (complete(String.valueOf(node
295: .getTotalTime0InPerCent()), 7) + " % "))
296: + ((!invocations) ? "" : complete(String.valueOf(node
297: .getNCalls()), 3)));
298:
299: for (int i = 0; i < node.getNChildren(); i++) {
300: PrestimeCPUCCTNode pnode = (PrestimeCPUCCTNode) (node
301: .getChild(i));
302: refOfCCTNodes(pnode, pre + " ", time, percent, invocations);
303: }
304: }
305:
306: protected void startSnapshotTest(ProfilerEngineSettings settings,
307: String[] reverseMethod, long initDelay, double diffPercent,
308: String[] filterout) {
309: CPUCallGraphBuilder builder = new CPUCallGraphBuilder();
310:
311: assertTrue(builder != null);
312:
313: TargetAppRunner runner = new TargetAppRunner(settings,
314: new TestProfilerAppHandler(this ),
315: new TestProfilingPointsProcessor());
316: runner.addProfilingEventListener(Utils
317: .createProfilingListener(this ));
318:
319: builder.removeAllListeners();
320: ProfilingResultsDispatcher.getDefault().removeAllListeners();
321:
322: CPUResultListener resultListener = new CPUResultListener();
323: builder.addListener(resultListener);
324:
325: FlatProfileBuilder flattener = new FlatProfileBuilder();
326: builder.addListener(flattener);
327: flattener.setContext(runner.getProfilerClient());
328:
329: ProfilingResultsDispatcher.getDefault().addListener(builder);
330:
331: builder.startup(runner.getProfilerClient());
332: EventBufferResultsProvider.getDefault().startup(
333: runner.getProfilerClient());
334:
335: try {
336: runner.readSavedCalibrationData();
337:
338: Process p = startTargetVM(runner);
339: assertNotNull("Target JVM is not started", p);
340: bindStreams(p);
341: runner.connectToStartedVMAndStartTA();
342:
343: runner.getProfilerClient()
344: .initiateRecursiveCPUProfInstrumentation(
345: settings.getInstrumentationRootMethods());
346:
347: waitForStatus(STATUS_RUNNING);
348: assertTrue("runner is not running", runner
349: .targetAppIsRunning());
350:
351: if (initDelay == 0) {
352: waitForStatus(STATUS_APP_FINISHED);
353: } else {
354: Thread.sleep(initDelay);
355: }
356:
357: if (runner.targetJVMIsAlive()) {
358: log("obtaining results "
359: + String.valueOf(System.currentTimeMillis()));
360: assertTrue("Results do not exist - issue 65185.",
361: runner.getProfilerClient().cpuResultsExist());
362:
363: CPUResultsSnapshot snapshot = runner
364: .getProfilerClient()
365: .getCPUProfilingResultsSnapshot();
366: log("\nSnapshot:");
367:
368: //test tree values
369: PrestimeCPUCCTNode root = snapshot
370: .getRootNode(CPUResultsSnapshot.METHOD_LEVEL_VIEW);
371: log("Snapshot taken: " + snapshot.getTimeTaken());
372: log("Checking tree ...");
373: checkSumsOfCCTNodes(root, "", diffPercent, filterout, 0);
374:
375: log("Checking serialization");
376: assertTrue(
377: "The snapshot is not serialized/deserialized right.",
378: checkSerialization(snapshot));
379:
380: log("Checking reverse call");
381:
382: if (reverseMethod != null) {
383: int[] sigs = findThreadAndMethod(root,
384: reverseMethod, filterout);
385:
386: if (sigs != null) {
387: PrestimeCPUCCTNode revers = snapshot
388: .getReverseCCT(
389: -1,
390: sigs[1],
391: CPUResultsSnapshot.METHOD_LEVEL_VIEW);
392:
393: if (initDelay > 0) {
394: refOfCCTNodes(revers, "", false, false,
395: false);
396: } else {
397: refOfCCTNodes(revers, "", false, false,
398: true);
399: }
400: }
401: }
402:
403: log("");
404: }
405:
406: setStatus(STATUS_MEASURED);
407: } catch (Exception ex) {
408: log(ex);
409: assertTrue("Exception thrown: " + ex.getMessage(), false);
410: } finally {
411: ProfilingResultsDispatcher.getDefault().pause(true);
412: builder.shutdown();
413: flattener.setContext(null);
414: builder.removeListener(flattener);
415: builder.removeListener(resultListener);
416: ProfilingResultsDispatcher.getDefault().removeListener(
417: builder);
418: finalizeTest(runner);
419: }
420: }
421: }
|