Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2020 Red Hat, Inc. and/or its affiliates.
*
* 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.optaplanner.benchmark.impl;
import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.time.OffsetDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.optaplanner.benchmark.api.PlannerBenchmark;
import org.optaplanner.benchmark.api.PlannerBenchmarkException;
import org.optaplanner.benchmark.impl.report.BenchmarkReport;
import org.optaplanner.benchmark.impl.result.BenchmarkResultIO;
import org.optaplanner.benchmark.impl.result.PlannerBenchmarkResult;
import org.optaplanner.benchmark.impl.result.ProblemBenchmarkResult;
import org.optaplanner.benchmark.impl.result.SingleBenchmarkResult;
import org.optaplanner.benchmark.impl.result.SolverBenchmarkResult;
import org.optaplanner.benchmark.impl.result.SubSingleBenchmarkResult;
import org.optaplanner.benchmark.impl.statistic.ProblemStatistic;
import org.optaplanner.benchmark.impl.statistic.PureSubSingleStatistic;
import org.optaplanner.core.config.SolverConfigContext;
import org.optaplanner.core.config.solver.termination.TerminationConfig;
import org.optaplanner.core.config.util.ConfigUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DefaultPlannerBenchmark implements PlannerBenchmark {
protected final transient Logger logger = LoggerFactory.getLogger(getClass());
protected final transient Logger singleBenchmarkRunnerExceptionLogger = LoggerFactory.getLogger(
getClass().getName() + ".singleBenchmarkRunnerException");
private final PlannerBenchmarkResult plannerBenchmarkResult;
private final SolverConfigContext solverConfigContext;
private final File benchmarkDirectory;
private final ExecutorService warmUpExecutorService;
private final ExecutorCompletionService warmUpExecutorCompletionService;
private final ExecutorService executorService;
private final BenchmarkResultIO benchmarkResultIO;
private final BenchmarkReport benchmarkReport;
private long startingSystemTimeMillis = -1L;
private SubSingleBenchmarkRunner firstFailureSubSingleBenchmarkRunner = null;
public DefaultPlannerBenchmark(
PlannerBenchmarkResult plannerBenchmarkResult, SolverConfigContext solverConfigContext,
File benchmarkDirectory,
ExecutorService warmUpExecutorService, ExecutorService executorService,
BenchmarkReport benchmarkReport) {
this.plannerBenchmarkResult = plannerBenchmarkResult;
this.solverConfigContext = solverConfigContext;
this.benchmarkDirectory = benchmarkDirectory;
this.warmUpExecutorService = warmUpExecutorService;
warmUpExecutorCompletionService = new ExecutorCompletionService<>(warmUpExecutorService);
this.executorService = executorService;
this.benchmarkReport = benchmarkReport;
benchmarkResultIO = new BenchmarkResultIO();
}
public PlannerBenchmarkResult getPlannerBenchmarkResult() {
return plannerBenchmarkResult;
}
public File getBenchmarkDirectory() {
return benchmarkDirectory;
}
public BenchmarkReport getBenchmarkReport() {
return benchmarkReport;
}
// ************************************************************************
// Benchmark methods
// ************************************************************************
@Override
public void benchmark() {
benchmarkingStarted();
warmUp();
runSingleBenchmarks();
benchmarkingEnded();
}
public void benchmarkingStarted() {
if (startingSystemTimeMillis >= 0L) {
throw new IllegalStateException("This benchmark has already ran before.");
}
startingSystemTimeMillis = System.currentTimeMillis();
plannerBenchmarkResult.setStartingTimestamp(OffsetDateTime.now());
List solverBenchmarkResultList = plannerBenchmarkResult.getSolverBenchmarkResultList();
if (ConfigUtils.isEmptyCollection(solverBenchmarkResultList)) {
throw new IllegalArgumentException(
"The solverBenchmarkResultList (" + solverBenchmarkResultList + ") cannot be empty.");
}
initBenchmarkDirectoryAndSubdirectories();
plannerBenchmarkResult.initSystemProperties();
logger.info("Benchmarking started: parallelBenchmarkCount ({})"
+ " for problemCount ({}), solverCount ({}), totalSubSingleCount ({}).",
plannerBenchmarkResult.getParallelBenchmarkCount(),
plannerBenchmarkResult.getUnifiedProblemBenchmarkResultList().size(),
solverBenchmarkResultList.size(),
plannerBenchmarkResult.getTotalSubSingleCount());
}
private void initBenchmarkDirectoryAndSubdirectories() {
if (benchmarkDirectory == null) {
throw new IllegalArgumentException("The benchmarkDirectory (" + benchmarkDirectory + ") must not be null.");
}
// benchmarkDirectory usually already exists
benchmarkDirectory.mkdirs();
plannerBenchmarkResult.initBenchmarkReportDirectory(benchmarkDirectory);
}
private void warmUp() {
if (plannerBenchmarkResult.getWarmUpTimeMillisSpentLimit() <= 0L) {
return;
}
logger.info("================================================================================");
logger.info("Warm up started");
logger.info("================================================================================");
long timeLeftTotal = plannerBenchmarkResult.getWarmUpTimeMillisSpentLimit();
int parallelBenchmarkCount = plannerBenchmarkResult.getParallelBenchmarkCount();
int solverBenchmarkResultCount = plannerBenchmarkResult.getSolverBenchmarkResultList().size();
/*
* cyclesCount needs to be long, as opposed to its natural int,
* otherwise JDK 11 compiler uses Math.floorDiv(long, int), which is only available on JDK 9+.
* When such compiled code is then used on Java 8, there is a NoSuchMethodError.
* All is fine When the code is compiled on JDK 8, the compiler will use the good old Math.floorDiv(long, long).
* TODO Remove when JDK 8 is no longer supported.
*/
long cyclesCount = ConfigUtils.ceilDivide(solverBenchmarkResultCount, parallelBenchmarkCount);
long timeLeftPerCycle = Math.floorDiv(timeLeftTotal, cyclesCount);
Map> originalProblemStatisticMap = new HashMap<>(
plannerBenchmarkResult.getUnifiedProblemBenchmarkResultList().size());
ConcurrentMap singleBenchmarkResultIndexMap = new ConcurrentHashMap<>(
solverBenchmarkResultCount);
Map warmUpConfigBackupMap = WarmUpConfigBackup
.backupBenchmarkConfig(plannerBenchmarkResult, originalProblemStatisticMap);
SolverBenchmarkResult[] solverBenchmarkResultCycle = new SolverBenchmarkResult[parallelBenchmarkCount];
int solverBenchmarkResultIndex = 0;
for (int i = 0; i < cyclesCount; i++) {
long timeCycleEnd = System.currentTimeMillis() + timeLeftPerCycle;
for (int j = 0; j < parallelBenchmarkCount; j++) {
solverBenchmarkResultCycle[j] = plannerBenchmarkResult.getSolverBenchmarkResultList()
.get(solverBenchmarkResultIndex % solverBenchmarkResultCount);
solverBenchmarkResultIndex++;
}
ConcurrentMap, SubSingleBenchmarkRunner> futureMap = new ConcurrentHashMap<>(
parallelBenchmarkCount);
warmUpPopulate(futureMap, singleBenchmarkResultIndexMap, solverBenchmarkResultCycle, timeLeftPerCycle);
warmUp(futureMap, singleBenchmarkResultIndexMap, timeCycleEnd);
}
WarmUpConfigBackup.restoreBenchmarkConfig(plannerBenchmarkResult, originalProblemStatisticMap, warmUpConfigBackupMap);
List notFinishedWarmUpList = warmUpExecutorService.shutdownNow();
if (!notFinishedWarmUpList.isEmpty()) {
throw new IllegalStateException("Impossible state: notFinishedWarmUpList (" + notFinishedWarmUpList
+ ") is not empty.");
}
logger.info("================================================================================");
logger.info("Warm up ended");
logger.info("================================================================================");
}
private void warmUpPopulate(Map, SubSingleBenchmarkRunner> futureMap,
ConcurrentMap singleBenchmarkResultIndexMap,
SolverBenchmarkResult[] solverBenchmarkResultArray, long timeLeftPerSolverConfig) {
for (SolverBenchmarkResult solverBenchmarkResult : solverBenchmarkResultArray) {
TerminationConfig originalTerminationConfig = solverBenchmarkResult.getSolverConfig().getTerminationConfig();
TerminationConfig tmpTerminationConfig = new TerminationConfig();
if (originalTerminationConfig != null) {
tmpTerminationConfig.inherit(originalTerminationConfig);
}
tmpTerminationConfig.shortenTimeMillisSpentLimit(timeLeftPerSolverConfig);
solverBenchmarkResult.getSolverConfig().setTerminationConfig(tmpTerminationConfig);
Integer singleBenchmarkResultIndex = singleBenchmarkResultIndexMap.get(solverBenchmarkResult);
singleBenchmarkResultIndex = (singleBenchmarkResultIndex == null) ? 0
: singleBenchmarkResultIndex % solverBenchmarkResult.getSingleBenchmarkResultList().size();
SingleBenchmarkResult singleBenchmarkResult = solverBenchmarkResult.getSingleBenchmarkResultList()
.get(singleBenchmarkResultIndex);
// Just take the first subSingle, we don't need to warm up each one
SubSingleBenchmarkRunner subSingleBenchmarkRunner = new SubSingleBenchmarkRunner(
singleBenchmarkResult.getSubSingleBenchmarkResultList().get(0), true, solverConfigContext);
Future future = warmUpExecutorCompletionService.submit(subSingleBenchmarkRunner);
futureMap.put(future, subSingleBenchmarkRunner);
singleBenchmarkResultIndexMap.put(solverBenchmarkResult, singleBenchmarkResultIndex + 1);
}
}
private void warmUp(Map, SubSingleBenchmarkRunner> futureMap,
ConcurrentMap singleBenchmarkResultIndexMap, long timePhaseEnd) {
// Wait for the warm up benchmarks to complete
int tasksCount = futureMap.size();
// Use a counter because completion order of futures is different from input order
for (int i = 0; i < tasksCount; i++) {
Future future;
try {
future = warmUpExecutorCompletionService.take();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IllegalStateException("Waiting for a warm up singleBenchmarkRunner was interrupted.", e);
}
Throwable failureThrowable = null;
SubSingleBenchmarkRunner subSingleBenchmarkRunner;
try {
// Explicitly returning it in the Callable guarantees memory visibility
subSingleBenchmarkRunner = future.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
subSingleBenchmarkRunner = futureMap.get(future);
singleBenchmarkRunnerExceptionLogger.error("The warm up singleBenchmarkRunner ({}) was interrupted.",
subSingleBenchmarkRunner, e);
failureThrowable = e;
} catch (ExecutionException e) {
Throwable cause = e.getCause();
subSingleBenchmarkRunner = futureMap.get(future);
singleBenchmarkRunnerExceptionLogger.warn("The warm up singleBenchmarkRunner ({}) failed.",
subSingleBenchmarkRunner, cause);
failureThrowable = cause;
}
if (failureThrowable != null) {
subSingleBenchmarkRunner.setFailureThrowable(failureThrowable);
if (firstFailureSubSingleBenchmarkRunner == null) {
firstFailureSubSingleBenchmarkRunner = subSingleBenchmarkRunner;
}
}
SolverBenchmarkResult solverBenchmarkResult = subSingleBenchmarkRunner.getSubSingleBenchmarkResult()
.getSingleBenchmarkResult().getSolverBenchmarkResult();
long timeLeftInCycle = timePhaseEnd - System.currentTimeMillis();
if (timeLeftInCycle > 0L) {
SolverBenchmarkResult[] solverBenchmarkResultSingleton = new SolverBenchmarkResult[] { solverBenchmarkResult };
warmUpPopulate(futureMap, singleBenchmarkResultIndexMap, solverBenchmarkResultSingleton, timeLeftInCycle);
tasksCount++;
}
}
}
protected void runSingleBenchmarks() {
Map> futureMap = new HashMap<>();
for (ProblemBenchmarkResult