/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2016 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * Licensed 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.pentaho.di.trans; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.pentaho.di.core.Const; import org.pentaho.di.core.KettleEnvironment; import org.pentaho.di.core.RowMetaAndData; import org.pentaho.di.core.RowSet; import org.pentaho.di.core.logging.LogLevel; import org.pentaho.di.core.row.RowMeta; import org.pentaho.di.core.row.RowMetaInterface; import org.pentaho.di.core.row.ValueMetaInterface; import org.pentaho.di.core.row.value.ValueMetaBigNumber; import org.pentaho.di.core.row.value.ValueMetaBoolean; import org.pentaho.di.core.row.value.ValueMetaDate; import org.pentaho.di.core.row.value.ValueMetaInteger; import org.pentaho.di.core.row.value.ValueMetaNumber; import org.pentaho.di.core.row.value.ValueMetaString; import org.pentaho.di.trans.TransMeta.TransformationType; import org.pentaho.di.trans.step.StepInterface; import org.pentaho.di.trans.step.StepMetaDataCombi; import junit.framework.TestCase; public class TransSingleThreadTest extends TestCase { public void testSingleThreadedTrans() throws Exception { KettleEnvironment.init(); // // Create a new transformation... // TransMeta transMeta = new TransMeta( "testfiles/SingleThreadedTest - Stream Lookup.ktr" ); transMeta.setTransformationType( TransformationType.SingleThreaded ); long transStart = System.currentTimeMillis(); // Now execute the transformation... Trans trans = new Trans( transMeta ); trans.setLogLevel( LogLevel.MINIMAL ); trans.prepareExecution( null ); StepInterface si = trans.getStepInterface( "OUTPUT", 0 ); RowStepCollector rc = new RowStepCollector(); si.addRowListener( rc ); RowProducer rp = trans.addRowProducer( "INPUT", 0 ); trans.startThreads(); // The single threaded transformation type expects us to run the steps // ourselves. // SingleThreadedTransExecutor executor = new SingleThreadedTransExecutor( trans ); // Initialize all steps // executor.init(); int iterations = 1000000; long totalWait = 0; List<RowMetaAndData> inputList = createData(); for ( int i = 0; i < iterations; i++ ) { // add rows for ( RowMetaAndData rm : inputList ) { Object[] copy = rm.getRowMeta().cloneRow( rm.getData() ); rp.putRow( rm.getRowMeta(), copy ); } long start = System.currentTimeMillis(); boolean cont = executor.oneIteration(); if ( !cont ) { fail( "We don't expect any step or the transformation to be done before the end of all iterations." ); } long end = System.currentTimeMillis(); long delay = end - start; totalWait += delay; if ( i > 0 && ( i % 100000 ) == 0 ) { long rowsProcessed = trans.findRunThread( "bottles" ).getLinesRead(); double speed = Const.round( ( rowsProcessed ) / ( (double) ( end - transStart ) / 1000 ), 1 ); int totalRows = 0; for ( StepMetaDataCombi combi : trans.getSteps() ) { for ( RowSet rowSet : combi.step.getInputRowSets() ) { totalRows += rowSet.size(); } for ( RowSet rowSet : combi.step.getOutputRowSets() ) { totalRows += rowSet.size(); } } System.out.println( "#" + i + " : Finished processing one iteration in " + delay + "ms, average is: " + Const.round( ( (double) totalWait / ( i + 1 ) ), 1 ) + ", speed=" + speed + " row/s, total rows buffered: " + totalRows ); } List<RowMetaAndData> resultRows = rc.getRowsWritten(); // Result has one row less because we filter out one. // We also join with 3 identical rows in a data grid, giving 9 rows of which 3 are filtered out // assertEquals( "Error found in iteration " + i, 6, resultRows.size() ); rc.clear(); } rp.finished(); // Dispose all steps. // executor.dispose(); long rowsProcessed = trans.findRunThread( "bottles" ).getLinesRead(); long transEnd = System.currentTimeMillis(); long transTime = transEnd - transStart; System.out.println( "Average delay before idle : " + Const.round( ( (double) totalWait / iterations ), 1 ) ); double transTimeSeconds = Const.round( ( (double) transTime / 1000 ), 1 ); System.out.println( "Total transformation runtime for " + iterations + " iterations :" + transTimeSeconds + " seconds" ); double transTimePerIteration = Const.round( ( (double) transTime / iterations ), 2 ); System.out.println( "Runtime per iteration: " + transTimePerIteration + " miliseconds" ); double rowsPerSecond = Const.round( ( rowsProcessed ) / ( (double) transTime / 1000 ), 1 ); System.out.println( "Average speed: " + rowsPerSecond + " rows/second" ); } public RowMetaInterface createRowMetaInterface() { RowMetaInterface rm = new RowMeta(); ValueMetaInterface[] valuesMeta = { new ValueMetaString( "field1" ), new ValueMetaInteger( "field2" ), new ValueMetaNumber( "field3" ), new ValueMetaDate( "field4" ), new ValueMetaBoolean( "field5" ), new ValueMetaBigNumber( "field6" ), new ValueMetaBigNumber( "field7" ), }; for ( int i = 0; i < valuesMeta.length; i++ ) { rm.addValueMeta( valuesMeta[i] ); } return rm; } public List<RowMetaAndData> createData() { List<RowMetaAndData> list = new ArrayList<RowMetaAndData>(); RowMetaInterface rm = createRowMetaInterface(); Object[] r1 = new Object[] { "KETTLE1", new Long( 123L ), new Double( 10.5D ), new Date(), Boolean.TRUE, BigDecimal.valueOf( 123.45 ), BigDecimal.valueOf( 123.60 ) }; Object[] r2 = new Object[] { "KETTLE2", new Long( 500L ), new Double( 20.0D ), new Date(), Boolean.FALSE, BigDecimal.valueOf( 123.45 ), BigDecimal.valueOf( 123.60 ) }; Object[] r3 = new Object[] { "KETTLE3", new Long( 501L ), new Double( 21.0D ), new Date(), Boolean.FALSE, BigDecimal.valueOf( 123.45 ), BigDecimal.valueOf( 123.70 ) }; list.add( new RowMetaAndData( rm, r1 ) ); list.add( new RowMetaAndData( rm, r2 ) ); list.add( new RowMetaAndData( rm, r3 ) ); return list; } }