antelder    2002/07/02 01:37:37

  Added:       java/test/performance SpeedTest.java Monitor.java
  Log:
  New testcase to help with testing performance improvement changes
  
  Revision  Changes    Path
  1.1                  xml-axis-wsif/java/test/performance/SpeedTest.java
  
  Index: SpeedTest.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "WSIF" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 2001, 2002, International
   * Business Machines, Inc., http://www.apache.org.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package performance;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Properties;
  
  import junit.framework.Test;
  import junit.framework.TestCase;
  import junit.framework.TestSuite;
  
  import org.apache.wsif.WSIFMessage;
  import org.apache.wsif.WSIFOperation;
  import org.apache.wsif.WSIFPort;
  import org.apache.wsif.WSIFService;
  import org.apache.wsif.WSIFServiceFactory;
  import org.apache.wsif.base.WSIFServiceImpl;
  import org.apache.wsif.providers.soap.apacheaxis.WSIFDynamicProvider_ApacheAxis;
  import util.TestUtilities;
  
  import addressbook.wsiftypes.Address;
  import addressbook.wsiftypes.Phone;
  
  /**
   * Junit test to measure some simple performance statistics.
   * It times a number of iterations of getPort, createOperation,
   * and executeRequestResponseOperation for each provider. The 
   * results are stored in a properties file to allow each run 
   * to test if the performance has changed since the last run.
   * 
   * The number of iterations to do is determined by the time
   * each test takes and the TIME_PER_TEST constant. You need
   * to run it atleast 3 times to get the iterations calculation
   * to settle on a good value; The MARGIN_OF_ERROR constant 
   * defines how mush variation between run times is ignored
   * when determining if the performance has changed. 
   *  
   * You may need to change the TIME_PER_TEST and MARGIN_OF_ERROR 
   * constants for your machine speed.
   * 
   * For testing you can add futher timing points to the internal
   * WSIF classes which this test will then monitor and report on.
   * 
   * For example, to time the axis provider invoke method, at the
   * start of the invoke method add:
   *    Monitor.start( "axisInvoke" ); 
   * followed by a stop call at the end of the invoke method:
   *    Monitor.stop( "axisInvoke" );
   * 
   * Monitor points can be paused around unwanted code. For example
   * with the above monitors in the invoke method, you could exclude
   * the SOAP call time with:
   *    Monitor.pause( "axisInvoke" );
   *    resp = call.invoke(locationUri, getSoapActionURI());
   *    Monitor.resume( "axisInvoke" ); 
   * 
   * @author <a href="mailto:[EMAIL PROTECTED]";>Ant Elder</a>
   */
  public class SpeedTest extends TestCase {
  
      // This defines how long each test should be run for.
      // There are 3 tests per provider; getPort, createOperation
      // and executeOperation, so the total runnning time will be
      // 3 times this value, times the number of providers tested.
      static final float TIME_PER_TEST = 10000.0F;  // 10 seconds
  
      // This defines the time variation between runs before a
      // result is considered a significant performance change. 
      static final float MARGIN_OF_ERROR = 0.1F;  // tenth of a millisecond
      
      // defines if this run will overwrite existing statistics
      static final boolean UPDATE_STATS = true;
      
      // delete this file to reset the previous statistics
      File propFile = new File( "wsifPerformanceStats.txt" );
      
      Properties stats;
      
      static final String wsdlLocation =
          TestUtilities.getWsdlPath("java\\samples\\addressbook\\wsifservice")
              + "AddressBook.wsdl";
  
      public SpeedTest(String name) {
          super(name);
      }
  
        public static void main(String[] args) {
            TestUtilities.startListeners();     
            junit.textui.TestRunner.run (suite());
          TestUtilities.stopListeners();        
        }
  
      public static Test suite() {
          return new TestSuite(SpeedTest.class);
      }
  
      public void setUp() {
          TestUtilities.setUpExtensionsAndProviders();
      }
      public void tearDown() {
         if ( UPDATE_STATS ) {
            saveStatsToFile();
         }
      }
  
      public void testJava() {
          doit("JavaPort", "java");
      }
  
      //public void testAxis() {
      //    doit("SOAPPort", "axis");
      //}
      //public void testSoap() {
      //    doit("SOAPPort", "soap");
      //}
  
      //public void testEJB() { 
      //}
  
  /* JMS seems to slow for most runs
      public void testSoapJms() {
          doit("SOAPJMSPort", "soap");
      }
      public void testAxisJms() {
          doit("SOAPJMSPort", "axis");
      }
      public void testNativeJms() {
          doit("NativeJmsPort", "njms" ); 
      }
  */
  
      private void doit(String portName, String protocol) {
          int iterations;
          long startTime, endTime;
          float totalTime, avgTime;
          String testNamePrefix = portName + "." + protocol;
          String testName;
  
          if (portName.indexOf("JMS") != -1 && !TestUtilities.areWeTesting("jms"))
              return;
  
          if (protocol.equals("axis")) {
              WSIFServiceImpl.setDynamicWSIFProvider(
                  "http://schemas.xmlsoap.org/wsdl/soap/";,
                  new WSIFDynamicProvider_ApacheAxis());
          }
  
          try {
              WSIFServiceFactory factory = WSIFServiceFactory.newInstance();
              WSIFService service = factory.getService(wsdlLocation, null, // 
serviceNS 
                 null, // serviceName 
                 "http://wsifservice.addressbook/";, // portTypeNS 
                 "AddressBook"); // portTypeName 
  
              service.mapType(
                  new javax.xml.namespace.QName(
                      "http://wsiftypes.addressbook/";,
                      "address"),
                  Class.forName("addressbook.wsiftypes.Address"));
  
              service.mapType(
                  new javax.xml.namespace.QName(
                      "http://wsiftypes.addressbook/";,
                      "phone"),
                  Class.forName("addressbook.wsiftypes.Phone"));
  
              WSIFPort port = null;
  
              port = service.getPort(portName);
              
              /*
               * Run iterations of getPort
               */
              testName = testNamePrefix + ".getPort";
              iterations = getIterations( testName );
              System.out.println( "running " + iterations + " " + testName + " 
iterations..." ); 
              for (int i = 0; i < iterations; i++ ) {
                 Monitor.start( testName );
                 port = service.getPort(portName);
                 Monitor.stop( testName );
              }
  
              WSIFOperation operation =
                  port.createOperation("addEntry", "AddEntryWholeNameRequest", null);
  
              WSIFMessage inputMessage = operation.createInputMessage();
              WSIFMessage outputMessage = operation.createOutputMessage();
              WSIFMessage faultMessage = operation.createFaultMessage();
  
              // Create a name and address to add to the addressbook 
              String nameToAdd = "Chris P. Bacon";
              Address addressToAdd =
                  new Address(
                      1,
                      "The Waterfront",
                      "Some City",
                      "NY",
                      47907,
                      new Phone(765, "494", "4900"));
  
              // Add the name and address to the input message 
              inputMessage.setObjectPart("name", nameToAdd);
              inputMessage.setObjectPart("address", addressToAdd);
  
              // Execute the operation, obtaining a flag to indicate its success 
              boolean ok=
                  operation.executeRequestResponseOperation(
                      inputMessage,
                      outputMessage,
                      faultMessage);
  
              assertTrue( "failed to add name and address!!", ok );
  
              /*
               * Run iterations of createOperation
               */
              testName = testNamePrefix + ".createOperation";
              iterations = getIterations( testName );
              System.out.println( "running " + iterations + " " + testName + " 
iterations..." ); 
              for (int i = 0; i < iterations; i++ ) {
                 Monitor.start( testName );
                           operation = port.createOperation("getAddressFromName");
                 Monitor.stop( testName );
              }
  
              /*
               * Run iterations of executeRequestResponseOperation
               */
              testName = testNamePrefix + ".executeOperation";
              iterations = getIterations( testName );
              System.out.println( "running " + iterations + " " + testName + " 
iterations..." ); 
              startTime = System.currentTimeMillis();
              for (int i = 0; i < iterations; i++ ) {
                           operation = port.createOperation("getAddressFromName");
                           inputMessage = operation.createInputMessage();
                           outputMessage = operation.createOutputMessage();
                           faultMessage = operation.createFaultMessage();
  
                           inputMessage.setObjectPart("name", nameToAdd);
  
                 Monitor.start( testName );
                           boolean operationSucceeded =
                                  operation.executeRequestResponseOperation(
                                         inputMessage,
                                         outputMessage,
                                         faultMessage);
                 Monitor.stop( testName );
                           if (!operationSucceeded) {
                                  System.out.println("Failed to lookup name in 
addressbook");
                                  assertTrue("executing op returned false!!", false);
                           }
              }
  
              // make sure it all worked
                    Address addressFound =
                           (Address) outputMessage.getObjectPart("address");
                        assertTrue( "returned address not correct!!", 
                           addressToAdd.equals( addressFound) ); 
              
              // test is theres a performance change
              boolean worse = testResults();
              
              updateStats();
              setIterations( testNamePrefix );
  
              assertTrue( "performance is worse than before!!", !worse );
  
         } catch (Exception ex) {
               ex.printStackTrace();
                   assertTrue("exception executing op!!", false);
           }
      }
  
      private boolean testResults() {
        float diff;
          String s1, s2;
        boolean worse = false;
  
          HashMap results = Monitor.getResults();
          String testName;
          float duration, oldDuration;
          for (Iterator i = results.keySet().iterator(); i.hasNext(); ) {
                testName = (String)i.next();
              duration = ((Float)results.get( testName )).floatValue();
              oldDuration = getfloatStat( testName );            
            diff = duration - oldDuration;
              worse = (diff-MARGIN_OF_ERROR) > 0;
            if ( Math.abs(diff) - MARGIN_OF_ERROR > 0 ) {
                   System.err.println( testName + " significantly " + 
                      ( (diff>0) ? "worse" : "better" ) + 
                      " by " + diff + " msecs, time = " + duration + " msecs" );
            } else {
                   System.out.println( testName + " time = " + duration + " msecs" );
            }
          }
  
        return worse;
      }
      
      private int getIterations(String testName) {
        int i;
          i = getintStat( testName + ".Iterations" );
          if ( i == 0 ) {
                i = 100; // 1st run default to 100 iterations
          }
          return i;     
      }
      
      private void setIterations(String prefix) {
          String s;
          int iterations;
          float duration, createDuration;
          HashMap results = Monitor.getResults();
          
          s = prefix + ".getPort";
          duration = ((Float)results.get( s )).floatValue();
          iterations = (duration==0) ? 
             100 : (int)((TIME_PER_TEST*100) / (duration*100)); 
        stats.setProperty( s + ".Iterations", ""+iterations );
  
          s = prefix + ".createOperation";
          duration = ((Float)results.get( s )).floatValue();
          iterations = (duration==0) ? 
             100 : (int)((TIME_PER_TEST*100) / (duration*100)); 
        stats.setProperty( s + ".Iterations", ""+iterations );
          createDuration = duration;
  
          s = prefix + ".executeOperation";
          duration = ((Float)results.get( s )).floatValue();
          iterations = (duration==0) ? 
             100 : (int)((TIME_PER_TEST*100) / ((duration+createDuration)*100)); 
        stats.setProperty( s + ".Iterations", ""+iterations );
  
      }
      
      private void updateStats() {
          HashMap results = Monitor.getResults();
          Properties stats = getStats();
          String testName;
          float duration;
          int iterations;
          for (Iterator i = results.keySet().iterator(); i.hasNext(); ) {
             testName = (String)i.next();
             duration = ((Float)results.get( testName )).floatValue();
           stats.setProperty( testName, ""+duration );
          }
      }
      
      private int getintStat(String name) {
        int i;
        Properties stats = getStats();
        try {
           i = Integer.parseInt(stats.getProperty( name ) );
        } catch (Exception ex) {
           i = 0;
        }
          return i;     
      }
      
      private float getfloatStat(String name) {
        float f;
        Properties stats = getStats();
        try {
           f = Float.parseFloat(stats.getProperty( name ) );
        } catch (Exception ex) {
           f = 0;
        }
          return f;     
      }
      
      private Properties getStats() {
        if ( stats == null ) {
                loadStatsFromFile();
        }
        return stats;
      }
  
      private void loadStatsFromFile() {
        try {
           FileInputStream fis = new FileInputStream( propFile );
           stats = new Properties();
           stats.load( fis );
        } catch (Exception ex) {
                stats = new Properties();
        }
      }
      
      private void saveStatsToFile() {
        try {
               FileOutputStream fos = new FileOutputStream( propFile );
           stats.store( fos, "WSIF Performance stats" );
        } catch (Exception ex) {
                ex.printStackTrace();
        }
      }
      
  }
  
  
  1.1                  xml-axis-wsif/java/test/performance/Monitor.java
  
  Index: Monitor.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "WSIF" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 2001, 2002, International
   * Business Machines, Inc., http://www.apache.org.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package performance;
  
  import java.util.HashMap;
  import java.util.Iterator;
  
  /**
   * Collect monitor point timing statistics.
   * 
   * @author <a href="mailto:[EMAIL PROTECTED]";>Ant Elder</a>
   */
  public class Monitor {
  
     static HashMap timers = new HashMap();
     
     public static void start(String s) {
        Timer t = (Timer)timers.get( s );
        if ( t == null ) {
             t = new Timer();
           timers.put( s, t );
        } 
        t.start();      
     }
  
     public static void stop(String s) {
        Timer t = (Timer)timers.get( s );
        t.stop();       
     }
  
     public static void pause(String s) {
        Timer t = (Timer)timers.get( s );
        if ( t != null ) {
           t.pause();
        }       
     }
  
     public static void resume(String s) {
        Timer t = (Timer)timers.get( s );
        if ( t != null ) {
           t.resume();  
        }
     }
     
     public static HashMap getResults() {
        Timer t;
        String testName;
        HashMap results = new HashMap();
        for (Iterator i = timers.keySet().iterator(); i.hasNext(); ) {
           testName = (String)i.next();
           t = (Timer)timers.get( testName );
           float f1 = t.getAvgTime();
           Float f = new Float( t.getAvgTime() );
           results.put( testName, new Float( t.getAvgTime() ) );
        }
        return results;
     }
  
  }
  
  class Timer {
  
     long start;
     long interval;
     long totalTime;
     int startCount;
        
     public Timer() {
           interval = 0;
           totalTime = 0;
           startCount = 0;
     }
  
     public void start() {
           interval = 0;
           startCount +=1;
           totalTime += interval;
           start = System.currentTimeMillis();
     }
  
     public void pause() {
           interval += System.currentTimeMillis() - start;
           start = 0;
     }
  
     public void resume() {
           start = System.currentTimeMillis();
     }
  
     public void stop() {
           interval += System.currentTimeMillis() - start;
           totalTime += interval;
     }
  
     public long getInterval() {
           return interval;
     }
        
     public float getAvgTime() {
           return (float)totalTime / startCount;
     }
        
  }
  
  


Reply via email to