/* * JBoss, Home of Professional Open Source. * Copyright 2008, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.test.perf.test; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.net.URL; import java.net.URLClassLoader; import java.security.CodeSource; import java.security.ProtectionDomain; import java.text.NumberFormat; import javax.naming.InitialContext; import org.jboss.test.perf.interfaces.Probe; import org.jboss.test.perf.interfaces.ProbeHome; import org.jboss.test.perf.interfaces.TxSession; import org.jboss.test.perf.interfaces.TxSessionHome; /** An MBean that tests intra-VM EJB call invocation overhead. The runTests *operation accepts the number of iterations and returns a simple html report *showing the output of each test run. @author Scott.Stark@jboss.org @version $Revision: 81036 $ */ public class PerfTest implements PerfTestMBean { private static NumberFormat fmt = NumberFormat.getInstance(); static { fmt.setMinimumFractionDigits(3); fmt.setMaximumFractionDigits(3); } int iterationCount; public String runTests(int iterationCount) { StringBuffer results = new StringBuffer("<h1>PerfTest.results</h1><pre>\n"); this.iterationCount = iterationCount; int testCount = 0; int failureCount = 0; // Print out some codebase info URL thisURL = getClass().getProtectionDomain().getCodeSource().getLocation(); results.append("\nPertTest.ClassLoader="+getClass().getClassLoader()); results.append("\nPertTest.codebase="+thisURL); try { testCount ++; testTimings(results); } catch(Throwable e) { failureCount ++; formatException(e, "testTimings", results); } results.append('\n'); try { testCount ++; testTimingsCMT(results); } catch(Throwable e) { failureCount ++; formatException(e, "testTimingsCMT", results); } results.append('\n'); try { testCount ++; testTxTimings(results); } catch(Throwable e) { failureCount ++; formatException(e, "testTxTimings", results); } results.append("\nTotal tests: "+testCount); results.append("\nTotal failures: "+failureCount); results.append("\n<pre>"); return results.toString(); } public void testTimings(StringBuffer results) throws Exception { results.append("\n+++ testTimings()"); ClassLoader oldCl = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(ProbeHome.class.getClassLoader()); try { Object obj = new InitialContext().lookup("perf.Probe"); // Print out some codebase info for the ProbeHome Class homeClass = obj.getClass(); ClassLoader cl = homeClass.getClassLoader(); results.append("\nProbeHome.ClassLoader="+cl); ClassLoader parent = cl; while( parent != null ) { results.append("\n.."+parent); if( parent instanceof URLClassLoader ) { URLClassLoader ucl = (URLClassLoader) parent; URL[] urls = ucl.getURLs(); int length = urls != null ? urls.length : 0; for(int u = 0; u < length; u ++) { results.append("\n...."+urls[u]); } } if( parent != null ) parent = parent.getParent(); } results.append("\nProbeHome Interfaces:"); Class[] ifaces = homeClass.getInterfaces(); for(int i = 0; i < ifaces.length; i ++) { results.append("\n++"+ifaces[i]); ProtectionDomain pd = ifaces[i].getProtectionDomain(); CodeSource cs = pd.getCodeSource(); if( cs != null ) results.append("\n++++CodeSource: "+cs); else results.append("\n++++Null CodeSource"); } CodeSource homeCS = ProbeHome.class.getProtectionDomain().getCodeSource(); if( homeCS != null ) results.append("\nPerfTest ProbHome CodeSource: "+homeCS); else results.append("\nPerfTest ProbHome CodeSource is NULL"); ProbeHome home = (ProbeHome) obj; results.append("\n\nFound ProbeHome @ jndiName=Probe"); Probe bean = home.create(); results.append("\nCreated Probe"); warmup(bean, results); noop(bean, results); ping(bean, results); echo(bean, results); } finally { Thread.currentThread().setContextClassLoader(oldCl); } // end of finally } public void testTimingsCMT(StringBuffer results) throws Exception { results.append("\n+++ testTimingsCMT()"); ClassLoader oldCl = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(ProbeHome.class.getClassLoader()); try { Object obj = new InitialContext().lookup("perf.ProbeCMT"); ProbeHome home = (ProbeHome) obj; results.append("\nFound ProbeHome @ jndiName=ProbeCMT"); Probe bean = home.create(); results.append("\nCreated ProbeCMT"); warmup(bean, results); noop(bean, results); ping(bean, results); echo(bean, results); } finally { Thread.currentThread().setContextClassLoader(oldCl); } // end of finally } public void testTxTimings(StringBuffer results) throws Exception { results.append("\n+++ testTxTimings()"); ClassLoader oldCl = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(TxSessionHome.class.getClassLoader()); try { Object obj = new InitialContext().lookup("perf.TxSession"); TxSessionHome home = (TxSessionHome) obj; results.append("\nFound TxSession @ jndiName=TxSession"); TxSession bean = home.create(); results.append("\nCreated TxSession"); txRequired(bean, results); txRequiresNew(bean, results); txSupports(bean, results); txNotSupported(bean, results); requiredToSupports(bean, results); requiredToMandatory(bean, results); requiredToRequiresNew(bean, results); } finally { Thread.currentThread().setContextClassLoader(oldCl); } // end of finally } private void warmup(Probe bean, StringBuffer results) throws Exception { bean.noop(); bean.ping("Ping"); bean.echo("Echo"); } private void noop(Probe bean, StringBuffer results) throws Exception { results.append("\nStarting "+iterationCount+" noop() invocations"); long start = System.currentTimeMillis(); for(int n = 0; n < iterationCount; n ++) bean.noop(); long end = System.currentTimeMillis(); long elapsed = end - start; float avgTime = elapsed; avgTime /= iterationCount; results.append("\n"+iterationCount+" noop() invocations = "+elapsed+" ms, " + fmt.format(avgTime)+" ms/noop"); } private void ping(Probe bean, StringBuffer results) throws Exception { results.append("\nStarting "+iterationCount+" ping(PING) invocations"); long start = System.currentTimeMillis(); for(int n = 0; n < iterationCount; n ++) bean.ping("PING"); long end = System.currentTimeMillis(); long elapsed = end - start; float avgTime = elapsed; avgTime /= iterationCount; results.append("\n"+iterationCount+" ping() invocations = "+elapsed+" ms, " + fmt.format(avgTime)+" ms/ping"); } private void echo(Probe bean, StringBuffer results) throws Exception { results.append("\nStarting "+iterationCount+" echo(ECHO) invocations"); long start = System.currentTimeMillis(); for(int n = 0; n < iterationCount; n ++) { String echo = bean.echo("ECHO"); } long end = System.currentTimeMillis(); long elapsed = end - start; float avgTime = elapsed; avgTime /= iterationCount; results.append("\n"+iterationCount+" echo() invocations = "+elapsed+" ms, " + fmt.format(avgTime)+" ms/echo"); } private void txRequired(TxSession bean, StringBuffer results) throws Exception { results.append("\nStarting "+iterationCount+" txRequired() invocations"); long start = System.currentTimeMillis(); for(int n = 0; n < iterationCount; n ++) { String echo = bean.txRequired(); } long end = System.currentTimeMillis(); long elapsed = end - start; float avgTime = elapsed; avgTime /= iterationCount; results.append("\n"+iterationCount+" txRequired() invocations = "+elapsed+" ms, " + fmt.format(avgTime)+" ms/txRequired"); } private void txRequiresNew(TxSession bean, StringBuffer results) throws Exception { results.append("\nStarting "+iterationCount+" txRequired() invocations"); long start = System.currentTimeMillis(); for(int n = 0; n < iterationCount; n ++) { String echo = bean.txRequiresNew(); } long end = System.currentTimeMillis(); long elapsed = end - start; float avgTime = elapsed; avgTime /= iterationCount; results.append("\n"+iterationCount+" txRequiresNew() invocations = "+elapsed+" ms, " + fmt.format(avgTime)+" ms/txRequiresNew"); } private void txSupports(TxSession bean, StringBuffer results) throws Exception { results.append("\nStarting "+iterationCount+" txSupports() invocations"); long start = System.currentTimeMillis(); for(int n = 0; n < iterationCount; n ++) { String echo = bean.txSupports(); } long end = System.currentTimeMillis(); long elapsed = end - start; float avgTime = elapsed; avgTime /= iterationCount; results.append("\n"+iterationCount+" txSupports() invocations = "+elapsed+" ms, " + fmt.format(avgTime)+" ms/txSupports"); } private void txNotSupported(TxSession bean, StringBuffer results) throws Exception { results.append("\nStarting "+iterationCount+" txNotSupported() invocations"); long start = System.currentTimeMillis(); for(int n = 0; n < iterationCount; n ++) { String echo = bean.txNotSupported(); } long end = System.currentTimeMillis(); long elapsed = end - start; float avgTime = elapsed; avgTime /= iterationCount; results.append("\n"+iterationCount+" txNotSupported() invocations = "+elapsed+" ms, " + fmt.format(avgTime)+" ms/txNotSupported"); } private void requiredToSupports(TxSession bean, StringBuffer results) throws Exception { results.append("\nStarting "+iterationCount+" requiredToSupports() invocations"); long start = System.currentTimeMillis(); for(int n = 0; n < iterationCount; n ++) { String echo = bean.requiredToSupports(); } long end = System.currentTimeMillis(); long elapsed = end - start; float avgTime = elapsed; avgTime /= iterationCount; results.append("\n"+iterationCount+" requiredToSupports() invocations = "+elapsed+" ms, " + fmt.format(avgTime)+" ms/requiredToSupports"); } private void requiredToMandatory(TxSession bean, StringBuffer results) throws Exception { results.append("\nStarting "+iterationCount+" requiredToMandatory() invocations"); long start = System.currentTimeMillis(); for(int n = 0; n < iterationCount; n ++) { String echo = bean.requiredToMandatory(); } long end = System.currentTimeMillis(); long elapsed = end - start; float avgTime = elapsed; avgTime /= iterationCount; results.append("\n"+iterationCount+" requiredToMandatory() invocations = "+elapsed+" ms, " + fmt.format(avgTime)+" ms/requiredToMandatory"); } private void requiredToRequiresNew(TxSession bean, StringBuffer results) throws Exception { results.append("\nStarting "+iterationCount+" requiredToRequiresNew() invocations"); long start = System.currentTimeMillis(); for(int n = 0; n < iterationCount; n ++) { String echo = bean.requiredToRequiresNew(); } long end = System.currentTimeMillis(); long elapsed = end - start; float avgTime = elapsed; avgTime /= iterationCount; results.append("\n"+iterationCount+" requiredToRequiresNew() invocations = "+elapsed+" ms, " + fmt.format(avgTime)+" ms/requiredToRequiresNew"); } private void formatException(Throwable t, String testName, StringBuffer results) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); t.printStackTrace(pw); results.append("\n"+testName+" failed:\n"); results.append(sw.toString()); } }