From 3f05c61faeb94a2f1c920d87a6ca8bde34d551e0 Mon Sep 17 00:00:00 2001 From: Dante Niewenhuis Date: Thu, 5 Sep 2024 15:17:58 +0200 Subject: Sim trace update (#249) * Started on reimplementing the SimTrace implementation * updated trace format. Fragments now do not have a deadline, but a duration. The Fragments are executed in order. --- .../simulator/compute/workload/SimTrace.java | 99 ++++++++++++++++------ .../compute/workload/SimTraceFragment.java | 4 +- .../org/opendc/simulator/compute/SimMachineTest.kt | 6 +- 3 files changed, 76 insertions(+), 33 deletions(-) (limited to 'opendc-simulator/opendc-simulator-compute/src') diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTrace.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTrace.java index 1afb12aa..39ce7f61 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTrace.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTrace.java @@ -82,7 +82,7 @@ public final class SimTrace { final Builder builder = builder(); for (SimTraceFragment fragment : fragments) { - builder.add(fragment.deadline(), fragment.cpuUsage(), fragment.coreCount()); + builder.add(fragment.duration(), fragment.cpuUsage(), fragment.coreCount()); } return builder.build(); @@ -97,7 +97,7 @@ public final class SimTrace { final Builder builder = builder(); for (SimTraceFragment fragment : fragments) { - builder.add(fragment.deadline(), fragment.cpuUsage(), fragment.coreCount()); + builder.add(fragment.duration(), fragment.cpuUsage(), fragment.coreCount()); } return builder.build(); @@ -121,16 +121,16 @@ public final class SimTrace { /** * Add a fragment to the trace. * - * @param deadline The timestamp at which the fragment ends (in epoch millis). + * @param duration The timestamp at which the fragment ends (in epoch millis). * @param usage The CPU usage at this fragment. * @param cores The number of cores used during this fragment. */ - public void add(long deadline, double usage, int cores) { + public void add(long duration, double usage, int cores) { if (isBuilt) { recreate(); } - fragments.add(new SimTraceFragment(deadline, usage, cores)); + fragments.add(new SimTraceFragment(duration, usage, cores)); } /** @@ -178,7 +178,7 @@ public final class SimTrace { @Override public void setOffset(long now) { - this.offset = now - this.start; + this.offset = now; } @Override @@ -192,8 +192,6 @@ public final class SimTrace { this.logic = logic; } - public void injectFragment(long duration, double usage, int coreCount) {} - @Override public void onStop(SimMachineContext ctx) { final WorkloadStageLogic logic = this.logic; @@ -243,17 +241,16 @@ public final class SimTrace { private final OutPort output; private int index = 0; - private final long workloadOffset; private final SimMachineContext ctx; private final Iterator fragments; private SimTraceFragment currentFragment; + private long startOffFragment; private SingleWorkloadLogic(SimMachineContext ctx, long offset, Iterator fragments) { this.ctx = ctx; - this.workloadOffset = offset; + this.fragments = fragments; - this.currentFragment = this.fragments.next(); final FlowGraph graph = ctx.getGraph(); final List cpus = ctx.getCpus(); @@ -265,29 +262,46 @@ public final class SimTrace { this.output = output; graph.connect(output, cpu.getInput()); + + // Start the first Fragment + this.currentFragment = this.fragments.next(); + this.output.push((float) currentFragment.cpuUsage()); + this.startOffFragment = offset; } @Override public long onUpdate(FlowStage ctx, long now) { + long passedTime = now - this.startOffFragment; + long duration = this.currentFragment.duration(); - // Shift the current time to align with the starting time of the workload - long nowOffset = now - this.workloadOffset; - - long deadline = currentFragment.deadline(); + // The current Fragment has not yet been finished, continue + if (passedTime < duration) { + return now + (duration - passedTime); + } - // Loop through the deadlines until the next deadline is reached. - while (deadline <= nowOffset) { + // Loop through fragments until the passed time is filled. + // We need a while loop to account for skipping of fragments. + while (passedTime >= duration) { if (!this.fragments.hasNext()) { return doStop(ctx); } + passedTime = passedTime - duration; + + // get next Fragment this.index++; currentFragment = this.fragments.next(); - deadline = currentFragment.deadline(); + duration = currentFragment.duration(); } + // start new fragment + this.startOffFragment = now - passedTime; + + // Change the cpu Usage to the new Fragment this.output.push((float) currentFragment.cpuUsage()); - return deadline + this.workloadOffset; + + // Return the time when the current fragment will complete + return this.startOffFragment + duration; } @Override @@ -322,18 +336,16 @@ public final class SimTrace { private int index = 0; private final int coreCount; - private final long offset; private final Iterator fragments; private SimTraceFragment currentFragment; + private long startOffFragment; private final SimMachineContext ctx; private MultiWorkloadLogic(SimMachineContext ctx, long offset, Iterator fragments) { this.ctx = ctx; - this.offset = offset; this.fragments = fragments; - this.currentFragment = this.fragments.next(); final FlowGraph graph = ctx.getGraph(); final List cpus = ctx.getCpus(); @@ -351,16 +363,40 @@ public final class SimTrace { graph.connect(output, cpu.getInput()); outputs[i] = output; } + + this.currentFragment = this.fragments.next(); + + int cores = Math.min(this.coreCount, currentFragment.coreCount()); + float usage = (float) currentFragment.cpuUsage() / cores; + + // Push the usage to all active cores + for (int i = 0; i < cores; i++) { + outputs[i].push(usage); + } + + // Push a usage of 0 to all non-active cores + for (int i = cores; i < outputs.length; i++) { + outputs[i].push(0.f); + } + + this.startOffFragment = offset; } @Override public long onUpdate(FlowStage ctx, long now) { - long offset = this.offset; - long nowOffset = now - offset; + long passedTime = now - this.startOffFragment; + long duration = this.currentFragment.duration(); - long deadline = currentFragment.deadline(); + // The current Fragment has not yet been finished, continue + if (passedTime < duration) { + return now + (duration - passedTime); + } + + // Loop through fragments until the passed time is filled. + // We need a while loop to account for skipping of fragments. + while (passedTime >= duration) { - while (deadline <= nowOffset) { + // Stop running if (!this.fragments.hasNext()) { final SimMachineContext machineContext = this.ctx; if (machineContext != null) { @@ -370,11 +406,17 @@ public final class SimTrace { return Long.MAX_VALUE; } + passedTime = passedTime - duration; + + // get next Fragment this.index++; currentFragment = this.fragments.next(); - deadline = currentFragment.deadline(); + duration = currentFragment.duration(); } + // start the new fragment + this.startOffFragment = now - passedTime; + int cores = Math.min(this.coreCount, currentFragment.coreCount()); float usage = (float) currentFragment.cpuUsage() / cores; @@ -390,7 +432,8 @@ public final class SimTrace { outputs[i].push(0.f); } - return deadline + offset; + // Return the time when the current fragment will complete + return now + (duration - passedTime); } @Override diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTraceFragment.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTraceFragment.java index a529ae1d..374e9732 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTraceFragment.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTraceFragment.java @@ -22,9 +22,9 @@ package org.opendc.simulator.compute.workload; -public record SimTraceFragment(long deadline, double cpuUsage, int coreCount) { +public record SimTraceFragment(long duration, double cpuUsage, int coreCount) { public SimTraceFragment(long start, long duration, double cpuUsage, int coreCount) { - this(start + duration, cpuUsage, coreCount); + this(duration, cpuUsage, coreCount); } } diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt index fc242e8c..8bb856c5 100644 --- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt +++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt @@ -95,9 +95,9 @@ class SimMachineTest { val random = ThreadLocalRandom.current() val builder = SimTrace.builder() repeat(1000000) { - val timestamp = it.toLong() * 1000 - val deadline = timestamp + 1000 - builder.add(deadline, random.nextDouble(0.0, 4500.0), 1) +// val timestamp = it.toLong() * 1000 +// val deadline = timestamp + 1000 + builder.add(1000, random.nextDouble(0.0, 4500.0), 1) } val trace = builder.build() -- cgit v1.2.3