All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.dagere.kopeme.PerformanceTestRunner Maven / Gradle / Ivy

package de.dagere.kopeme;

import static de.dagere.kopeme.PerformanceTestUtils.saveData;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import de.dagere.kopeme.TimeBoundExecution.Type;
import de.dagere.kopeme.annotations.Assertion;
import de.dagere.kopeme.annotations.MaximalRelativeStandardDeviation;
import de.dagere.kopeme.annotations.PerformanceTest;
import de.dagere.kopeme.datacollection.DataCollectorList;
import de.dagere.kopeme.datacollection.TestResult;
import de.dagere.kopeme.datastorage.RunConfiguration;
import de.dagere.kopeme.datastorage.SaveableTestData;

/**
 * Represents an execution of all runs of one test.
 * 
 * @author dagere
 * 
 */
public class PerformanceTestRunner {

   private static Logger LOG = LogManager.getLogger(PerformanceTestRunner.class);

   protected final Class klasse;
   protected final Object instanz;
   protected final Method method;
   protected int executionTimes, warmupExecutions, repetitions, minEarlyStopExecutions;
   private long timeout;
   protected Map maximalRelativeStandardDeviation;
   protected Map assertationvalues;
   protected String filename;
   private boolean isFinished = false;
   private final RunConfiguration configuration;

   /**
    * Initializes the PerformanceTestRunner.
    * 
    * @param klasse Class whose tests should be run
    * @param instance Instance of the class, whose tests should be run
    * @param method Test method that should be run
    */
   public PerformanceTestRunner(final Class klasse, final Object instance, final Method method) {
      this.klasse = klasse;
      this.instanz = instance;
      this.method = method;

      final PerformanceTest annotation = method.getAnnotation(PerformanceTest.class);

      if (annotation != null) {
         executionTimes = annotation.iterations();
         warmupExecutions = annotation.warmup();
         repetitions = annotation.repetitions();
         minEarlyStopExecutions = annotation.minEarlyStopExecutions();
         timeout = annotation.timeout();
         maximalRelativeStandardDeviation = new HashMap<>();

         for (final MaximalRelativeStandardDeviation maxDev : annotation.deviations()) {
            maximalRelativeStandardDeviation.put(maxDev.collectorname(), maxDev.maxvalue());
         }

         assertationvalues = new HashMap<>();
         for (final Assertion a : annotation.assertions()) {
            assertationvalues.put(a.collectorname(), a.maxvalue());
         }
         configuration = new RunConfiguration(annotation);
      } else {
         configuration = new RunConfiguration(5, 1, false, false, false, true, false, false);
      }

      filename = klasse.getName();
      LOG.info("Executing Performancetest: " + filename);
   }

   /**
    * Runs the performance test.
    * 
    * @throws Throwable Any error that occurs during the test
    */
   public void evaluate() throws Throwable {
      final Finishable finishable = new Finishable() {
         @Override
         public void run() {
            TestResult tr = null;
            try {
               if (method.getParameterTypes().length == 1) {
                  tr = executeComplexTest();
               } else {
                  tr = executeSimpleTest();
               }
               if (!assertationvalues.isEmpty()) {
                  tr.checkValues(assertationvalues);
               }
            } catch (IllegalAccessException | InvocationTargetException e) {
               e.printStackTrace();
            }
         }

         @Override
         public boolean isFinished() {
            return PerformanceTestRunner.this.isFinished;
         }

         @Override
         public void setFinished(final boolean isFinished) {
            PerformanceTestRunner.this.isFinished = isFinished;
         }

      };

      final TimeBoundExecution tbe = new TimeBoundExecution(finishable, timeout, Type.METHOD, configuration.isUseKieker());
      tbe.execute();

      LOG.trace("Test {} beendet", filename);
   }

   /**
    * Executes a complex test, i.e. a test which has TestResult as a parameter.
    * 
    * @return New TestResult
    * @throws IllegalAccessException Thrown if an error during method access occurs
    * @throws InvocationTargetException Thrown if an error during method access occurs
    */
   private TestResult executeComplexTest() throws IllegalAccessException, InvocationTargetException {
      final TestResult tr = new TestResult(method.getName(), warmupExecutions, DataCollectorList.NONE, true);
      final Object[] params = { tr };
      runWarmup(params);

      try {
         if (!PerformanceTestUtils.checkCollectorValidity(tr, assertationvalues, maximalRelativeStandardDeviation)) {
            LOG.warn("Not all Collectors are valid!");
         }
         TestResult finalResult = new TestResult(method.getName(), executionTimes, DataCollectorList.STANDARD, false);
         params[0] = finalResult;
         tr.beforeRun();
         final PerformanceKoPeMeStatement pts = new PerformanceKoPeMeStatement(method, instanz, false, params, finalResult);
         runMainExecution(pts, finalResult);
      } catch (final Throwable t) {
         tr.finalizeCollection(t);
         saveData(SaveableTestData.createErrorTestData(method.getName(), filename, tr, configuration));
         throw t;
      }
      saveData(SaveableTestData.createFineTestData(method.getName(), filename, tr, configuration));
      tr.checkValues();
      return tr;
   }

   /**
    * Executes a simple test, i.e. a test without parameters.
    * 
    * @return The result of the test
    * @throws IllegalAccessException Thrown if an error during method access occurs
    * @throws InvocationTargetException Thrown if an error during method access occurs
    */
   private TestResult executeSimpleTest() throws IllegalAccessException, InvocationTargetException {
      TestResult tr = new TestResult(method.getName(), warmupExecutions, DataCollectorList.STANDARD, false);
      final Object[] params = {};
      runWarmup(params);
      tr.deleteTempFile();
      tr = new TestResult(method.getName(), executionTimes, DataCollectorList.STANDARD, true);

      if (!PerformanceTestUtils.checkCollectorValidity(tr, assertationvalues, maximalRelativeStandardDeviation)) {
         LOG.warn("Not all Collectors are valid!");
      }
      final long start = System.currentTimeMillis();
      try {
         tr.beforeRun();
         final PerformanceKoPeMeStatement pts = new PerformanceKoPeMeStatement(method, instanz, true, params, tr);
         runMainExecution(pts, tr);
      } catch (final Throwable t) {
         tr.finalizeCollection(t);
         saveData(SaveableTestData.createErrorTestData(method.getName(), filename, tr, configuration));
         throw t;
      }
      LOG.trace("Zeit: " + (System.currentTimeMillis() - start));
      tr.finalizeCollection();
      saveData(SaveableTestData.createFineTestData(method.getName(), filename, tr, configuration));
      tr.checkValues();
      return tr;
   }

   /**
    * Runs the warmup-executions of a test.
    * 
    * @param params The params for the method executions
    * @throws IllegalAccessException Thrown if an error during method access occurs
    * @throws InvocationTargetException Thrown if an error during method access occurs
    */
   private void runWarmup(final Object[] params) throws IllegalAccessException, InvocationTargetException {
      final String methodString = method.getClass().getName() + "." + method.getName();
      for (int i = 1; i <= warmupExecutions; i++) {
         LOG.info("--- Starting warmup execution " + methodString + " - " + i + "/" + warmupExecutions + " ---");
         method.invoke(instanz, params);
         LOG.info("--- Stopping warmup execution " + i + "/" + warmupExecutions + " ---");
      }
   }

   /**
    * Runs the main Executions of a test.
    * 
    * @param pts The Statement that should be run
    * @param tr The testresult that should save the results and eventually cancel the executions early
    * @throws IllegalAccessException Thrown if an error during method access occurs
    * @throws InvocationTargetException Thrown if an error during method access occurs
    */
   private void runMainExecution(final PerformanceKoPeMeStatement pts, final TestResult tr) throws IllegalAccessException, InvocationTargetException {
      final String methodString = method.getClass().getName() + "." + method.getName();
      int executions;
      for (executions = 1; executions <= executionTimes; executions++) {
         LOG.debug("--- Starting execution " + methodString + " " + executions + "/" + executionTimes + " ---");
         for (int reptition = 0; reptition < repetitions; reptition++) {
            pts.evaluate();
         }
         LOG.debug("--- Stopping execution " + executions + "/" + executionTimes + " ---");
         for (final Map.Entry entry : maximalRelativeStandardDeviation.entrySet()) {
            LOG.debug("Entry: {} Aim: {}", entry.getKey(), entry.getValue());
         }
         tr.setRealExecutions(executions);
         // if (executions >= minEarlyStopExecutions && !maximalRelativeStandardDeviation.isEmpty()
         // && tr.isRelativeStandardDeviationBelow(maximalRelativeStandardDeviation)) {
         // break;
         // }
      }
      LOG.debug("Executions: " + executions);
      tr.setRealExecutions(executions);
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy