use of com.carrotsearch.ant.tasks.junit4.balancers.SuiteHint in project randomizedtesting by randomizedtesting.
the class JUnit4 method loadBalanceSuites.
/**
* Perform load balancing of the set of suites. Sets {@link ForkedJvmInfo#testSuites}
* to suites preassigned to a given slave and returns a pool of suites
* that should be load-balanced dynamically based on job stealing.
*/
private List<String> loadBalanceSuites(List<ForkedJvmInfo> jvmInfo, TestsCollection testsCollection, List<SuiteBalancer> balancers) {
// Order test suites identically for balancers.
// and split into replicated and non-replicated suites.
Map<Boolean, List<String>> partitioned = sortAndSplitReplicated(testsCollection.testClasses);
Collection<String> replicated = partitioned.get(true);
Collection<String> suites = partitioned.get(false);
final List<SuiteBalancer> balancersWithFallback = new ArrayList<>(balancers);
balancersWithFallback.add(new RoundRobinBalancer());
// Go through all the balancers, the first one to assign a suite wins.
final List<String> remaining = new ArrayList<>(suites);
Collections.sort(remaining);
final Map<Integer, List<Assignment>> perJvmAssignments = new HashMap<>();
for (ForkedJvmInfo si : jvmInfo) {
perJvmAssignments.put(si.id, new ArrayList<Assignment>());
}
final int jvmCount = jvmInfo.size();
for (SuiteBalancer balancer : balancersWithFallback) {
balancer.setOwner(this);
final List<Assignment> assignments = balancer.assign(Collections.unmodifiableCollection(remaining), jvmCount, masterSeed());
for (Assignment e : assignments) {
if (e == null) {
throw new RuntimeException("Balancer must return non-null assignments.");
}
if (!remaining.remove(e.suiteName)) {
throw new RuntimeException("Balancer must return suite name as a key: " + e.suiteName);
}
log(String.format(Locale.ROOT, "Assignment hint: J%-2d (cost %5d) %s (by %s)", e.slaveId, e.estimatedCost, e.suiteName, balancer.getClass().getSimpleName()), Project.MSG_VERBOSE);
perJvmAssignments.get(e.slaveId).add(e);
}
}
if (remaining.size() != 0) {
throw new RuntimeException("Not all suites assigned?: " + remaining);
}
if (shuffleOnSlave) {
// (sort first, then shuffle with a constant seed).
for (List<Assignment> assignments : perJvmAssignments.values()) {
Collections.sort(assignments);
Collections.shuffle(assignments, new Random(this.masterSeed()));
}
}
// Take a fraction of suites scheduled as last on each slave and move them to a common
// job-stealing queue.
List<SuiteHint> stealingQueueWithHints = new ArrayList<>();
for (ForkedJvmInfo si : jvmInfo) {
final List<Assignment> assignments = perJvmAssignments.get(si.id);
int moveToCommon = (int) (assignments.size() * dynamicAssignmentRatio);
if (moveToCommon > 0) {
final List<Assignment> movedToCommon = assignments.subList(assignments.size() - moveToCommon, assignments.size());
for (Assignment a : movedToCommon) {
stealingQueueWithHints.add(new SuiteHint(a.suiteName, a.estimatedCost));
}
movedToCommon.clear();
}
final ArrayList<String> slaveSuites = (si.testSuites = new ArrayList<>());
for (Assignment a : assignments) {
slaveSuites.add(a.suiteName);
}
}
// Sort stealing queue according to descending cost.
Collections.sort(stealingQueueWithHints, SuiteHint.DESCENDING_BY_WEIGHT);
// to enforce all replicated suites run on each bound JVM.
if (!replicated.isEmpty()) {
for (ForkedJvmInfo si : jvmInfo) {
for (String suite : replicated) {
si.testSuites.add(suite);
}
if (shuffleOnSlave) {
// Shuffle suites on slaves so that the result is always the same wrt master seed
// (sort first, then shuffle with a constant seed).
Collections.shuffle(si.testSuites, new Random(this.masterSeed()));
}
}
}
// Dump scheduling information.
for (ForkedJvmInfo si : jvmInfo) {
log("Forked JVM J" + si.id + " assignments (after shuffle):", Project.MSG_VERBOSE);
for (String suiteName : si.testSuites) {
log(" " + suiteName, Project.MSG_VERBOSE);
}
}
log("Stealing queue:", Project.MSG_VERBOSE);
for (SuiteHint suiteHint : stealingQueueWithHints) {
log(" " + suiteHint.suiteName + " " + suiteHint.cost, Project.MSG_VERBOSE);
}
List<String> stealingQueue = new ArrayList<>(stealingQueueWithHints.size());
for (SuiteHint suiteHint : stealingQueueWithHints) {
stealingQueue.add(suiteHint.suiteName);
}
return stealingQueue;
}
Aggregations