/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.tuscany.sca.test.performance; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.OperatingSystemMXBean; import java.lang.ref.WeakReference; import javax.management.MBeanServer; import org.apache.tuscany.sca.Node; import org.apache.tuscany.sca.TuscanyRuntime; import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.core.FactoryExtensionPoint; import org.apache.tuscany.sca.core.UtilityExtensionPoint; import org.apache.tuscany.sca.databinding.jaxb.JAXBContextHelper; import org.apache.tuscany.sca.impl.NodeImpl; import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceFactoryImpl; import org.apache.tuscany.sca.test.performance.client.BeanA; import org.apache.tuscany.sca.test.performance.client.Helloworld; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import com.sun.management.HotSpotDiagnosticMXBean; /* * A test looking at memory and runtime performance. * TODO - only a couple of memory tests to start with */ public class PerformanceTestCase { public boolean writeHeapDump = true; private static BufferedWriter resultsFile = null; private TuscanyRuntime runtime; private Node node; private ExtensionPointRegistry extensionPointRegistry; private long lastTotal = 0; private long lastFree = 0; private long lastUsed = 0; @BeforeClass public static void setUp() throws Exception { FileWriter fileWriter = new FileWriter("out.txt"); resultsFile = new BufferedWriter(fileWriter); } @AfterClass public static void tearDown() throws Exception { resultsFile.flush(); resultsFile.close(); } @Test public void testNodeStartStop() { dumpHeapStart("testInstallUninstall"); printRuntimeStats("createRuntime"); createRuntime(); callNodeStartStopRepeatedly(100); waitForInput(); dumpHeapEnd("testInstallUninstall_postNodeStop"); printRuntimeStats("stopRuntime"); stopRuntime(); printRuntimeStats("destroyRuntime"); destroyRuntime(); printRuntimeStats("End"); dumpHeapEnd("testInstallUninstall_postStop"); } @Test public void testInstallUninstall() { dumpHeapStart("testInstallUninstall"); printRuntimeStats("createRuntime"); createRuntime(); printRuntimeStats("createNode"); createNode(); callInstallUninstallRepeatedly(100); dumpHeapEnd("testInstallUninstall_postUninstall"); checkCacheStatus(); printRuntimeStats("stopNode"); stopNode(); printRuntimeStats("destroyNode"); destroyNode(); printRuntimeStats("stopRuntime"); stopRuntime(); printRuntimeStats("destroyRuntime"); destroyRuntime(); printRuntimeStats("End"); dumpHeapEnd("testInstallUninstall_postStop"); } @Test public void testCall() { dumpHeapStart("TestCall"); printRuntimeStats("createRuntime"); createRuntime(); printRuntimeStats("createNode"); createNode(); printRuntimeStats("installContribution"); installContribution(); printRuntimeStats("startNode"); startComposite(); printRuntimeStats("callServiceRepeatedly 10000 times"); callServiceRepeatedly(10000); printRuntimeStats("stopCompositeAndUninstallUnused"); stopCompositeAndUninstallUnused(); //printRuntimeStats("uninstallContribution"); //uninstallContribution(); dumpHeapEnd("TestCall_postUninstall"); printRuntimeStats("stopNode"); stopNode(); printRuntimeStats("destroyNode"); destroyNode(); printRuntimeStats("stopRuntime"); stopRuntime(); printRuntimeStats("destroyRuntime"); destroyRuntime(); printRuntimeStats("End"); dumpHeapEnd("TestCall_postStop"); } public void checkCacheStatus(){ UtilityExtensionPoint utilityExtensionPoint = extensionPointRegistry.getExtensionPoint(UtilityExtensionPoint.class); JAXBContextHelper jaxbContextHelper = utilityExtensionPoint.getUtility(JAXBContextHelper.class); Assert.assertEquals("JAXBContextCache > 1", 1, jaxbContextHelper.getJAXBContextCache().getCache().keySet().size()); FactoryExtensionPoint factoryExtensionPoint = extensionPointRegistry.getExtensionPoint(FactoryExtensionPoint.class); JavaInterfaceFactory javaInterfaceFactory = factoryExtensionPoint.getFactory(JavaInterfaceFactory.class); Assert.assertEquals("JavaInterfaceFactoryImpl.normalCache > 1", 1, ((JavaInterfaceFactoryImpl)javaInterfaceFactory).getNormalCache().keySet().size()); } // ============================================================ public void callNodeStartStopRepeatedly(int repeatCount) { for (int i =0; i < repeatCount; i++){ printRuntimeStats("createNode"); createNode(); callInstallUninstallRepeatedly(1); printRuntimeStats("stopNode"); stopNode(); printRuntimeStats("destroyNode"); destroyNode(); } } public void callInstallUninstallRepeatedly(int repeatCount) { for (int i =0; i < repeatCount; i++){ printRuntimeStats("install/unistall contribution"); installContribution(); startComposite(); callService(); stopCompositeAndUninstallUnused(); //uninstallContribution(); } } public void callServiceRepeatedly(int repeatCount) { for (int i =0; i < repeatCount; i++){ callService(); } } // ============================================================ public void dumpHeapStart(String name){ if (writeHeapDump){ dumpHeap("heap_start_" + name + ".bin"); } } public void dumpHeapEnd(String name){ if (writeHeapDump){ dumpHeap("heap_stop_" + name + ".bin"); System.out.println("You can watch a JVM run using \n" + " jconsole \n" + "You can manually dump the heap using \n" + " jmap -dump:file=heap_stop_" + name + ".bin 345" + "Where 345 is the process id from jconsole \n" + "The program dumps the heap at the start and end. You can look at them using \n" + " jhat -J-Xmx512m heap_start.bin\n" + " jhat -J-Xmx512m heap_stop_" + name + ".bin\n" + "Then point your browser at\n" + " http://localhost:7000/"); } else { System.out.println("NO HEAP DUMPS WRITTEN"); } } public void createRuntime() { runtime = TuscanyRuntime.newInstance(); } public void createNode() { node = runtime.createNode("default"); extensionPointRegistry = ((NodeImpl)node).getExtensionPointRegistry(); } public void installContribution() { try { node.installContribution("performance", "../performance-contribution1/target/itest-performance-contribution1-2.0-SNAPSHOT.jar", null, null); } catch (Exception ex){ ex.printStackTrace(); } } public void startComposite() { try { node.startComposite("performance", "PerformanceTest.composite"); } catch (Exception ex){ ex.printStackTrace(); } } public void stopCompositeAndUninstallUnused(){ try { node.stopCompositeAndUninstallUnused("performance", "PerformanceTest.composite"); } catch (Exception ex){ ex.printStackTrace(); } } public void uninstallContribution(){ try { node.installContribution("performance"); } catch (Exception ex){ ex.printStackTrace(); } } public void stopNode(){ node.stop(); } public void destroyNode() { node = null; } public void stopRuntime() { runtime.stop(); } public void destroyRuntime() { runtime = null; } public void callService() { try { Helloworld helloWorldClient = node.getService(Helloworld.class, "HelloWorldClientComponent"); assertNotNull(helloWorldClient); BeanA beanA = new BeanA(); beanA.setField1("Smith"); beanA.setField2(13); assertEquals("Hello Hello Jane Smith", helloWorldClient.sayHello("Jane", beanA)); } catch (Exception ex) { fail(ex.toString()); } } public void printRuntimeStats(String step){ tryToGC(); Runtime runtime = Runtime.getRuntime(); long used = runtime.totalMemory() - runtime.freeMemory(); long free = runtime.freeMemory(); long total = runtime.totalMemory(); String stats = "U " + used + "[" + (used - lastUsed ) + "] \t" + "F " + free + "[" + (free - lastFree ) + "] \t" + "T " + total + "[" + (total - lastTotal) + "] \t" + step + "\n"; try { resultsFile.write(stats); } catch (Exception ex) { ex.printStackTrace(); } System.out.print(stats); lastTotal = total; lastFree = free; lastUsed = used; } /** * We can't rely on GC doing anything sensible * but I'm just playing here to see if I can * force it to GC */ public void tryToGC(){ Runtime runtime = Runtime.getRuntime(); /* // force OOME StringBuffer sb = new StringBuffer(); try { while(true) { sb.append("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); } } catch (OutOfMemoryError ex){ // we are going to GC now System.out.println("OOME"); } sb = null; for (int i = 0; i < 10; i++){ Object obj = new Object(); WeakReference ref = new WeakReference(obj); obj = null; while(ref.get() != null) { runtime.runFinalization(); runtime.gc(); try { Thread.sleep(100); } catch (InterruptedException e) { // Do nothing } } } */ } public void dumpHeap(String heapName){ String vendor = System.getProperty("java.vendor"); if (vendor.contains("Sun")){ dumpHeapSun(heapName); } } public void dumpHeapSun(String heapName){ final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean(); final OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean(); final MBeanServer platformBean = ManagementFactory.getPlatformMBeanServer(); HotSpotDiagnosticMXBean bean = null; try { bean = ManagementFactory.newPlatformMXBeanProxy(platformBean, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class); deleteFile(heapName); bean.dumpHeap(heapName, false); } catch(Exception ex){ ex.printStackTrace(); } } public void dumpHeapIBM(){ } public void deleteFile(String filename){ File theFile = new File(filename); theFile.delete(); } public void waitForInput() { System.out.println("Press a key to end"); try { System.in.read(); } catch (Exception ex) { } System.out.println("Continuing"); } // final MemoryMXBean mb = ManagementFactory.getMemoryMXBean(); // com.sun.management.OperatingSystemMXBean if java.lang.management.OperationSystemMXBean }