| /* |
| * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Oracle - initial API and implementation from Oracle TopLink |
| package org.eclipse.persistence.testing.framework; |
| |
| import java.util.*; |
| |
| import org.eclipse.persistence.sessions.*; |
| |
| /** |
| * Used to compare the performance of two different task/processes. |
| * Defines a test and testBaseLine method and compares the performance of the two. |
| * Use the static REPEATS for number of repeats, and computes the averge difference/etc. |
| * Note that setup should do any setup and the test should only do what is being compared. |
| */ |
| public abstract class PerformanceComparisonTestCase extends TestCase implements PerformanceComparisonTest { |
| |
| /** |
| * The allowable percentage difference for test compared to the baseline. |
| */ |
| public double allowableDecrease; |
| |
| /** |
| * The total time (ms) to run each of the test runs. |
| * This is used to compute the number of test iterations to use, |
| * the tests are then still timed based on that number of iterations. |
| */ |
| public long testRunTime; |
| |
| /** |
| * List of performance tests, the source test is the baseline, |
| * n other tests can be added to compare with. |
| */ |
| protected List tests; |
| |
| /** |
| * The count of the iterations. |
| * This is maintained by the test to allow concurrent tests to manage the count. |
| */ |
| protected volatile int iterations; |
| |
| public PerformanceComparisonTestCase() { |
| this.testRunTime = DEFAULT_TEST_TIME; |
| this.allowableDecrease = DEFAULT_ALLOWABLE_DECREASE; |
| this.tests = new ArrayList(); |
| } |
| |
| /** |
| * Return the count of the iterations. |
| * This is maintained by the test to allow concurrent tests to manage the count. |
| */ |
| @Override |
| public int getIterations() { |
| return iterations; |
| } |
| |
| /** |
| * Increment the iteration count. |
| * This is maintained by the test to allow concurrent tests to manage the count. |
| */ |
| @Override |
| public void incrementIterations() { |
| this.iterations++; |
| } |
| |
| /** |
| * Reset the iteration count. |
| * This is maintained by the test to allow concurrent tests to manage the count. |
| */ |
| @Override |
| public void resetIterations() { |
| this.iterations = 0; |
| } |
| |
| /** |
| * Allows any test specific setup before starting the test run. |
| */ |
| @Override |
| public void startTest() { |
| } |
| |
| /** |
| * Allows any test specific setup before starting the test run. |
| */ |
| @Override |
| public void endTest() { |
| } |
| |
| /** |
| * Return the total time (ms) to run each of the test runs. |
| * This is used to compute the number of test iterations to use, |
| * the tests are then still timed based on that number of iterations. |
| */ |
| @Override |
| public long getTestRunTime() { |
| return testRunTime; |
| } |
| |
| /** |
| * Set the total time (ms) to run each of the test runs. |
| * This is used to compute the number of test iterations to use, |
| * the tests are then still timed based on that number of iterations. |
| */ |
| @Override |
| public void setTestRunTime(long testRunTime) { |
| this.testRunTime = testRunTime; |
| } |
| |
| /** |
| * Return the allowable percentage difference for test compared to the baseline. |
| */ |
| @Override |
| public double getAllowableDecrease() { |
| return allowableDecrease; |
| } |
| |
| /** |
| * Set the allowable percentage difference for test compared to the baseline. |
| */ |
| @Override |
| public void setAllowableDecrease(double allowableDecrease) { |
| this.allowableDecrease = allowableDecrease; |
| } |
| |
| /** |
| * Return the performance tests to compare the base-line with. |
| */ |
| @Override |
| public List getTests() { |
| return tests; |
| } |
| |
| /** |
| * Add a performance tests to compare the base-line with. |
| */ |
| @Override |
| public void addTest(TestCase test) { |
| getTests().add(test); |
| } |
| |
| |
| /** |
| * Executes this test case. |
| * Log some debug info as perf tests sometimes take a long time or hang. |
| */ |
| @Override |
| public void execute(TestExecutor executor) { |
| System.out.println("Begin:" + getName()); |
| try { |
| super.execute(executor); |
| } finally { |
| System.out.println("End:" + getName() + ":" + getTestResult().getTotalTime()); |
| } |
| } |
| |
| /** |
| * Executes this test comparison with the base-line. |
| * Static allow reuse with EJB tests. |
| */ |
| @Override |
| public void executeTest() throws Throwable { |
| executeTest(this); |
| } |
| |
| /** |
| * Executes this test comparison with the base-line. |
| * Static allow reuse with EJB tests. |
| */ |
| public static void executeTest(PerformanceComparisonTest performanceTest) throws Throwable { |
| PerformanceComparisonTestResult result = new PerformanceComparisonTestResult((TestCase)performanceTest, "Passed"); |
| ((TestCase)performanceTest).setTestResult(result); |
| try { |
| // Repeat the test and baseline for the number of repeats. |
| for (int index = 0; index < REPEATS; index++) { |
| long startTime, endTime; |
| int iterations = 0; |
| try { |
| System.gc(); |
| Thread.sleep(1000); |
| performanceTest.resetIterations(); |
| startTime = System.currentTimeMillis(); |
| performanceTest.startTest(); |
| endTime = startTime; |
| // Count how many times the test can be invoked in the run time. |
| // This allows for the test run time to be easily changed. |
| while ((startTime + performanceTest.getTestRunTime()) >= endTime) { |
| ((TestCase)performanceTest).test(); |
| performanceTest.incrementIterations(); |
| endTime = System.currentTimeMillis(); |
| } |
| iterations = performanceTest.getIterations(); |
| } finally { |
| performanceTest.endTest(); |
| } |
| result.addTestCount(iterations, 0); |
| |
| for (int testIndex = 0; testIndex < performanceTest.getTests().size(); testIndex++) { |
| PerformanceComparisonTest test = (PerformanceComparisonTest)performanceTest.getTests().get(testIndex); |
| ((TestCase)test).setExecutor(((TestCase)performanceTest).getExecutor()); |
| try { |
| System.gc(); |
| Thread.sleep(1000); |
| performanceTest.resetIterations(); |
| startTime = System.currentTimeMillis(); |
| test.startTest(); |
| endTime = startTime; |
| // Count how many times the test can be invoked in the run time. |
| // This allows for the test run time to be easily changed. |
| while ((startTime + performanceTest.getTestRunTime()) >= endTime) { |
| ((TestCase)test).test(); |
| performanceTest.incrementIterations(); |
| endTime = System.currentTimeMillis(); |
| } |
| iterations = performanceTest.getIterations(); |
| } finally { |
| test.endTest(); |
| } |
| result.addTestCount(iterations, testIndex + 1); |
| } |
| } |
| } finally { |
| result.computeResults(); |
| } |
| } |
| |
| /** |
| * Verify each test comparison is within the set limits. |
| * Static allow reuse with EJB tests. |
| */ |
| @Override |
| public void verify() { |
| verify(this); |
| } |
| |
| /** |
| * Verify each test comparison is within the set limits. |
| * Static allow reuse with EJB tests. |
| */ |
| public static void verify(PerformanceComparisonTest performanceTest) { |
| PerformanceComparisonTestResult result = (PerformanceComparisonTestResult)((TestCase)performanceTest).getTestResult(); |
| for (int index = 0; index < result.percentageDifferences.size(); index++) { |
| double difference = ((Number)result.percentageDifferences.get(index)).doubleValue(); |
| PerformanceComparisonTest test = (PerformanceComparisonTest)performanceTest.getTests().get(index); |
| double allowable = test.getAllowableDecrease(); |
| if (difference < allowable) { |
| throw new TestErrorException("Decrease lower than allowable detected, decrease: " + difference + |
| " allowed: " + allowable + " test: " + test.getName()); |
| } |
| } |
| } |
| |
| /** |
| * Build and return an emulated session for isolated Java performance from the database. |
| */ |
| public Session buildEmulatedSession() { |
| try { |
| Class.forName(getSession().getLogin().getDriverClassName()); |
| } catch (Exception ignore) {} |
| Project project = getSession().getProject().clone(); |
| DatabaseLogin login = (DatabaseLogin)project.getLogin().clone(); |
| try { |
| Class.forName(login.getDriverClassName()); |
| } catch (Exception ignore) {} |
| //login.useDirectDriverConnect(); |
| login.setDriverClass(org.eclipse.persistence.testing.tests.performance.emulateddb.EmulatedDriver.class); |
| login.setConnectionString("emulate:" + login.getConnectionString()); |
| project.setLogin(login); |
| DatabaseSession session = project.createDatabaseSession(); |
| session.setSessionLog(getSession().getSessionLog()); |
| session.login(); |
| |
| return session; |
| } |
| } |