Commit 59c46e2a by Michael Schmid

first commit, works good, but refactoring

parents
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="target/generated-sources/annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
/.vscode
/.settings
/target
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>jester</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mvd.jester</groupId>
<artifactId>jester</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>jester</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.21.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.0-jre</version>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
package mvd.jester;
import mvd.jester.model.Task;
import mvd.jester.model.SystemSetup;
import mvd.jester.tests.MaiaBertogna;
import mvd.jester.tests.SchmidMottok;
import mvd.jester.tests.TestEnvironment;
/**
* Hello world!
*
*/
public class App {
public static void main(String[] args) {
TestEnvironment te = new TestEnvironment(4000, 4);
te.registerTestInterface(SchmidMottok.class);
te.registerTestInterface(MaiaBertogna.class);
te.runTests();
}
}
package mvd.jester.model;
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 {
this.taskletWcet = LongMath.gcd(jobWcet, numberOfJobs);
this.numberOfTasklets = this.jobWcet * this.numberOfJobs / this.taskletWcet;
}
}
/**
* @return the numberOfJobs
*/
public long getNumberOfJobs() {
return numberOfJobs;
}
/**
* @return the jobWcet
*/
public long getJobWcet() {
return jobWcet;
}
/**
* @return the numberOfTasklets
*/
public long getNumberOfTasklets() {
return numberOfTasklets;
}
/**
* @return the taskletWcet
*/
public long getTaskletWcet() {
return taskletWcet;
}
}
package mvd.jester.model;
import java.util.TreeSet;
import mvd.jester.priority.PriorityManager;
/**
* SortedTaskSet
*/
public class SortedTaskSet extends TreeSet<Task> {
private static final long serialVersionUID = 4808544133562675597L;
public SortedTaskSet(PriorityManager priorityMananger) {
super((t1, t2) -> priorityMananger.compare(t1, t2));
}
}
package mvd.jester.model;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import mvd.jester.priority.PriorityManager;
import mvd.jester.priority.RateMonotonic;
/**
* TaskSet
*/
public class SystemSetup {
private SortedTaskSet tasks;
private final long numberOfProcessors;
public SystemSetup(SortedTaskSet tasks, long numberOfProcessors) {
this.tasks = tasks;
this.numberOfProcessors = numberOfProcessors;
}
/**
* @return the tasks
*/
public SortedTaskSet getTasks() {
return tasks;
}
public void setSortedTaskSet(SortedTaskSet tasks) {
this.tasks = tasks;
}
/**
* @return the numberOfProcessors
*/
public long getNumberOfProcessors() {
return numberOfProcessors;
}
public double getUtilization() {
double utilization = 0;
for (Task t : tasks) {
utilization += (double) t.getMaximumWcet() / t.getPeriod();
}
return utilization;
}
public static class Generator {
private long numberOfProcessors = 4;
private long minPeriod = 100;
private long maxPeriod = 1000;
private long minNumberOfSegments = 3;
private long maxNumberOfSegments = 7;
private long minNumberOfJobs = 2;
private long maxNumberOfJobs = 3 * numberOfProcessors / 2;
private long minWcet = 1;
private long ratio = randomTaskRatio();
private PriorityManager priorityManager = new RateMonotonic();
public Generator() {
}
private long randomTaskPeriod() {
return ThreadLocalRandom.current().nextLong(minPeriod, maxPeriod);
}
private long randomTaskRatio() {
return ThreadLocalRandom.current().nextLong(0, 100);
}
private long randomNumberOfSegments() {
return ThreadLocalRandom.current().nextLong(minNumberOfSegments, maxNumberOfSegments);
}
private long randomNumberOfJobs() {
return ThreadLocalRandom.current().nextLong(minNumberOfJobs, maxNumberOfJobs);
}
private long randomWcet(long period, long numberOfSegments) {
long maxWcet = period / numberOfSegments;
return ThreadLocalRandom.current().nextLong(minWcet, maxWcet);
}
private Task generateTask() {
boolean serial = randomTaskRatio() > this.ratio;
long period = randomTaskPeriod();
long numberOfSegments = 1;
Set<Segment> segments = new LinkedHashSet<Segment>();
if (!serial) {
numberOfSegments = randomNumberOfSegments();
} else {
numberOfSegments = 1;
}
for (int i = 0; i < numberOfSegments; ++i) {
serial = i % 2 == 0;
long wcet = randomWcet(period, numberOfSegments);
long numberOfJobs = serial ? 1 : randomNumberOfJobs();
segments.add(new Segment(wcet, numberOfJobs));
}
return new Task(period, segments);
}
private SortedTaskSet generateTaskSet() {
SortedTaskSet taskSet = new SortedTaskSet(priorityManager);
for (int i = 0; i < 4; ++i) {
Task task = generateTask();
taskSet.add(task);
}
return taskSet;
}
public SystemSetup build() {
this.ratio = randomTaskRatio();
SortedTaskSet taskSet = generateTaskSet();
return new SystemSetup(taskSet, numberOfProcessors);
}
public void addTask(SystemSetup taskSet) {
taskSet.tasks.add(generateTask());
}
/**
* @param numberOfProcessors the numberOfProcessors to set
*/
public void setNumberOfProcessors(long numberOfProcessors) {
this.numberOfProcessors = numberOfProcessors;
}
public Generator setNumberOfSegments(long minNumberOfSegments, long maxNumberOfSegments) {
this.minNumberOfSegments = minNumberOfSegments;
this.maxNumberOfSegments = maxNumberOfSegments;
return this;
}
public Generator setPeriods(long minPeriod, long maxPeriod) {
this.minPeriod = minPeriod;
this.maxPeriod = maxPeriod;
return this;
}
public Generator setPriorityManager(PriorityManager priorityManager) {
this.priorityManager = priorityManager;
return this;
}
/**
* @param maxNumberOfJobs the maxNumberOfJobs to set
*/
public Generator setNumberOfJobs(long minNumberOfJobs, long maxNumberOfJobs) {
this.minNumberOfJobs = minNumberOfJobs;
this.maxNumberOfJobs = maxNumberOfJobs;
return this;
}
}
}
package mvd.jester.model;
import java.util.Set;
/**
* Task
*/
public class Task {
private final long deadline;
private final long period;
private final Set<Segment> segments;
private final long maximumWcet;
private final long maximumParallelism;
public Task(long period, long deadline, Set<Segment> segments) {
this.deadline = deadline;
this.period = period;
this.segments = segments;
long maxWcet = 0;
long maxParallelism = 0;
for (Segment s : segments) {
maxWcet += s.getJobWcet() * s.getNumberOfJobs();
if (maxParallelism < s.getNumberOfJobs()) {
maxParallelism = s.getNumberOfJobs();
}
}
this.maximumParallelism = maxParallelism;
this.maximumWcet = maxWcet;
}
public Task(long period, Set<Segment> segments) {
this(period, period, segments);
}
/**
* @return the deadline
*/
public long getDeadline() {
return deadline;
}
/**
* @return the period
*/
public long getPeriod() {
return period;
}
/**
* @return the segments
*/
public Set<Segment> getSegments() {
return segments;
}
/**
* @return the maximumWcet
*/
public long getMaximumWcet() {
return maximumWcet;
}
/**
* @return the maximumParallelism
*/
public long getMaximumParallelism() {
return maximumParallelism;
}
}
package mvd.jester.priority;
import java.util.Comparator;
import mvd.jester.model.Task;
/**
* PriorityManager
*/
public interface PriorityManager extends Comparator<Task> {
}
package mvd.jester.priority;
import mvd.jester.model.Task;
public class RateMonotonic implements PriorityManager {
/**
* Compare the priority of two tasks according to the Rate Monotonic policy
*
* @param t1 The first task
* @param t2 The second task
* @return 0 if both tasks have the same priority, positive number if the first task has a
* higher priority, negative number if the second task has a higher priority
*/
@Override
public int compare(Task t1, Task t2) {
return Long.compare(t1.getPeriod(), t2.getPeriod());
}
}
package mvd.jester.tests;
import java.util.HashMap;
import java.util.Map;
import mvd.jester.model.Task;
/**
* AbstractTest
*/
public abstract class AbstractTest implements TestInterface {
protected Map<Task, Long> responseTimes;
public AbstractTest() {
this.responseTimes = new HashMap<Task, Long>();
}
}
package mvd.jester.tests;
import java.math.RoundingMode;
import java.util.Map.Entry;
import com.google.common.math.LongMath;
import mvd.jester.model.Segment;
import mvd.jester.model.Task;
import mvd.jester.model.SystemSetup;
/**
* MaiaBertogna
*/
public class MaiaBertogna extends AbstractTest {
private SystemSetup systemSetup;
public MaiaBertogna() {
}
@Override
public boolean runSchedulabilityCheck(SystemSetup systemSetup) {
responseTimes.clear();
this.systemSetup = systemSetup;
for (Task t : systemSetup.getTasks()) {
responseTimes.put(t, calculateResponseTime(t));
}
for (Entry<Task, Long> keyValuePair : responseTimes.entrySet()) {
if (keyValuePair.getKey().getDeadline() < keyValuePair.getValue().longValue()) {
return false;
}
}
return true;
}
@Override
public String getName() {
return "MaiaBertogna";
}
private long calculateResponseTime(Task task) {
long minimumWcet = getMinimumWcet(task);
long responseTime = minimumWcet;
long previousResponseTime = 0;
do {
previousResponseTime = responseTime;
long interference = 0;
for (Task t : systemSetup.getTasks()) {
if (t.getPeriod() < task.getPeriod()) {
long maxNumberOfJobsOfT = t.getMaximumParallelism();
for (int p = 0; p < maxNumberOfJobsOfT; ++p) {
interference += Math.min(getTaskInterference(t, responseTime, p + 1),
responseTime - minimumWcet + 1);
}
}
}
double taskInterference = (double) interference / systemSetup.getNumberOfProcessors();
long selfInterference = 0;
long maxNumberOfJobs = task.getMaximumParallelism();
for (int p = 0; p < maxNumberOfJobs; ++p) {
selfInterference +=
Math.min(getSelfInterference(task, p + 1), responseTime - minimumWcet + 1);
}
long totalInterference = (long) Math.floor(taskInterference + selfInterference);
responseTime = minimumWcet + totalInterference;
} while (previousResponseTime != responseTime);
return responseTime;
}
private long getSelfInterference(Task task, long parallelism) {
long interference = 0;
for (Segment s : task.getSegments()) {
if (s.getNumberOfJobs() >= parallelism + 1) {
s.getJobWcet();
}
}
return interference;
}
private long getTaskInterference(Task task, long interval, long parallelism) {
long responseTime = responseTimes.get(task);
long minWcet = getMinimumWcet(task);
long period = task.getPeriod();
long numberOfJobs =
(LongMath.divide(interval + responseTime - minWcet, period, RoundingMode.FLOOR)
+ 1);
long workload = 0;
for (Segment s : task.getSegments()) {
if (s.getNumberOfJobs() >= parallelism) {
workload += s.getJobWcet();
}
}
long interference = numberOfJobs * workload;
return interference;
}
private long getMinimumWcet(Task task) {
long minWcet = 0;
for (Segment s : task.getSegments()) {
minWcet += s.getJobWcet();
}
return minWcet;
}
}
package mvd.jester.tests;
import java.math.RoundingMode;
import java.util.Map.Entry;
import com.google.common.math.LongMath;
import mvd.jester.model.Segment;
import mvd.jester.model.Task;
import mvd.jester.model.SystemSetup;
/**
* SchmidMottok
*/
public class SchmidMottok extends AbstractTest {
private SystemSetup systemSetup;
public SchmidMottok() {
}
@Override
public boolean runSchedulabilityCheck(SystemSetup systemSetup) {
responseTimes.clear();
this.systemSetup = systemSetup;
for (Task t : systemSetup.getTasks()) {
responseTimes.put(t, calculateResponseTime(t));
}
for (Entry<Task, Long> taskResponsePair : responseTimes.entrySet()) {
if (taskResponsePair.getKey().getDeadline() < taskResponsePair.getValue().longValue()) {
return false;
}
}
return true;
}
@Override
public String getName() {
return "SchmidMottok";
}
private long calculateResponseTime(Task task) {
long minimumWcet = getMinimumWcet(task);
long responseTime = minimumWcet;
long previousResponseTime = 0;
do {
previousResponseTime = responseTime;
long interference = 0;
for (Task t : systemSetup.getTasks()) {
if (t.getPeriod() < task.getPeriod()) {
interference += Math.min(getTaskInterference(t, responseTime),
responseTime - minimumWcet + 1);
}
}
double taskInterference = (double) interference / 4;
double selfInterference = getSelfInterference(task);
long totalInterference = (long) Math.floor(taskInterference + selfInterference);
responseTime = minimumWcet + totalInterference;
} while (previousResponseTime != responseTime);
return responseTime;
}
private double getSelfInterference(Task task) {
double interference = 0;
for (Segment s : task.getSegments()) {
long processingUnits = s.getNumberOfJobs() > 4 ? 4 : s.getNumberOfJobs();
interference +=
(double) (s.getNumberOfTasklets() - 1) * s.getTaskletWcet() / processingUnits;
}
return interference;
}
private long getTaskInterference(Task task, long interval) {
long responseTime = responseTimes.get(task);
long minWcet = getMinimumWcet(task);
long period = task.getPeriod();
long interference =
(LongMath.divide(interval + responseTime - minWcet, period, RoundingMode.FLOOR) + 1)
* getMaximumWcet(task);
return interference;
}
private long getMinimumWcet(Task task) {
long minWcet = 0;
for (Segment s : task.getSegments()) {
minWcet += s.getTaskletWcet();
}
return minWcet;
}
private long getMaximumWcet(Task task) {
long maxWcet = 0;
for (Segment s : task.getSegments()) {
maxWcet += s.getTaskletWcet() * s.getNumberOfTasklets();
}
return maxWcet;
}
}
package mvd.jester.tests;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import mvd.jester.model.SortedTaskSet;
import mvd.jester.model.SystemSetup;
/**
* TestEnvironment
*/
public class TestEnvironment {
private final long numberOfTaskSets;
private final long numberOfProcessors;
private final Set<Class<? extends AbstractTest>> abstractTests;
public TestEnvironment(long numberOfTaskSets, long numberOfProcessors) {
this.numberOfTaskSets = numberOfTaskSets;
this.numberOfProcessors = numberOfProcessors;
abstractTests = new HashSet<>();
}
public TestEnvironment registerTestInterface(Class<? extends AbstractTest> abstractTest) {
abstractTests.add(abstractTest);
return this;
}
public void runTests() {
Map<AbstractTest, Long> testCases = new HashMap<>();
for (Class<? extends AbstractTest> t : abstractTests) {
try {
testCases.put(t.newInstance(), (long) 0);
} catch (Exception e) {
System.out.println("Ahhh SHIT!");
}
}
long checkedTasksets = 0;
while (checkedTasksets < 4000) {
SystemSetup.Generator generator = new SystemSetup.Generator();
SystemSetup systemSetup = generator.build();
double utilization = systemSetup.getUtilization();
while (utilization <= systemSetup.getNumberOfProcessors()
&& checkedTasksets < numberOfTaskSets) {
checkedTasksets++;
for (AbstractTest t : testCases.keySet()) {
if (t.runSchedulabilityCheck(systemSetup)) {
testCases.computeIfPresent(t, (k, v) -> v + 1);
}
}
generator.addTask(systemSetup);
utilization = systemSetup.getUtilization();
}
}
for (AbstractTest t : testCases.keySet()) {
System.out.println("Testcase " + t.getName() + " scheduled " + testCases.get(t) + " of "
+ numberOfTaskSets + " tasks!");
}
}
}
package mvd.jester.tests;
import mvd.jester.model.SystemSetup;
/**
* TestInterface
*/
public interface TestInterface {
public boolean runSchedulabilityCheck(SystemSetup systemSetup);
public String getName();
}
package mvd.jester.utils;
public class TimeUnit {
public static long Seconds(long seconds) {
return seconds*1_000_000_000;
}
public static long Seconds(double seconds) {
return Math.round(seconds*1_000_000_000);
}
public static long Milliseconds(long milliseconds) {
return milliseconds*1_000_000;
}
public static long Milliseconds(double milliseconds) {
return Math.round(milliseconds*1_000_000);
}
public static long Microseconds(long microseconds) {
return microseconds*1_000;
}
public static long Microseconds(double microseconds) {
return Math.round(microseconds*1_000);
}
public static long Nanoseconds(long nanoseconds) {
return nanoseconds;
}
public static long Nanoseconds(double nanoseconds) {
return Math.round(nanoseconds);
}
public static long RoundTo(long value, long round) {
return value / round * round;
}
}
package mvd.jester.model;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
public class TaskSetTest {
private static final int NUMBER_OF_SETS = 1000;
@Test
@DisplayName("Check if randomly generated task parameters lie within the specified ranges.")
public void testRandomTaskSetGeneration() {
for (int i = 0; i < NUMBER_OF_SETS; ++i) {
SystemSetup taskSet = new SystemSetup.Generator().build();
for (Task t : taskSet.getTasks()) {
assertTrue(t.getPeriod() >= 100);
assertTrue(t.getPeriod() <= 1000);
assertTrue(t.getDeadline() == t.getPeriod());
long maxJobWcet = t.getPeriod() / t.getSegments().size();
for (Segment s : t.getSegments()) {
assertTrue(s.getJobWcet() * s.getNumberOfJobs() == s.getTaskletWcet()
* s.getNumberOfTasklets());
assertTrue(s.getJobWcet() >= 1);
assertTrue(s.getJobWcet() <= maxJobWcet);
assertTrue(s.getNumberOfJobs() >= 1);
assertTrue(s.getNumberOfJobs() <= 6);
}
assertTrue(t.getSegments().size() >= 1);
assertTrue(t.getSegments().size() <= 5);
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment