From 037c0600d0fe3ec699f239c41ab0e60a458484d7 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Tue, 18 Oct 2022 11:35:56 +0200 Subject: perf(sim/compute): Optimize workload implementation of SimTrace This change updates the workload implementation of SimTrace by introducing multiple implementations of the FlowStageLogic interface, which is selected dynamically when the workload starts. This change helps eliminate the unecessary division (and memory fetch) when running a workload with just a single CPU. --- .../simulator/compute/workload/SimTrace.java | 155 ++++++++++++++++++--- 1 file changed, 137 insertions(+), 18 deletions(-) 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 0bd2b2eb..12a567ff 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 @@ -203,12 +203,8 @@ public final class SimTrace { /** * Implementation of {@link SimWorkload} that executes a trace. */ - private static class Workload implements SimWorkload, FlowStageLogic { - private SimMachineContext ctx; - private FlowStage stage; - private OutPort[] outputs; - private int index; - private int coreCount; + private static class Workload implements SimWorkload { + private WorkloadStageLogic logic; private final long offset; private final double[] usageCol; @@ -226,7 +222,137 @@ public final class SimTrace { @Override public void onStart(SimMachineContext ctx) { + final WorkloadStageLogic logic; + if (ctx.getCpus().size() == 1) { + logic = new SingleWorkloadLogic(ctx, offset, usageCol, deadlineCol, size); + } else { + logic = new MultiWorkloadLogic(ctx, offset, usageCol, deadlineCol, coresCol, size); + } + this.logic = logic; + } + + @Override + public void onStop(SimMachineContext ctx) { + final WorkloadStageLogic logic = this.logic; + + if (logic != null) { + this.logic = null; + logic.getStage().close(); + } + } + } + + /** + * Interface to represent the {@link FlowStage} that simulates the trace workload. + */ + private interface WorkloadStageLogic extends FlowStageLogic { + /** + * Return the {@link FlowStage} belonging to this instance. + */ + FlowStage getStage(); + } + + /** + * Implementation of {@link FlowStageLogic} for just a single CPU resource. + */ + private static class SingleWorkloadLogic implements WorkloadStageLogic { + private final FlowStage stage; + private final OutPort output; + private int index; + + private final long offset; + private final double[] usageCol; + private final long[] deadlineCol; + private final int size; + + private final SimMachineContext ctx; + + private SingleWorkloadLogic( + SimMachineContext ctx, long offset, double[] usageCol, long[] deadlineCol, int size) { this.ctx = ctx; + this.offset = offset; + this.usageCol = usageCol; + this.deadlineCol = deadlineCol; + this.size = size; + + final FlowGraph graph = ctx.getGraph(); + final List cpus = ctx.getCpus(); + + stage = graph.newStage(this); + + final SimProcessingUnit cpu = cpus.get(0); + final OutPort output = stage.getOutlet("cpu"); + this.output = output; + + graph.connect(output, cpu.getInput()); + } + + @Override + public long onUpdate(FlowStage ctx, long now) { + int size = this.size; + long offset = this.offset; + long nowOffset = now - offset; + + int index = this.index; + + long[] deadlines = deadlineCol; + long deadline = deadlines[index]; + + while (deadline <= nowOffset) { + if (++index >= size) { + return doStop(ctx); + } + deadline = deadlines[index]; + } + + this.index = index; + this.output.push((float) usageCol[index]); + return deadline + offset; + } + + @Override + public FlowStage getStage() { + return stage; + } + + /** + * Helper method to stop the execution of the workload. + */ + private long doStop(FlowStage ctx) { + final SimMachineContext machineContext = this.ctx; + if (machineContext != null) { + machineContext.shutdown(); + } + ctx.close(); + return Long.MAX_VALUE; + } + } + + /** + * Implementation of {@link FlowStageLogic} for multiple CPUs. + */ + private static class MultiWorkloadLogic implements WorkloadStageLogic { + private final FlowStage stage; + private final OutPort[] outputs; + private int index; + private final int coreCount; + + private final long offset; + private final double[] usageCol; + private final long[] deadlineCol; + private final int[] coresCol; + private final int size; + + private final SimMachineContext ctx; + + private MultiWorkloadLogic( + SimMachineContext ctx, long offset, double[] usageCol, long[] deadlineCol, int[] coresCol, int size) { + this.ctx = ctx; + this.offset = offset; + this.usageCol = usageCol; + this.deadlineCol = deadlineCol; + this.coresCol = coresCol; + this.size = size; final FlowGraph graph = ctx.getGraph(); final List cpus = ctx.getCpus(); @@ -246,18 +372,6 @@ public final class SimTrace { } } - @Override - public void onStop(SimMachineContext ctx) { - this.ctx = null; - - final FlowStage stage = this.stage; - - if (stage != null) { - this.stage = null; - stage.close(); - } - } - @Override public long onUpdate(FlowStage ctx, long now) { int size = this.size; @@ -299,5 +413,10 @@ public final class SimTrace { return deadline + offset; } + + @Override + public FlowStage getStage() { + return stage; + } } } -- cgit v1.2.3