/* Copyright (c) 2005 Ricebridge. All Rights Reserved.
 *
 * This file is available under the terms and conditions of the
 * Ricebridge "Open Source API" policy; Ricebridge grants use of this
 * copyrighted work under the terms of a BSD-style license only. See
 * http://www.opensource.org/licenses/bsd-license.php for more
 * information.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *  - Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 *  - 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.
 *
 *  - Neither the name of the Ricebridge nor the names of its
 *  contributors may be used to endorse or promote products derived
 *  from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS 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
 * COPYRIGHT OWNER OR 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.  
 */

package com.ricebridge.xmlman.test;


import com.ricebridge.xmlman.*;
import com.ricebridge.data.*;
import com.ricebridge.data.sc.*;
import com.ricebridge.csvman.*;

import com.ricebridge.xmlman.in.test.TestUtil;

import org.dom4j.*;
import org.dom4j.io.*;

import org.jostraca.util.*;

import junit.framework.*;
import junit.textui.*;

import org.w3c.dom.*;

import javax.swing.table.*;
import javax.xml.parsers.*;
import java.sql.ResultSet;
import java.util.*;
import java.text.*;
import java.io.*;


/** Gather performance test data created by {@link PerformanceTestFileMaker} class.
 *    <p>The <b><a href="PerformanceTest.java.html">Source Code</a></b> of this Java class 
 *    is available under a <a href="http://www.opensource.org/licenses/bsd-license.php">BSD-style license</a>.</p>
 */
public class PerformanceTest extends TestCase {

  // standard test methods
  
  public PerformanceTest( String pName ) {
    super( pName );
  }

  public static TestSuite suite() {
    return new TestSuite( PerformanceTest.class );
  }

  public static void main( String[] pArgs ) {
    TestRunner.run( suite() );
  }




  public void testDataRecordRate() {
    CsvManager cm = new CsvManager();
    cm.getCsvSpec().setFlushEachLine(true);

    XmlManager xm = new XmlManager();
    RecordSpec rs = new RecordSpec("/data/row", 
                                   new String[] { "@char", "int", "val/@long", "val/double", "val/date", "." },
                                   new String[] { "Char", "Int", "Long", "Double", "Date", "Text" } 
                                   );
    HashMap scm = new HashMap();
    scm.put( "Date", new DateStringConverter() );
    BeanSpec bs = new BeanSpec( PerfBean.class, scm );

    try {
      System.setProperty("entityExpansionLimit","10240000");

      // 1.4.2 crimson has fillbuf bug that fails when text ends with ] (and in other cases)
      // System.setProperty("javax.xml.parsers.SAXParserFactory","net.sf.saxon.aelfred.SAXParserFactoryImpl");

      // primer
      File pf = findFile("p10");
      xm.load(           pf, rs );
      xm.loadAsLists(    pf, rs );
      xm.loadTableModel( pf, rs );
      xm.loadResultSet(  pf, rs );
      xm.loadBeans(      pf, rs, bs );

      String[]  files = new String[] { 
        "p10", "p100", "p1000", "p10000",
        "p100000", "p1000000", "p10000000" };
      ArrayList stats = new ArrayList();
      
      ArrayList row = new ArrayList();
      row.add("FileName");
      row.add("NumRecords");
      row.add("Load");
      row.add("LoadAsLists");
      row.add("TableModel");
      row.add("ResultSet");
      row.add("Beans");
      stats.add( row );

      int start = 0;
      int stop  = 5;

      for( int fI = start; fI < stop; fI++ ) {
        if( 4 < fI ) {
          // use special measuring listeners to avoid memory swapping
          // we want tests to reflect storage operation costs as well,
          // but not be skewed when we run out of main memory
          xm.getXmlManagerStore().setStringArrayRecordListenerClass( MeasureStringArrayRecordListener.class );
          xm.getXmlManagerStore().setStringListRecordListenerClass( MeasureStringListRecordListener.class );
          xm.getXmlManagerStore().setTableModelRecordListenerClass( MeasureTableModelRecordListener.class );
          xm.getXmlManagerStore().setResultSetRecordListenerClass( MeasureResultSetRecordListener.class );
          xm.getXmlManagerStore().setBeanRecordListenerClass( MeasureBeanRecordListener.class );
        }

        measureFile( xm, rs, bs, files[fI], (long) Math.pow(10, fI+1),  stats );
        //measureDom4jFile( xm, rs, bs, files[fI], (long) Math.pow(10, fI+1),  stats );
        //measureDOMFile( xm, rs, bs, files[fI], (long) Math.pow(10, fI+1),  stats );
      }

      cm.saveAsLists( findFile("stats","csv"), stats );
    }
    catch( Exception e ) {
      System.out.println( e );
      e.printStackTrace();
    }
    catch( Error e ) {
      System.out.println( xm.getStats().getTotalRecords() );
      System.out.println( e.getMessage() );
      e.printStackTrace();
    }
  }


  public static final int ITERATIONS = 10;
  public static final int MAX_RECORDS = 100000;


  public void measureFile( XmlManager pXmlManager, RecordSpec pRecordSpec, BeanSpec pBeanSpec, 
                           String pFileName, long pRecordCount, ArrayList pStats ) throws Exception {

    boolean big = 100000 < pRecordCount;

    for( int rI = 0; rI < ITERATIONS; rI++ ) {
      System.out.println( pFileName+":"+rI );
      File fn = findFile( pFileName );

      ArrayList row = new ArrayList();
      row.add( pFileName );
      row.add( new Long(pRecordCount) );

      pStats.add( row );

      List d  = pXmlManager.load( fn, pRecordSpec );
      //display(pXmlManager);
      check( pXmlManager, pRecordCount, 0 );
      row.add( new Long( pXmlManager.getStats().getTimeTaken() ) );
      if( big ) {
        d = null;
        System.gc();
        System.out.println( "load" );
      }

      List lald = pXmlManager.loadAsLists( fn, pRecordSpec );
      //display(pXmlManager);
      check( pXmlManager, pRecordCount, 0 );
      row.add( new Long( pXmlManager.getStats().getTimeTaken() ) );
      if( big ) {
        lald = null;
        System.gc();
        System.out.println( "loadAsLists" );
      }

      TableModel tm  = pXmlManager.loadTableModel( fn, pRecordSpec );
      //display(pXmlManager);
      check( pXmlManager, pRecordCount, 0 );
      row.add( new Long( pXmlManager.getStats().getTimeTaken() ) );
      if( big ) {
        tm = null;
        System.gc();
        System.out.println( "loadTableModel" );
      }

      ResultSet rt  = pXmlManager.loadResultSet( fn, pRecordSpec );
      //display(pXmlManager);
      check( pXmlManager, pRecordCount, 0 );
      row.add( new Long( pXmlManager.getStats().getTimeTaken() ) );
      if( big ) {
        rt = null;
        System.gc();
        System.out.println( "loadResultSet" );
      }

      List beans  = pXmlManager.loadBeans( fn, pRecordSpec, pBeanSpec );
      //display(pXmlManager);
      check( pXmlManager, pRecordCount, 0 );
      row.add( new Long( pXmlManager.getStats().getTimeTaken() ) );
      if( big ) {
        beans = null;
        System.gc();
        System.out.println( "loadBeans" );
      }

      System.out.println( row );
    }
  }


  public void measureDom4jFile( XmlManager pXmlManager, RecordSpec pRecordSpec, BeanSpec pBeanSpec, 
                                String pFileName, long pRecordCount, ArrayList pStats ) throws Exception {

    boolean big = 100000 < pRecordCount;

    SAXReader r    = new SAXReader();

    for( int rI = 0; rI < ITERATIONS; rI++ ) {
      System.out.println( pFileName+":"+rI );
      File fn = findFile( pFileName );

      ArrayList statsrow = new ArrayList();
      statsrow.add( pFileName );
      statsrow.add( new Long(pRecordCount) );
      pStats.add( statsrow );

      Date start = new Date();
      org.dom4j.Document  doc  = r.read( fn );
      org.dom4j.Node root = doc.getRootElement();

      ArrayList data = new ArrayList();
      List nodes = root.selectNodes("/data/row");
      int numnodes = nodes.size();
      System.out.println( "numnodes:"+numnodes );
      for( int nI = 0; nI < numnodes; nI++ ) {
        String[] row = new String[6];
        org.dom4j.Node rec = (org.dom4j.Node) nodes.get(nI);
        row[0] = rec.valueOf("@char");
        row[1] = rec.valueOf("int");
        row[2] = rec.valueOf("val/@long");
        row[3] = rec.valueOf("val/double");
        row[4] = rec.valueOf("val/date");
        row[5] = rec.valueOf(".");
        data.add(row);
        if( data.size() > MAX_RECORDS ) {
          data.clear();
        }
      }
      Date end = new Date();
      Long time = new Long( end.getTime()-start.getTime() );
      System.out.println( "time:"+time );
      statsrow.add( time );
    }
  }


  public void measureDOMFile( XmlManager pXmlManager, RecordSpec pRecordSpec, BeanSpec pBeanSpec, 
                              String pFileName, long pRecordCount, ArrayList pStats ) throws Exception {

    boolean big = 100000 < pRecordCount;

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();

    for( int rI = 0; rI < ITERATIONS; rI++ ) {
      System.out.println( pFileName+":"+rI );
      File fn = findFile( pFileName );

      ArrayList statsrow = new ArrayList();
      statsrow.add( pFileName );
      statsrow.add( new Long(pRecordCount) );
      pStats.add( statsrow );


      Date start = new Date();
      ArrayList data = new ArrayList();

      org.w3c.dom.Document doc = db.parse( fn );
      org.w3c.dom.Element  root = doc.getDocumentElement();
      org.w3c.dom.NodeList rootcl = root.getChildNodes();
      for( int i = 0; i < rootcl.getLength(); i++ ) {
        org.w3c.dom.Node n = rootcl.item(i);
        if( org.w3c.dom.Node.ELEMENT_NODE == n.getNodeType() && "row".equals( n.getNodeName() ) ) {
          String[] row = new String[6];          
          org.w3c.dom.Element rowe = (org.w3c.dom.Element)n;
          row[0] = rowe.getAttribute("char");
          
          org.w3c.dom.NodeList rowcl = rowe.getChildNodes();
          for( int j = 0; j < rowcl.getLength(); j++ ) {
            org.w3c.dom.Node nr = rowcl.item(j);
            if( org.w3c.dom.Node.TEXT_NODE == nr.getNodeType() ) {
              if( null == row[5] ) {
                row[5] = nr.getNodeValue();
              }
            }
            else if( org.w3c.dom.Node.ELEMENT_NODE == nr.getNodeType() ) {
              if( "int".equals( nr.getNodeName() ) ) {
                row[1] = nr.getFirstChild().getNodeValue();
              }
              else if( "val".equals( nr.getNodeName() ) ) {
                org.w3c.dom.Element vale = (org.w3c.dom.Element)nr;
                row[2] = vale.getAttribute("long");
                org.w3c.dom.NodeList valcl = vale.getChildNodes();
                for( int k = 0; k < valcl.getLength(); k++ ) {
                  org.w3c.dom.Node nv = valcl.item(k);
                  if( org.w3c.dom.Node.ELEMENT_NODE == nv.getNodeType() ) {
                    if( "double".equals( nv.getNodeName() ) ) {
                      row[3] = nv.getFirstChild().getNodeValue();
                    }
                    else if( "date".equals( nv.getNodeName() ) ) {
                      row[4] = nv.getFirstChild().getNodeValue();
                    }
                  }
                }
              }
            }
          }

          data.add(row);
          if( data.size() > MAX_RECORDS ) {
            data.clear();
          }
        }
      }

      Date end = new Date();
      Long time = new Long( end.getTime()-start.getTime() );
      System.out.println( "time:"+time );
      statsrow.add( time );
    }
  }



  public void check( XmlManager pXmlManager, long pRecordCount, long pBadRecordCount ) {
    assertEquals( pRecordCount, pXmlManager.getStats().getTotalRecords() );
    assertEquals( pBadRecordCount, pXmlManager.getStats().getTotalBadRecords() );
  }


  public void display( XmlManager pXmlManager ) {
    System.out.println( "tr:"+pXmlManager.getStats().getTotalRecords()+" tbr:"+pXmlManager.getStats().getTotalBadRecords()
                        +" tt:"+pXmlManager.getStats().getTimeTaken() +" atpr:"+pXmlManager.getStats().getAverageTimePerRecordInSeconds());
  }


  public static File findFile( String pName ) throws Exception {
    return findFile( pName, "xml" );
  }

  public static File findFile( String pName, String pExt ) throws Exception {
    return TestUtil.findFile( "com/ricebridge/xmlman/test/perf/"+pName+"."+pExt );
  }


  public static class PerfBean {
    public void setChar( char val ) {}
    public void setInt( int val ) {}
    public void setLong( long val ) {}
    public void setDouble( double val ) {}
    public void setDate( Date val ) {}
    public void setText( String val ) {}
  }

  public static class DateStringConverter extends DefaultStringConverter {
    SimpleDateFormat sdf = new SimpleDateFormat();
    protected Object makeObjectImpl( String pString ) throws Exception { 
      return sdf.parse( pString );
    }
    protected String makeStringImpl( Object pObject ) {
      return sdf.format( (Date) pObject );
    }
  }



  public static class MeasureStringArrayRecordListener extends StringArrayRecordListener {
    protected BadRecord handleRecordImpl( String[] pRecord, long pRecordNumber ) {
      if( 0 == pRecordNumber % 10000 ) {
        System.out.println( "rec:"+pRecordNumber );
      }
      if( MAX_RECORDS < iRecords.size() ) {
        iRecords.clear();
      }
      return super.handleRecordImpl( pRecord, pRecordNumber );
    }
  }

  public static class MeasureStringListRecordListener extends StringListRecordListener {
    protected BadRecord handleRecordImpl( String[] pRecord, long pRecordNumber ) {
      if( 0 == pRecordNumber % 10000 ) {
        System.out.println( "rec:"+pRecordNumber );
      }
      if( MAX_RECORDS < iRecords.size() ) {
        iRecords.clear();
      }
      return super.handleRecordImpl( pRecord, pRecordNumber );
    }
  }

  public static class MeasureTableModelRecordListener extends TableModelRecordListener {
    protected BadRecord handleRecordImpl( String[] pRecord, long pRecordNumber ) {
      if( 0 == pRecordNumber % 10000 ) {
        System.out.println( "rec:"+pRecordNumber );
      }
      if( MAX_RECORDS < iTableModel.getRowCount() ) {
        iTableModel.clear();
      }
      return super.handleRecordImpl( pRecord, pRecordNumber );
    }
  }

  public static class MeasureResultSetRecordListener extends ResultSetRecordListener {
    protected BadRecord handleRecordImpl( String[] pRecord, long pRecordNumber ) {
      if( 0 == pRecordNumber % 10000 ) {
        System.out.println( "rec:"+pRecordNumber );
      }
      if( MAX_RECORDS < iResultSet.getRowCount() ) {
        iResultSet.clear();
      }
      return super.handleRecordImpl( pRecord, pRecordNumber );
    }
  }

  public static class MeasureBeanRecordListener extends BeanRecordListener {
    protected BadRecord handleRecordImpl( String[] pRecord, long pRecordNumber ) throws Exception {
      if( 0 == pRecordNumber % 10000 ) {
        System.out.println( "rec:"+pRecordNumber );
      }
      if( MAX_RECORDS < iBeans.size() ) {
        iBeans.clear();
      }
      return super.handleRecordImpl( pRecord, pRecordNumber );
    }
  }

}





Syntax Highlighting created using the com.Ostermiller.Syntax package.
Thursday, February 23 2006 at 16:47