Commit 4d9fd939 by Michael Schmid

Lots of changes for Dags

parent 72d32bca
......@@ -15,7 +15,17 @@
</properties>
<dependencies>
<dependency>
<dependency>
<groupId>org.jgrapht</groupId>
<artifactId>jgrapht-ext</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.jgrapht</groupId>
<artifactId>jgrapht-core</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>net.sourceforge.cobertura</groupId>
<artifactId>cobertura</artifactId>
<version>2.1.1</version>
......
package mvd.jester;
import java.util.Arrays;
import java.util.Set;
import mvd.jester.model.DagTask;
import mvd.jester.model.SystemSetup;
import mvd.jester.priority.EarliestDeadlineFirst;
import mvd.jester.priority.RateMonotonic;
import mvd.jester.tests.AbstractTest;
import mvd.jester.tests.FonsecaNelis;
import mvd.jester.tests.MelaniButtazzo;
import mvd.jester.tests.SchmidMottok;
/**
......@@ -11,18 +16,15 @@ import mvd.jester.priority.RateMonotonic;
*/
public class App {
public static void main(String[] args) {
for (int p = 4; p <= 16; p *= 2) {
SystemSetup.Builder builder = new SystemSetup.Builder().setNumberOfProcessors(p);
TestEnvironment te = new TestEnvironment(builder, 40000);
for (int p = 4; p <= 4; p *= 2) {
SystemSetup.DagTaskBuilder builder =
new SystemSetup.DagTaskBuilder().setNumberOfProcessors(p);
TestEnvironment te = new TestEnvironment();
te.registerSchedulingAlgorithm(new RateMonotonic());
te.registerSchedulingAlgorithm(new EarliestDeadlineFirst());
Set<ResultCollector<AbstractTest<DagTask>>> tests = te.registerTests(
Arrays.asList(new SchmidMottok(p), new MelaniButtazzo(p), new FonsecaNelis(p)));
te.registerTest(mvd.jester.tests.SchmidMottok.class);
te.registerTest(mvd.jester.tests.MaiaBertogna.class);
te.registerTest(mvd.jester.tests.ChwaLee.class);
te.runExperiments();
te.runExperiments(builder, tests, p, 500);
}
}
}
package mvd.jester;
import java.lang.reflect.Constructor;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import mvd.jester.info.SchedulingInfo;
import mvd.jester.model.SystemSetup;
import mvd.jester.model.DagTask;
import mvd.jester.model.SortedTaskSet;
import mvd.jester.model.SynchronousTask;
import mvd.jester.model.Task;
import mvd.jester.model.SystemSetup.DagTaskBuilder;
import mvd.jester.model.SystemSetup.SynchronousTaskBuilder;
import mvd.jester.priority.PriorityManager;
import mvd.jester.simulator.AbstractSimulator;
import mvd.jester.tests.AbstractTest;
/**
......@@ -14,106 +18,34 @@ import mvd.jester.tests.AbstractTest;
*/
public class TestEnvironment {
private final long numberOfTaskSets;
private final SystemSetup systemSetup;
private final SystemSetup.Builder builder;
private final Set<Constructor<? extends AbstractTest>> abstractTests;
private final Set<Constructor<? extends AbstractSimulator>> abstractSimulators;
private final Set<PriorityManager> schedulingAlgorithms;
public TestEnvironment(SystemSetup.Builder builder, long numberOfTaskSets) {
this.numberOfTaskSets = numberOfTaskSets;
this.abstractTests = new HashSet<>();
this.abstractSimulators = new HashSet<>();
this.schedulingAlgorithms = new HashSet<>();
this.builder = builder;
this.systemSetup = builder.build();
}
public TestEnvironment registerSchedulingAlgorithm(PriorityManager priorityManager) {
schedulingAlgorithms.add(priorityManager);
return this;
}
public TestEnvironment registerTest(Class<? extends AbstractTest> abstractTest) {
try {
abstractTests.add(abstractTest.getConstructor(SystemSetup.class));
} catch (Exception e) {
System.out.println("Missing constructor for abstract test!");
}
return this;
}
public TestEnvironment registerSimulator(Class<? extends AbstractSimulator> abstractSimulator) {
try {
abstractSimulators.add(abstractSimulator.getConstructor(SystemSetup.class));
} catch (Exception e) {
System.out.println("Missing constructor for abstract simulator!");
}
return this;
public TestEnvironment() {
}
public TestEnvironment registerTestPair(Class<? extends AbstractTest> abstractTest,
Class<? extends AbstractSimulator> abstractSimulator) {
try {
abstractTests.add(abstractTest.getConstructor(SystemSetup.class));
} catch (Exception e) {
System.out.println("Missing constructor for abstract test!");
}
try {
abstractSimulators.add(abstractSimulator.getConstructor(SystemSetup.class));
} catch (Exception e) {
System.out.println("Missing constructor for abstract simulator!");
public <T extends Task> Set<ResultCollector<AbstractTest<T>>> registerTests(
List<AbstractTest<T>> tests) {
Set<ResultCollector<AbstractTest<T>>> testSet = new HashSet<>();
for (AbstractTest<T> t : tests) {
testSet.add(new ResultCollector<AbstractTest<T>>(t.getPriorityManager(), t));
}
return this;
return testSet;
}
public void runExperiments() {
Set<ResultCollector<AbstractTest>> abstractTestInstances = new HashSet<>();
Set<ResultCollector<AbstractSimulator>> abstractSimulatorInstances = new HashSet<>();
for (PriorityManager pm : schedulingAlgorithms) {
for (Constructor<? extends AbstractTest> c : abstractTests) {
try {
if (pm.hasTest(c.getDeclaringClass())) {
abstractTestInstances.add(new ResultCollector<AbstractTest>(pm,
c.newInstance(this.systemSetup)));
}
} catch (Exception e) {
System.out.println("Could not instantiate object of AbstractTest!");
throw new RuntimeException("Could not instantiate object of AbstractTest!");
}
}
for (Constructor<? extends AbstractSimulator> c : abstractSimulators) {
try {
if (pm.hasSimulator(c.getDeclaringClass())) {
abstractSimulatorInstances.add(new ResultCollector<AbstractSimulator>(pm,
c.newInstance(this.systemSetup)));
}
} catch (Exception e) {
System.out.println("Could not instantiate object of AbstractSimulator!");
throw new RuntimeException(
"Could not instantiate object of AbstractSimulator!");
}
}
}
public void runExperiments(SynchronousTaskBuilder builder,
Set<ResultCollector<AbstractTest<SynchronousTask>>> abstractTestInstances,
long numberOfProcessors, long numberOfTaskSets) {
long checkedTasksets = 0;
System.out.print(Math.round((double) checkedTasksets / numberOfTaskSets * 100) + "% of "
+ numberOfTaskSets + " tasksets tested!\r");
while (checkedTasksets < numberOfTaskSets) {
builder.rebuild(this.systemSetup);
Set<SynchronousTask> tasks = builder.generateTaskSet();
double utilization = this.systemSetup.getUtilization();
double utilization = tasks.stream().mapToDouble(SynchronousTask::getUtilization).sum();
while (utilization <= this.systemSetup.getNumberOfProcessors()
&& checkedTasksets < numberOfTaskSets) {
while (utilization <= numberOfProcessors && checkedTasksets < numberOfTaskSets) {
checkedTasksets++;
if (checkedTasksets % 10 == 0) {
......@@ -121,36 +53,63 @@ public class TestEnvironment {
+ "% of " + numberOfTaskSets + " tasksets tested!\r");
}
for (ResultCollector<AbstractTest> testInstance : abstractTestInstances) {
for (ResultCollector<AbstractTest<SynchronousTask>> testInstance : abstractTestInstances) {
PriorityManager priorityManager = testInstance.getPriorityManager();
AbstractTest abstractTest = testInstance.getAbstractValue();
AbstractTest<SynchronousTask> abstractTest = testInstance.getAbstractValue();
SortedTaskSet<SynchronousTask> sortedTaskSet =
new SortedTaskSet<>(priorityManager);
sortedTaskSet.addAll(tasks);
SchedulingInfo schedulingInfo =
abstractTest.runSchedulabilityCheck(priorityManager);
abstractTest.runSchedulabilityCheck(sortedTaskSet);
testInstance.addResult(schedulingInfo);
}
for (ResultCollector<AbstractSimulator> simulatorInstance : abstractSimulatorInstances) {
PriorityManager priorityManager = simulatorInstance.getPriorityManager();
AbstractSimulator abstractSimulator = simulatorInstance.getAbstractValue();
builder.addTask(tasks);
SchedulingInfo schedulingInfo =
abstractSimulator.runSimulation(priorityManager);
simulatorInstance.addResult(schedulingInfo);
}
utilization = tasks.stream().mapToDouble(SynchronousTask::getUtilization).sum();
}
}
System.out.println("");
ResultLogger resultLogger = new ResultLogger(numberOfProcessors);
builder.addTask(systemSetup);
resultLogger.logTests(abstractTestInstances);
}
public void runExperiments(DagTaskBuilder builder,
Set<ResultCollector<AbstractTest<DagTask>>> abstractTestInstances,
long numberOfProcessors, long numberOfTaskSetsPerUtil) {
long checkedTasksets = 0;
long numberOfTaskSets = numberOfProcessors * 4 * numberOfTaskSetsPerUtil;
utilization = this.systemSetup.getUtilization();
for (double util = 1; util <= numberOfProcessors; util += 0.25) {
for (int i = 0; i < numberOfTaskSetsPerUtil; ++i) {
Set<DagTask> taskSet = builder.generateTaskSet(util);
System.out.print(Math.round((double) checkedTasksets / numberOfTaskSets * 100)
+ "% of " + numberOfTaskSets + " tasksets tested!\r");
for (ResultCollector<AbstractTest<DagTask>> testResultCollector : abstractTestInstances) {
AbstractTest<DagTask> testInstance = testResultCollector.getAbstractValue();
PriorityManager priorityManager = testResultCollector.getPriorityManager();
SortedTaskSet<DagTask> sortedTaskSet = new SortedTaskSet<>(priorityManager);
sortedTaskSet.addAll(taskSet);
SchedulingInfo schedulingInfo =
testInstance.runSchedulabilityCheck(sortedTaskSet);
testResultCollector.addResult(schedulingInfo);
}
checkedTasksets++;
}
}
System.out.println("");
ResultLogger resultLogger = new ResultLogger(systemSetup.getNumberOfProcessors());
ResultLogger resultLogger = new ResultLogger(numberOfProcessors);
resultLogger.logTests(abstractTestInstances);
resultLogger.logSimulations(abstractSimulatorInstances);
}
}
package mvd.jester.model;
import java.util.LinkedHashSet;
import java.util.Set;
import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
import org.jgrapht.graph.DefaultEdge;
public class DagTask implements Task {
private DirectedAcyclicGraph<Job, DefaultEdge> jobDag;
private final Set<Segment> workloadDistribution;
private final long workload;
private final long criticalPath;
private final long period;
private final long deadline;
private final long numberOfThreads;
public DagTask(DirectedAcyclicGraph<Job, DefaultEdge> jobDag, long period,
long numberOfThreads) {
this.jobDag = jobDag;
this.period = period;
this.deadline = period;
this.numberOfThreads = numberOfThreads;
this.workload = DagUtils.calculateWorkload(this.jobDag);
this.criticalPath = DagUtils.calculateCriticalPath(this.jobDag);
this.workloadDistribution =
DagUtils.calculateWorkloadDistribution(this.jobDag, this.criticalPath);
}
public double getUtilization() {
return (double) workload / period;
}
/**
* @return the deadline
*/
public long getDeadline() {
return deadline;
}
/**
* @return the jobDag
*/
public DirectedAcyclicGraph<Job, DefaultEdge> getJobDag() {
return jobDag;
}
/**
* @param jobDag the jobDag to set
*/
public void setJobDag(DirectedAcyclicGraph<Job, DefaultEdge> jobDag) {
this.jobDag = jobDag;
}
/**
* @return the period
*/
public long getPeriod() {
return period;
}
/**
* @return the workload
*/
public long getWorkload() {
return workload;
}
/**
* @return the criticalPath
*/
public long getCriticalPath() {
return criticalPath;
}
/**
* @return the workloadDistribution
*/
public Set<Segment> getWorkloadDistribution() {
return workloadDistribution;
}
@Override
public long getMaximumParallelism() {
long max = 0;
for (Segment s : workloadDistribution) {
if (max < s.getNumberOfJobs()) {
max = s.getNumberOfJobs();
}
}
return max;
}
@Override
public long getNumberOfThreads() {
return numberOfThreads;
}
public static class DagUtils {
public static long calculateWorkload(DirectedAcyclicGraph<Job, DefaultEdge> jobDag) {
long workload = 0;
for (Job job : jobDag) {
workload += job.getWcet();
}
return workload;
}
public static long calculateCriticalPath(DirectedAcyclicGraph<Job, DefaultEdge> jobDag) {
long criticalPath = 0;
for (Job job : jobDag) {
Set<DefaultEdge> edges = jobDag.incomingEdgesOf(job);
long longestRelativeCompletionTime = 0;
for (DefaultEdge e : edges) {
Job source = jobDag.getEdgeSource(e);
longestRelativeCompletionTime =
longestRelativeCompletionTime >= source.getRelativeCompletionTime()
? longestRelativeCompletionTime
: source.getRelativeCompletionTime();
}
job.setRelativeCompletionTime(longestRelativeCompletionTime + job.getWcet());
criticalPath = job.getRelativeCompletionTime();
}
return criticalPath;
}
public static LinkedHashSet<Segment> calculateWorkloadDistribution(
DirectedAcyclicGraph<Job, DefaultEdge> jobDag, long criticalPath) {
LinkedHashSet<Segment> segments = new LinkedHashSet<>();
long segmentDuration = 0;
long segmentHeight = 1;
for (long t = 0; t < criticalPath; ++t) {
long currentHeight = 0;
for (Job j : jobDag) {
if (t >= j.getRelativeCompletionTime() - j.getWcet()
&& t < j.getRelativeCompletionTime()) {
currentHeight++;
}
}
if (currentHeight == segmentHeight) {
segmentDuration++;
} else {
segments.add(new Segment(segmentDuration, segmentHeight));
segmentDuration = 1;
segmentHeight = currentHeight;
}
}
segments.add(new Segment(segmentDuration, segmentHeight));
return segments;
}
public static void createNFJGraph(DirectedAcyclicGraph<Job, DefaultEdge> jobDag) {
Set<Job> joinNodes = new LinkedHashSet<>();
Set<Job> forkNodes = new LinkedHashSet<>();
for (Job j : jobDag) {
if (jobDag.inDegreeOf(j) > 1) {
joinNodes.add(j);
}
if (jobDag.outDegreeOf(j) > 1) {
forkNodes.add(j);
}
}
for (Job j : joinNodes) {
for (Job f : forkNodes) {
Set<DefaultEdge> edges = jobDag.getAllEdges(f, j);
// jobDag.
}
}
}
}
}
package mvd.jester.model;
public class Job {
private final long wcet;
private long relativeCompletionTime;
public Job(long wcet) {
this.wcet = wcet;
this.relativeCompletionTime = wcet;
}
public long getWcet() {
return wcet;
}
/**
* @return the relativeCompletionTime
*/
public long getRelativeCompletionTime() {
return relativeCompletionTime;
}
/**
* @param relativeCompletionTime the relativeCompletionTime to set
*/
public void setRelativeCompletionTime(long relativeCompletionTime) {
this.relativeCompletionTime = relativeCompletionTime;
}
}
package mvd.jester.model;
import com.google.common.math.LongMath;
// import com.google.common.math.LongMath;
public class Segment {
private final long jobWcet;
private final long numberOfJobs;
private final long taskletWcet;
private final long numberOfTasklets;
public Segment(long jobWcet, long numberOfJobs) {
this.jobWcet = jobWcet;
this.numberOfJobs = numberOfJobs;
if (numberOfJobs == 1) {
this.taskletWcet = this.jobWcet;
this.numberOfTasklets = this.numberOfJobs;
} else if (this.numberOfJobs > this.jobWcet) {
this.taskletWcet = LongMath.gcd(jobWcet, numberOfJobs);
this.numberOfTasklets = this.jobWcet * this.numberOfJobs / this.taskletWcet;
} else {
this.taskletWcet = numberOfJobs;
this.numberOfTasklets = jobWcet;
}
}
/**
* @return the numberOfJobs
*/
......@@ -42,17 +25,4 @@ public class Segment {
return jobWcet;
}
/**
* @return the numberOfTasklets
*/
public long getNumberOfTasklets() {
return numberOfTasklets;
}
/**
* @return the taskletWcet
*/
public long getTaskletWcet() {
return taskletWcet;
}
}
......@@ -13,7 +13,7 @@ import mvd.jester.priority.RateMonotonic;
/**
* SortedTaskSet
*/
public class SortedTaskSet extends TreeSet<Task> {
public class SortedTaskSet<T extends Task> extends TreeSet<T> {
private static final long serialVersionUID = 4808544133562675597L;
......@@ -21,16 +21,28 @@ public class SortedTaskSet extends TreeSet<Task> {
super((t1, t2) -> priorityMananger.compare(t1, t2));
}
public static class Deserializer implements JsonDeserializer<SortedTaskSet> {
public double getUtilization() {
return super.stream().mapToDouble(T::getUtilization).sum();
}
public double getParallelTaskRatio() {
long parallelTasks = super.stream().filter(t -> t.getMaximumParallelism() > 1).count();
return (double) parallelTasks / super.size();
}
public static class Deserializer<T extends Task> implements JsonDeserializer<SortedTaskSet<T>> {
@Override
public SortedTaskSet deserialize(JsonElement json, Type typeOfT,
public SortedTaskSet<T> deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
SortedTaskSet taskSet = new SortedTaskSet(new RateMonotonic());
SortedTaskSet<T> taskSet = new SortedTaskSet<>(new RateMonotonic());
if (json.isJsonArray()) {
JsonArray array = json.getAsJsonArray();
array.forEach(e -> {
taskSet.add(context.deserialize(e, Task.class));
taskSet.add(context.deserialize(e, SynchronousTask.class));
});
}
return taskSet;
......
package mvd.jester.model;
import java.util.Set;
/**
* Task
*/
public class SynchronousTask implements Task {
private final long deadline;
private final long period;
private final Set<Segment> segments;
private final long workload;
private final long criticalPath;
private final long numberOfThreads;
public SynchronousTask(long period, long deadline, long numberOfThreads,
Set<Segment> segments) {
this.deadline = deadline;
this.period = period;
this.numberOfThreads = numberOfThreads;
this.segments = segments;
this.workload = SynchronousUtils.calculateWorkload(segments);
this.criticalPath = SynchronousUtils.calculateCriticalPath(segments);
}
public SynchronousTask(Set<Segment> segments, long period, long numberOfThreads) {
this(period, period, numberOfThreads, segments);
}
public double getUtilization() {
return (double) workload / period;
}
/**
* @return the deadline
*/
public long getDeadline() {
return deadline;
}
/**
* @return the period
*/
public long getPeriod() {
return period;
}
/**
* @return the segments
*/
public Set<Segment> getWorkloadDistribution() {
return segments;
}
/**
* @return the maximumWcet
*/
public long getWorkload() {
return workload;
}
/**
* @return the criticalPath
*/
public long getCriticalPath() {
return criticalPath;
}
@Override
public long getMaximumParallelism() {
long max = 0;
for (Segment s : segments) {
if (max < s.getNumberOfJobs()) {
max = s.getNumberOfJobs();
}
}
return max;
}
@Override
public long getNumberOfThreads() {
return numberOfThreads;
}
public static class SynchronousUtils {
public static long calculateWorkload(Set<Segment> segments) {
long workload = 0;
for (Segment s : segments) {
workload += s.getJobWcet() * s.getNumberOfJobs();
}
return workload;
}
public static long calculateCriticalPath(Set<Segment> segments) {
long criticalPath = 0;
for (Segment s : segments) {
criticalPath += s.getJobWcet();
}
return criticalPath;
}
}
}
......@@ -2,72 +2,21 @@ package mvd.jester.model;
import java.util.Set;
/**
* Task
*/
public class Task {
public interface Task {
public long getWorkload();
private final long deadline;
private final long period;
private final Set<Segment> segments;
private final long maximumWcet;
private final long maximumParallelism;
public long getCriticalPath();
public Task(long period, long deadline, Set<Segment> segments) {
this.deadline = deadline;
this.period = period;
this.segments = segments;
public double getUtilization();
long maxWcet = 0;
long maxParallelism = 0;
for (Segment s : segments) {
maxWcet += s.getJobWcet() * s.getNumberOfJobs();
if (maxParallelism < s.getNumberOfJobs()) {