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: * MemoryTestCase.java
043: *
044: * Created on July 19, 2005, 5:21 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.memory;
051:
052: import org.netbeans.lib.profiler.ProfilerEngineSettings;
053: import org.netbeans.lib.profiler.TargetAppRunner;
054: import org.netbeans.lib.profiler.results.CCTNode;
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.memory.AllocMemoryResultsSnapshot;
059: import org.netbeans.lib.profiler.results.memory.LivenessMemoryResultsSnapshot;
060: import org.netbeans.lib.profiler.results.memory.MemoryCCTManager;
061: import org.netbeans.lib.profiler.results.memory.MemoryCCTProvider;
062: import org.netbeans.lib.profiler.results.memory.MemoryCallGraphBuilder;
063: import org.netbeans.lib.profiler.results.memory.MemoryResultsSnapshot;
064: import org.netbeans.lib.profiler.results.memory.PresoObjAllocCCTNode;
065: import org.netbeans.lib.profiler.results.memory.RuntimeMemoryCCTNode;
066: import org.netbeans.lib.profiler.tests.jfluid.*;
067: import org.netbeans.lib.profiler.tests.jfluid.utils.*;
068: import org.netbeans.lib.profiler.utils.StringUtils;
069: import java.io.ByteArrayInputStream;
070: import java.io.ByteArrayOutputStream;
071: import java.io.DataInputStream;
072: import java.io.DataOutputStream;
073: import java.lang.reflect.Field;
074: import java.util.ArrayList;
075: import java.util.Collections;
076: import java.util.Date;
077:
078: /**
079: *
080: * @author ehucka
081: */
082: public abstract class MemorySnapshotTestCase extends
083: CommonProfilerTestCase {
084: //~ Inner Classes ------------------------------------------------------------------------------------------------------------
085:
086: private static class MemoryResultListener implements
087: MemoryCCTProvider.Listener {
088: //~ Instance fields ------------------------------------------------------------------------------------------------------
089:
090: private final Object resultsLock = new Object();
091: private boolean hasResults = false;
092:
093: //~ Methods --------------------------------------------------------------------------------------------------------------
094:
095: public void cctEstablished(RuntimeCCTNode appRootNode) {
096: System.out.println("Memory CCT Established");
097:
098: synchronized (resultsLock) {
099: hasResults = true;
100: resultsLock.notify();
101: }
102: }
103:
104: public void cctReset() {
105: synchronized (resultsLock) {
106: hasResults = false;
107: resultsLock.notify();
108: }
109: }
110:
111: public boolean wait4results(long timeout) {
112: synchronized (resultsLock) {
113: if (!hasResults) {
114: try {
115: resultsLock.wait(timeout);
116: } catch (InterruptedException e) {
117: }
118: }
119:
120: return hasResults;
121: }
122: }
123: }
124:
125: //~ Instance fields ----------------------------------------------------------------------------------------------------------
126:
127: MemoryCallGraphBuilder builder = new MemoryCallGraphBuilder();
128: MemoryResultListener resultListener = null;
129:
130: //~ Constructors -------------------------------------------------------------------------------------------------------------
131:
132: /**
133: * Creates a new instance of MemoryTestCase
134: */
135: public MemorySnapshotTestCase(String name) {
136: super (name);
137: }
138:
139: //~ Methods ------------------------------------------------------------------------------------------------------------------
140:
141: protected void checkClasses(MemoryResultsSnapshot snapshot,
142: String[] prefixes) {
143: ArrayList list = new ArrayList(128);
144:
145: if (snapshot instanceof AllocMemoryResultsSnapshot) {
146: AllocMemoryResultsSnapshot alsnapshot = (AllocMemoryResultsSnapshot) snapshot;
147:
148: int[] objcnts = alsnapshot.getObjectsCounts();
149: long[] objsizes = alsnapshot.getObjectsSizePerClass();
150: String[] classnames = alsnapshot.getClassNames();
151:
152: for (int i = 0; i < snapshot.getNProfiledClasses(); i++) {
153: boolean match = false;
154:
155: for (int j = 0; j < prefixes.length; j++) {
156: if (classnames[i].startsWith(prefixes[j])) {
157: match = true;
158:
159: break;
160: }
161: }
162:
163: if (match) {
164: StringBuffer out = new StringBuffer();
165: out.append(complete(StringUtils
166: .userFormClassName(classnames[i]), 32));
167: //out.append(complete(StringUtils.nBytesToString(objsizes[i]), 10));
168: out.append(complete(String.valueOf(objcnts[i]), 8));
169: list.add(out.toString());
170: }
171: }
172:
173: ref(complete("Name", 32) /*complete("Bytes", 10)+*/
174: + complete("Objects", 8));
175: } else if (snapshot instanceof LivenessMemoryResultsSnapshot) {
176: LivenessMemoryResultsSnapshot lsnapshot = (LivenessMemoryResultsSnapshot) snapshot;
177:
178: log("Max Value: " + lsnapshot.getMaxValue());
179: log("Number Alloc: " + lsnapshot.getNAlloc());
180: log("Instr Classes: " + lsnapshot.getNInstrClasses());
181: log("Total tracked: " + lsnapshot.getNTotalTracked());
182: log("Tracked bytes: "
183: + lsnapshot.getNTotalTrackedBytes());
184: log("Tracked items: " + lsnapshot.getNTrackedItems());
185:
186: float[] avgage = lsnapshot.getAvgObjectAge();
187: int[] maxSurvGen = lsnapshot.getMaxSurvGen();
188: long[] ntrackedallocobjects = lsnapshot
189: .getNTrackedAllocObjects();
190: int[] ntrackedliveobjects = lsnapshot
191: .getNTrackedLiveObjects();
192: int[] totalAllocObjects = lsnapshot.getnTotalAllocObjects();
193: String[] classnames = lsnapshot.getClassNames();
194: long[] trackedLiveObjectsSize = lsnapshot
195: .getTrackedLiveObjectsSize();
196:
197: for (int i = 0; i < snapshot.getNProfiledClasses(); i++) {
198: boolean match = false;
199:
200: for (int j = 0; j < prefixes.length; j++) {
201: if (classnames[i].startsWith(prefixes[j])) {
202: match = true;
203:
204: break;
205: }
206: }
207:
208: if (match) {
209: StringBuffer out = new StringBuffer();
210: out.append(complete(StringUtils
211: .userFormClassName(classnames[i]), 32));
212: //out.append(complete(StringUtils.nBytesToString(trackedLiveObjectsSize[i]), 10));
213: out.append(complete(String
214: .valueOf(ntrackedliveobjects[i]), 10));
215: out.append(complete(String
216: .valueOf(ntrackedallocobjects[i]), 8));
217: //out.append(complete(String.valueOf((int)avgage[i]), 8));
218: //out.append(complete(String.valueOf(maxSurvGen[i]), 8));
219: out.append(complete(String
220: .valueOf(totalAllocObjects[i]), 8));
221: list.add(out.toString());
222: }
223: }
224:
225: ref(complete("Name", 32) /*complete("LiveBytes", 10)+*/
226: + complete("LiveObjs", 10) + complete("Allocs", 8) /*+complete("AvgAge", 8)+complete("MaxSurv", 8)*/
227: + complete("Total", 8));
228: }
229:
230: //log results
231: Collections.sort(list);
232:
233: for (int i = 0; i < list.size(); i++) {
234: ref(list.get(i));
235: }
236:
237: ref("");
238: }
239:
240: protected void checkMemoryResults(TargetAppRunner targetAppRunner,
241: String[] classPrefixes, String stacktraceClass)
242: throws Exception {
243: targetAppRunner.getProfilerClient().forceObtainedResultsDump();
244:
245: boolean gotResults = resultListener.wait4results(10000);
246:
247: assertTrue("No memory results available after 10s", gotResults);
248: log("results obtained: " + System.currentTimeMillis());
249:
250: MemoryResultsSnapshot snapshot = targetAppRunner
251: .getProfilerClient().getMemoryProfilingResultsSnapshot(
252: false);
253: assertTrue(snapshot != null);
254: log("snapshot taken: " + snapshot);
255:
256: ref((snapshot.containsStacks()) ? "Contains stacks."
257: : "Does not contain stacks.");
258: log("Begin time: " + new Date(snapshot.getBeginTime()));
259: log("Profiled classes: " + snapshot.getNProfiledClasses());
260: log("Time Taken: " + new Date(snapshot.getTimeTaken()));
261: checkClasses(snapshot, classPrefixes);
262:
263: //stacktrace
264: if (snapshot.containsStacks()) {
265: int classid = -1;
266: String[] classes = snapshot.getClassNames();
267:
268: for (int i = 0; i < snapshot.getNProfiledClasses(); i++) {
269: if (classes[i].replace('/', '.')
270: .equals(stacktraceClass)) {
271: classid = i;
272: }
273: }
274:
275: assertTrue("Stack trace class wasn't find "
276: + stacktraceClass, (classid > -1));
277:
278: MemoryCCTManager manager = new MemoryCCTManager(snapshot,
279: classid, false);
280:
281: if (!manager.isEmpty()) {
282: PresoObjAllocCCTNode root = manager.getRootNode();
283: refNodes(root, "");
284: }
285: }
286:
287: testSerialization(snapshot);
288: }
289:
290: protected boolean equals(String[] a1, String[] a2, int length) {
291: for (int i = 0; i < length; i++) {
292: if (!a1[i].equals(a2[i])) {
293: return false;
294: }
295: }
296:
297: return true;
298: }
299:
300: protected boolean equals(int[] a1, int[] a2, int length) {
301: for (int i = 0; i < length; i++) {
302: if (a1[i] != a2[i]) {
303: return false;
304: }
305: }
306:
307: return true;
308: }
309:
310: protected boolean equals(long[] a1, long[] a2, int length) {
311: for (int i = 0; i < length; i++) {
312: if (a1[i] != a2[i]) {
313: return false;
314: }
315: }
316:
317: return true;
318: }
319:
320: protected boolean equals(float[] a1, float[] a2, int length) {
321: for (int i = 0; i < length; i++) {
322: if (a1[i] != a2[i]) {
323: return false;
324: }
325: }
326:
327: return true;
328: }
329:
330: protected boolean equals(RuntimeMemoryCCTNode a1,
331: RuntimeMemoryCCTNode a2) throws Exception {
332: ByteArrayOutputStream baos = new ByteArrayOutputStream();
333: DataOutputStream dos = new DataOutputStream(baos);
334: a1.writeToStream(dos);
335: dos.close();
336:
337: byte[] bytes = baos.toByteArray();
338: //write to bytes 2
339: baos = new ByteArrayOutputStream();
340: dos = new DataOutputStream(baos);
341: a2.writeToStream(dos);
342: dos.close();
343:
344: byte[] bytes2 = baos.toByteArray();
345:
346: if (bytes.length != bytes2.length) {
347: return false;
348: }
349:
350: for (int i = 0; i < bytes.length; i++) {
351: if (bytes[i] != bytes2[i]) {
352: return false;
353: }
354: }
355:
356: return true;
357: }
358:
359: protected ProfilerEngineSettings initMemorySnapshotTest(
360: String projectName, String className) {
361: ProfilerEngineSettings settings = initTest(projectName,
362: className, null);
363: //defaults
364: settings.setThreadCPUTimerOn(false);
365: settings.setAllocTrackEvery(1); //default is not strict - cannot be measured in test
366: settings.setRunGCOnGetResultsInMemoryProfiling(true);
367:
368: return settings;
369: }
370:
371: protected void refNodes(PresoObjAllocCCTNode root, String tab) {
372: ref(tab + (PresoObjAllocCCTNode) root);
373:
374: if (root.getNChildren() > 0) {
375: root.sortChildren(PresoObjAllocCCTNode.SORT_BY_NAME, false);
376:
377: CCTNode[] nodes = root.getChildren();
378:
379: for (int i = 0; i < nodes.length; i++) {
380: refNodes((PresoObjAllocCCTNode) nodes[i], tab + " ");
381: }
382: }
383: }
384:
385: protected void startMemorySnapshotTest(
386: ProfilerEngineSettings settings, int instrMode,
387: String[] classPrefixes, String stacktraceClass) {
388: //create runner //instrMode CommonConstants.INSTR_OBJECT_ALLOCATIONS
389: assertTrue(builder != null);
390:
391: TestProfilerAppHandler handler = new TestProfilerAppHandler(
392: this );
393: TargetAppRunner runner = new TargetAppRunner(settings, handler,
394: new TestProfilingPointsProcessor());
395: runner.addProfilingEventListener(Utils
396: .createProfilingListener(this ));
397:
398: builder.removeAllListeners();
399: ProfilingResultsDispatcher.getDefault().removeAllListeners();
400:
401: resultListener = new MemoryResultListener();
402: builder.addListener(resultListener);
403:
404: ProfilingResultsDispatcher.getDefault().addListener(builder);
405: builder.startup(runner.getProfilerClient());
406:
407: EventBufferResultsProvider.getDefault().startup(
408: runner.getProfilerClient());
409:
410: try {
411: assertTrue("not read calibration data", runner
412: .readSavedCalibrationData());
413:
414: Process p = startTargetVM(runner);
415: assertNotNull("Target JVM is not started", p);
416: bindStreams(p);
417:
418: runner.connectToStartedVMAndStartTA();
419:
420: runner.getProfilerClient()
421: .initiateMemoryProfInstrumentation(instrMode);
422:
423: waitForStatus(STATUS_RUNNING);
424: assertTrue("runner is not running", runner
425: .targetAppIsRunning());
426:
427: waitForStatus(STATUS_RESULTS_AVAILABLE
428: | STATUS_APP_FINISHED);
429:
430: if (!isStatus(STATUS_APP_FINISHED)) {
431: waitForStatus(STATUS_APP_FINISHED);
432: }
433:
434: checkMemoryResults(runner, classPrefixes, stacktraceClass);
435: setStatus(STATUS_MEASURED);
436: } catch (Exception ex) {
437: log(ex);
438: assertTrue("Exception thrown: " + ex.getMessage(), false);
439: } finally {
440: ProfilingResultsDispatcher.getDefault().pause(true);
441: builder.shutdown();
442:
443: builder.removeListener(resultListener);
444: ProfilingResultsDispatcher.getDefault().removeListener(
445: builder);
446:
447: finalizeTest(runner);
448: }
449: }
450:
451: protected void testSerialization(MemoryResultsSnapshot snapshot) {
452: try {
453: //write to bytes
454: ByteArrayOutputStream baos = new ByteArrayOutputStream();
455: DataOutputStream dos = new DataOutputStream(baos);
456: snapshot.writeToStream(dos);
457: dos.close();
458:
459: byte[] bytes = baos.toByteArray();
460: MemoryResultsSnapshot snapshot2;
461:
462: if (snapshot instanceof LivenessMemoryResultsSnapshot) {
463: snapshot2 = new LivenessMemoryResultsSnapshot();
464: } else {
465: snapshot2 = new AllocMemoryResultsSnapshot();
466: }
467:
468: //read from bytes
469: ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
470: DataInputStream dis = new DataInputStream(bis);
471: snapshot2.readFromStream(dis);
472: dis.close();
473:
474: //compare
475: if (snapshot instanceof LivenessMemoryResultsSnapshot) {
476: LivenessMemoryResultsSnapshot s1;
477: LivenessMemoryResultsSnapshot s2;
478: s1 = (LivenessMemoryResultsSnapshot) snapshot;
479: s2 = (LivenessMemoryResultsSnapshot) snapshot2;
480: assertEquals(
481: "Snapshot Serialization: diff containsStacks",
482: s1.containsStacks(), s2.containsStacks());
483: assertEquals("Snapshot Serialization: diff beginTime",
484: s1.getBeginTime(), s2.getBeginTime());
485: assertEquals("Snapshot Serialization: diff MaxValue",
486: s1.getMaxValue(), s2.getMaxValue());
487: assertEquals("Snapshot Serialization: diff NAlloc", s1
488: .getNAlloc(), s2.getNAlloc());
489: assertEquals(
490: "Snapshot Serialization: diff NInstrClasses",
491: s1.getNInstrClasses(), s2.getNInstrClasses());
492: assertEquals(
493: "Snapshot Serialization: diff NProfiledClasses",
494: s1.getNProfiledClasses(), s2
495: .getNProfiledClasses());
496: assertEquals(
497: "Snapshot Serialization: diff NTotalTracked",
498: s1.getNTotalTracked(), s2.getNTotalTracked());
499: assertEquals(
500: "Snapshot Serialization: diff NTotalTrackedBytes",
501: s1.getNTotalTrackedBytes(), s2
502: .getNTotalTrackedBytes());
503: assertEquals(
504: "Snapshot Serialization: diff NTrackedItems",
505: s1.getNTrackedItems(), s2.getNTrackedItems());
506: assertEquals("Snapshot Serialization: diff TimeTaken",
507: s1.getTimeTaken(), s2.getTimeTaken());
508:
509: assertTrue("Snapshot Serialization: diff AvgObjectAge",
510: equals(s1.getAvgObjectAge(), s2
511: .getAvgObjectAge(), s1
512: .getNProfiledClasses()));
513: assertTrue("Snapshot Serialization: diff ClassNames",
514: equals(s1.getClassNames(), s2.getClassNames(),
515: s1.getNProfiledClasses()));
516: assertTrue("Snapshot Serialization: diff MaxSurvGen",
517: equals(s1.getMaxSurvGen(), s2.getMaxSurvGen(),
518: s1.getNProfiledClasses()));
519: assertTrue(
520: "Snapshot Serialization: diff NTrackedAllocObjects",
521: equals(s1.getNTrackedAllocObjects(), s2
522: .getNTrackedAllocObjects(), s1
523: .getNProfiledClasses()));
524: assertTrue(
525: "Snapshot Serialization: diff NTrackedLiveObjects",
526: equals(s1.getNTrackedLiveObjects(), s2
527: .getNTrackedLiveObjects(), s1
528: .getNProfiledClasses()));
529: assertTrue(
530: "Snapshot Serialization: diff ObjectsSizePerClass",
531: equals(s1.getObjectsSizePerClass(), s2
532: .getObjectsSizePerClass(), s1
533: .getNProfiledClasses()));
534: assertTrue(
535: "Snapshot Serialization: diff TrackedLiveObjectsSize",
536: equals(s1.getTrackedLiveObjectsSize(), s2
537: .getTrackedLiveObjectsSize(), s1
538: .getNProfiledClasses()));
539: assertTrue(
540: "Snapshot Serialization: diff nTotalAllocObjects",
541: equals(s1.getnTotalAllocObjects(), s2
542: .getnTotalAllocObjects(), s1
543: .getNProfiledClasses()));
544: } else {
545: AllocMemoryResultsSnapshot s1;
546: AllocMemoryResultsSnapshot s2;
547: s1 = (AllocMemoryResultsSnapshot) snapshot;
548: s2 = (AllocMemoryResultsSnapshot) snapshot2;
549: assertEquals(
550: "Snapshot Serialization: diff containsStacks",
551: s1.containsStacks(), s2.containsStacks());
552: assertEquals("Snapshot Serialization: diff beginTime",
553: s1.getBeginTime(), s2.getBeginTime());
554: assertEquals(
555: "Snapshot Serialization: diff NProfiledClasses",
556: s1.getNProfiledClasses(), s2
557: .getNProfiledClasses());
558: assertEquals("Snapshot Serialization: diff TimeTaken",
559: s1.getTimeTaken(), s2.getTimeTaken());
560:
561: assertTrue("Snapshot Serialization: diff ClassNames",
562: equals(s1.getClassNames(), s2.getClassNames(),
563: s1.getNProfiledClasses()));
564: assertTrue(
565: "Snapshot Serialization: diff ObjectsSizePerClass",
566: equals(s1.getObjectsSizePerClass(), s2
567: .getObjectsSizePerClass(), s1
568: .getNProfiledClasses()));
569: }
570:
571: if (snapshot.containsStacks()) {
572: Field field = snapshot.getClass().getSuperclass()
573: .getDeclaredField("stacksForClasses");
574: field.setAccessible(true);
575:
576: RuntimeMemoryCCTNode[] stacksForClasses = (RuntimeMemoryCCTNode[]) field
577: .get(snapshot);
578: RuntimeMemoryCCTNode[] stacksForClasses2 = (RuntimeMemoryCCTNode[]) field
579: .get(snapshot2);
580:
581: for (int i = 0; i < stacksForClasses.length; i++) {
582: if (stacksForClasses[i] != null) {
583: assertTrue(
584: "Snapshot Serialization: diff stacktraces "
585: + snapshot.getClassName(i),
586: equals(stacksForClasses[i],
587: stacksForClasses2[i]));
588: }
589: }
590: }
591: } catch (Exception ex) {
592: ex.printStackTrace();
593: assertTrue("Snapshot Serialization: "
594: + ex.getClass().getName() + ": " + ex.getMessage(),
595: false);
596: }
597: }
598: }
|