diff options
| author | Dante Niewenhuis <d.niewenhuis@hotmail.com> | 2024-09-16 11:29:26 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-16 11:29:26 +0200 |
| commit | 4a010c6b9e033314a2624a0756dcdc7f17010d9d (patch) | |
| tree | 70dc26e98cf8421eb5db7f62cf63d4ea2399c505 /opendc-simulator/opendc-simulator-compute/src/main/java | |
| parent | 5047e4a25a0814f96852882f02c4017e1d5f81e7 (diff) | |
All simulation are now run with a single CPU and single MemoryUnit. multi CPUs are combined into one. This is for performance and explainability. (#255)
Diffstat (limited to 'opendc-simulator/opendc-simulator-compute/src/main/java')
16 files changed, 315 insertions, 537 deletions
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimAbstractMachine.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimAbstractMachine.java index af56f248..3a9e35c1 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimAbstractMachine.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimAbstractMachine.java @@ -23,7 +23,6 @@ package org.opendc.simulator.compute; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.function.Consumer; import org.opendc.simulator.compute.device.SimNetworkAdapter; @@ -43,7 +42,7 @@ import org.opendc.simulator.flow2.util.FlowTransforms; public abstract class SimAbstractMachine implements SimMachine { private final MachineModel model; - private Context activeContext; + private SimAbstractMachineContext activeContext; /** * Construct a {@link SimAbstractMachine} instance. @@ -66,40 +65,40 @@ public abstract class SimAbstractMachine implements SimMachine { throw new IllegalStateException("A machine cannot run multiple workloads concurrently"); } - final Context ctx = createContext(workload, new HashMap<>(meta), completion); + final SimAbstractMachineContext ctx = createContext(workload, new HashMap<>(meta), completion); ctx.start(); return ctx; } @Override public final void cancel() { - final Context context = activeContext; + final SimAbstractMachineContext context = activeContext; if (context != null) { context.shutdown(); } } /** - * Construct a new {@link Context} instance representing the active execution. + * Construct a new {@link SimAbstractMachineContext} instance representing the active execution. * * @param workload The workload to start on the machine. * @param meta The metadata to pass to the workload. * @param completion A block that is invoked when the workload completes carrying an exception if thrown by the workload. */ - protected abstract Context createContext( + protected abstract SimAbstractMachineContext createContext( SimWorkload workload, Map<String, Object> meta, Consumer<Exception> completion); /** - * Return the active {@link Context} instance (if any). + * Return the active {@link SimAbstractMachineContext} instance (if any). */ - protected Context getActiveContext() { + protected SimAbstractMachineContext getActiveContext() { return activeContext; } /** * The execution context in which the workload runs. */ - public abstract static class Context implements SimMachineContext { + public abstract static class SimAbstractMachineContext implements SimMachineContext { private final SimAbstractMachine machine; private final SimWorkload workload; private final Map<String, Object> meta; @@ -108,14 +107,14 @@ public abstract class SimAbstractMachine implements SimMachine { private SimWorkload snapshot; /** - * Construct a new {@link Context} instance. + * Construct a new {@link SimAbstractMachineContext} instance. * * @param machine The {@link SimAbstractMachine} to which the context belongs. * @param workload The {@link SimWorkload} to which the context belongs. * @param meta The metadata passed to the context. * @param completion A block that is invoked when the workload completes carrying an exception if thrown by the workload. */ - public Context( + public SimAbstractMachineContext( SimAbstractMachine machine, SimWorkload workload, Map<String, Object> meta, @@ -145,10 +144,8 @@ public abstract class SimAbstractMachine implements SimMachine { public void reset() { final FlowGraph graph = getMemory().getInput().getGraph(); - for (SimProcessingUnit cpu : getCpus()) { - final Inlet inlet = cpu.getInput(); - graph.disconnect(inlet); - } + final Inlet inlet = getCpu().getInput(); + graph.disconnect(inlet); graph.disconnect(getMemory().getInput()); @@ -225,16 +222,12 @@ public abstract class SimAbstractMachine implements SimMachine { */ public static final class Memory implements SimMemory { private final SimpleFlowSink sink; - private final List<MemoryUnit> models; + private final MemoryUnit memoryUnit; - public Memory(FlowGraph graph, List<MemoryUnit> models) { - long memorySize = 0; - for (MemoryUnit mem : models) { - memorySize += mem.getSize(); - } + public Memory(FlowGraph graph, MemoryUnit memoryUnit) { - this.sink = new SimpleFlowSink(graph, (float) memorySize); - this.models = models; + this.memoryUnit = memoryUnit; + this.sink = new SimpleFlowSink(graph, (float) memoryUnit.getSize()); } @Override @@ -243,8 +236,8 @@ public abstract class SimAbstractMachine implements SimMachine { } @Override - public List<MemoryUnit> getModels() { - return models; + public MemoryUnit getMemoryUnit() { + return memoryUnit; } @Override diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimBareMetalMachine.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimBareMetalMachine.java index 11356eb2..6acc605e 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimBareMetalMachine.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimBareMetalMachine.java @@ -28,8 +28,8 @@ import java.util.List; import java.util.Map; import java.util.function.Consumer; import org.opendc.simulator.compute.device.SimPeripheral; +import org.opendc.simulator.compute.model.Cpu; import org.opendc.simulator.compute.model.MachineModel; -import org.opendc.simulator.compute.model.ProcessingUnit; import org.opendc.simulator.compute.workload.SimWorkload; import org.opendc.simulator.flow2.FlowGraph; import org.opendc.simulator.flow2.InPort; @@ -56,7 +56,7 @@ public final class SimBareMetalMachine extends SimAbstractMachine { /** * The resources of this machine. */ - private final List<Cpu> cpus; + private final SimCpu cpu; private final Memory memory; private final List<NetworkAdapter> net; @@ -75,13 +75,7 @@ public final class SimBareMetalMachine extends SimAbstractMachine { this.graph = graph; this.psu = psuFactory.newPsu(this, graph); - int cpuIndex = 0; - final ArrayList<Cpu> cpus = new ArrayList<>(); - this.cpus = cpus; - for (ProcessingUnit cpu : model.getCpus()) { - cpus.add(new Cpu(psu, cpu, cpuIndex++)); - } - + this.cpu = new SimCpu(psu, model.getCpu(), 0); this.memory = new Memory(graph, model.getMemory()); int netIndex = 0; @@ -139,76 +133,58 @@ public final class SimBareMetalMachine extends SimAbstractMachine { * Return the CPU capacity of the machine in MHz. */ public double getCpuCapacity() { - final Context context = (Context) getActiveContext(); + final SimAbstractMachineContext context = (SimAbstractMachineContext) getActiveContext(); if (context == null) { return 0.0; } - float capacity = 0.f; - - for (SimProcessingUnit cpu : context.cpus) { - capacity += cpu.getFrequency(); - } - - return capacity; + return cpu.getFrequency(); } /** * The CPU demand of the machine in MHz. */ public double getCpuDemand() { - final Context context = (Context) getActiveContext(); + final SimAbstractMachineContext context = (SimAbstractMachineContext) getActiveContext(); if (context == null) { return 0.0; } - float demand = 0.f; - - for (SimProcessingUnit cpu : context.cpus) { - demand += cpu.getDemand(); - } - - return demand; + return cpu.getDemand(); } /** * The CPU usage of the machine in MHz. */ public double getCpuUsage() { - final Context context = (Context) getActiveContext(); + final SimAbstractMachineContext context = (SimAbstractMachineContext) getActiveContext(); if (context == null) { return 0.0; } - float rate = 0.f; - - for (SimProcessingUnit cpu : context.cpus) { - rate += cpu.getSpeed(); - } - - return rate; + return cpu.getSpeed(); } @Override - protected SimAbstractMachine.Context createContext( + protected SimAbstractMachine.SimAbstractMachineContext createContext( SimWorkload workload, Map<String, Object> meta, Consumer<Exception> completion) { - return new Context(this, workload, meta, completion); + return new SimAbstractMachineContext(this, workload, meta, completion); } /** * The execution context for a {@link SimBareMetalMachine}. */ - private static final class Context extends SimAbstractMachine.Context { + private static final class SimAbstractMachineContext extends SimAbstractMachine.SimAbstractMachineContext { private final FlowGraph graph; - private final List<Cpu> cpus; + private final SimCpu cpu; private final Memory memory; private final List<NetworkAdapter> net; private final List<StorageDevice> disk; - private Context( + private SimAbstractMachineContext( SimBareMetalMachine machine, SimWorkload workload, Map<String, Object> meta, @@ -216,7 +192,7 @@ public final class SimBareMetalMachine extends SimAbstractMachine { super(machine, workload, meta, completion); this.graph = machine.graph; - this.cpus = machine.cpus; + this.cpu = machine.cpu; this.memory = machine.memory; this.net = machine.net; this.disk = machine.disk; @@ -228,8 +204,8 @@ public final class SimBareMetalMachine extends SimAbstractMachine { } @Override - public List<? extends SimProcessingUnit> getCpus() { - return cpus; + public SimCpu getCpu() { + return cpu; } @Override @@ -251,17 +227,17 @@ public final class SimBareMetalMachine extends SimAbstractMachine { /** * A {@link SimProcessingUnit} of a bare-metal machine. */ - private static final class Cpu implements SimProcessingUnit { + private static final class SimCpu implements SimProcessingUnit { private final SimPsu psu; - private final ProcessingUnit model; + private final Cpu cpuModel; private final InPort port; - private Cpu(SimPsu psu, ProcessingUnit model, int id) { + private SimCpu(SimPsu psu, Cpu cpuModel, int id) { this.psu = psu; - this.model = model; - this.port = psu.getCpuPower(id, model); + this.cpuModel = cpuModel; + this.port = psu.getCpuPower(id, cpuModel); - this.port.pull((float) model.getFrequency()); + this.port.pull((float) cpuModel.getTotalCapacity()); } @Override @@ -272,7 +248,7 @@ public final class SimBareMetalMachine extends SimAbstractMachine { @Override public void setFrequency(double frequency) { // Clamp the capacity of the CPU between [0.0, maxFreq] - frequency = Math.max(0, Math.min(model.getFrequency(), frequency)); + frequency = Math.max(0, Math.min(cpuModel.getTotalCapacity(), frequency)); psu.setCpuFrequency(port, frequency); } @@ -287,8 +263,8 @@ public final class SimBareMetalMachine extends SimAbstractMachine { } @Override - public ProcessingUnit getModel() { - return model; + public org.opendc.simulator.compute.model.Cpu getCpuModel() { + return cpuModel; } @Override @@ -298,7 +274,7 @@ public final class SimBareMetalMachine extends SimAbstractMachine { @Override public String toString() { - return "SimBareMetalMachine.Cpu[model=" + model + "]"; + return "SimBareMetalMachine.Cpu[model=" + cpuModel + "]"; } } } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMachineContext.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMachineContext.java index 7f98dee5..887967fb 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMachineContext.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMachineContext.java @@ -51,7 +51,7 @@ public interface SimMachineContext { /** * Return the CPUs available on the machine. */ - List<? extends SimProcessingUnit> getCpus(); + SimProcessingUnit getCpu(); /** * Return the memory interface of the machine. diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMemory.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMemory.java index 4fcc64ab..85027f28 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMemory.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMemory.java @@ -22,7 +22,6 @@ package org.opendc.simulator.compute; -import java.util.List; import org.opendc.simulator.compute.model.MemoryUnit; import org.opendc.simulator.flow2.sink.FlowSink; @@ -38,5 +37,5 @@ public interface SimMemory extends FlowSink { /** * Return the models representing the static information of the memory units supporting this interface. */ - List<MemoryUnit> getModels(); + MemoryUnit getMemoryUnit(); } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimProcessingUnit.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimProcessingUnit.java index 3dbd3656..213c3d4f 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimProcessingUnit.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimProcessingUnit.java @@ -22,7 +22,7 @@ package org.opendc.simulator.compute; -import org.opendc.simulator.compute.model.ProcessingUnit; +import org.opendc.simulator.compute.model.Cpu; import org.opendc.simulator.flow2.sink.FlowSink; /** @@ -58,5 +58,5 @@ public interface SimProcessingUnit extends FlowSink { /** * The model representing the static properties of the processing unit. */ - ProcessingUnit getModel(); + Cpu getCpuModel(); } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java index 68dae4bf..e7718604 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java @@ -22,7 +22,7 @@ package org.opendc.simulator.compute; -import org.opendc.simulator.compute.model.ProcessingUnit; +import org.opendc.simulator.compute.model.Cpu; import org.opendc.simulator.flow2.InPort; import org.opendc.simulator.power.SimPowerInlet; @@ -57,7 +57,7 @@ public abstract class SimPsu extends SimPowerInlet { * @param id The unique identifier of the CPU for this machine. * @param model The details of the processing unit. */ - abstract InPort getCpuPower(int id, ProcessingUnit model); + abstract InPort getCpuPower(int id, Cpu model); /** * This method is invoked when the CPU frequency is changed for the specified <code>port</code>. diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java index 5b118429..27327616 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java @@ -24,7 +24,7 @@ package org.opendc.simulator.compute; import java.time.InstantSource; import org.jetbrains.annotations.NotNull; -import org.opendc.simulator.compute.model.ProcessingUnit; +import org.opendc.simulator.compute.model.Cpu; import org.opendc.simulator.compute.power.CpuPowerModel; import org.opendc.simulator.flow2.FlowGraph; import org.opendc.simulator.flow2.FlowStage; @@ -92,7 +92,7 @@ public class SimPsuFactories { } @Override - InPort getCpuPower(int id, ProcessingUnit model) { + InPort getCpuPower(int id, Cpu model) { final InPort port = stage.getInlet("cpu" + id); port.setMask(true); return port; @@ -165,8 +165,8 @@ public class SimPsuFactories { } @Override - InPort getCpuPower(int id, ProcessingUnit model) { - targetFreq += model.getFrequency(); + InPort getCpuPower(int id, Cpu model) { + targetFreq += model.getTotalCapacity(); final InPort port = stage.getInlet("cpu" + id); port.setHandler(handler); diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimHypervisor.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimHypervisor.java index aced54a7..42750b0f 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimHypervisor.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimHypervisor.java @@ -29,7 +29,6 @@ import java.util.List; import java.util.Map; import java.util.SplittableRandom; import java.util.function.Consumer; -import java.util.stream.Collectors; import org.opendc.simulator.compute.SimAbstractMachine; import org.opendc.simulator.compute.SimMachine; import org.opendc.simulator.compute.SimMachineContext; @@ -44,8 +43,8 @@ import org.opendc.simulator.compute.kernel.cpufreq.ScalingPolicy; import org.opendc.simulator.compute.kernel.interference.VmInterferenceDomain; import org.opendc.simulator.compute.kernel.interference.VmInterferenceMember; import org.opendc.simulator.compute.kernel.interference.VmInterferenceProfile; +import org.opendc.simulator.compute.model.Cpu; import org.opendc.simulator.compute.model.MachineModel; -import org.opendc.simulator.compute.model.ProcessingUnit; import org.opendc.simulator.compute.workload.SimWorkload; import org.opendc.simulator.flow2.FlowGraph; import org.opendc.simulator.flow2.FlowStage; @@ -68,8 +67,8 @@ public final class SimHypervisor implements SimWorkload { private final ScalingGovernorFactory scalingGovernorFactory; private final VmInterferenceDomain interferenceDomain; - private Context activeContext; - private final ArrayList<VirtualMachine> vms = new ArrayList<>(); + private SimHyperVisorContext activeContext; + private final ArrayList<SimVirtualMachine> vms = new ArrayList<>(); private final HvCounters counters = new HvCounters(); @Override @@ -156,7 +155,7 @@ public final class SimHypervisor implements SimWorkload { throw new IllegalArgumentException("Machine does not fit"); } - VirtualMachine vm = new VirtualMachine(model); + SimVirtualMachine vm = new SimVirtualMachine(model); vms.add(vm); return vm; } @@ -169,7 +168,7 @@ public final class SimHypervisor implements SimWorkload { public void removeMachine(SimVirtualMachine machine) { if (vms.remove(machine)) { // This cast must always succeed, since `_vms` only contains `VirtualMachine` types. - ((VirtualMachine) machine).close(); + ((SimVirtualMachine) machine).close(); } } @@ -177,7 +176,7 @@ public final class SimHypervisor implements SimWorkload { * Return the CPU capacity of the hypervisor in MHz. */ public double getCpuCapacity() { - final Context context = activeContext; + final SimHyperVisorContext context = activeContext; if (context == null) { return 0.0; @@ -190,7 +189,7 @@ public final class SimHypervisor implements SimWorkload { * The CPU demand of the hypervisor in MHz. */ public double getCpuDemand() { - final Context context = activeContext; + final SimHyperVisorContext context = activeContext; if (context == null) { return 0.0; @@ -203,7 +202,7 @@ public final class SimHypervisor implements SimWorkload { * The CPU usage of the hypervisor in MHz. */ public double getCpuUsage() { - final Context context = activeContext; + final SimHyperVisorContext context = activeContext; if (context == null) { return 0.0; @@ -217,26 +216,26 @@ public final class SimHypervisor implements SimWorkload { * moment. */ public boolean canFit(MachineModel model) { - final Context context = activeContext; + final SimHyperVisorContext context = activeContext; if (context == null) { return false; } final FlowMultiplexer multiplexer = context.multiplexer; - return (multiplexer.getMaxInputs() - multiplexer.getInputCount()) - >= model.getCpus().size(); + return (multiplexer.getMaxInputs() - multiplexer.getInputCount()) >= 1; } @Override public void onStart(SimMachineContext ctx) { - final Context context = new Context(ctx, muxFactory, scalingGovernorFactory, counters); + final SimHyperVisorContext context = + new SimHyperVisorContext(ctx, muxFactory, scalingGovernorFactory, counters); context.start(); activeContext = context; } @Override public void onStop(SimMachineContext ctx) { - final Context context = activeContext; + final SimHyperVisorContext context = activeContext; if (context != null) { activeContext = null; context.stop(); @@ -276,11 +275,11 @@ public final class SimHypervisor implements SimWorkload { /** * The context which carries the state when the hypervisor is running on a machine. */ - private static final class Context implements FlowStageLogic { + private static final class SimHyperVisorContext implements FlowStageLogic { private final SimMachineContext ctx; private final FlowMultiplexer multiplexer; private final FlowStage stage; - private final List<ScalingGovernor> scalingGovernors; + private final ScalingGovernor scalingGovernor; private final InstantSource clock; private final HvCounters counters; @@ -290,7 +289,7 @@ public final class SimHypervisor implements SimWorkload { private float previousRate; private float previousCapacity; - private Context( + private SimHyperVisorContext( SimMachineContext ctx, FlowMultiplexerFactory muxFactory, ScalingGovernorFactory scalingGovernorFactory, @@ -306,20 +305,15 @@ public final class SimHypervisor implements SimWorkload { this.lastCounterUpdate = clock.millis(); + final SimProcessingUnit cpu = ctx.getCpu(); + if (scalingGovernorFactory != null) { - this.scalingGovernors = ctx.getCpus().stream() - .map(cpu -> scalingGovernorFactory.newGovernor(new ScalingPolicyImpl(cpu))) - .collect(Collectors.toList()); + this.scalingGovernor = scalingGovernorFactory.newGovernor(new ScalingPolicyImpl(cpu)); } else { - this.scalingGovernors = Collections.emptyList(); + this.scalingGovernor = null; } - float cpuCapacity = 0.f; - final List<? extends SimProcessingUnit> cpus = ctx.getCpus(); - for (SimProcessingUnit cpu : cpus) { - cpuCapacity += cpu.getFrequency(); - } - this.d = cpus.size() / cpuCapacity; + this.d = 1 / cpu.getFrequency(); } /** @@ -329,12 +323,10 @@ public final class SimHypervisor implements SimWorkload { final FlowGraph graph = ctx.getGraph(); final FlowMultiplexer multiplexer = this.multiplexer; - for (SimProcessingUnit cpu : ctx.getCpus()) { - graph.connect(multiplexer.newOutput(), cpu.getInput()); - } + graph.connect(multiplexer.newOutput(), ctx.getCpu().getInput()); - for (ScalingGovernor governor : scalingGovernors) { - governor.onStart(); + if (this.scalingGovernor != null) { + this.scalingGovernor.onStart(); } } @@ -392,7 +384,7 @@ public final class SimHypervisor implements SimWorkload { updateCounters(now); final FlowMultiplexer multiplexer = this.multiplexer; - final List<ScalingGovernor> scalingGovernors = this.scalingGovernors; + final ScalingGovernor scalingGovernors = this.scalingGovernor; float demand = multiplexer.getDemand(); float rate = multiplexer.getRate(); @@ -404,10 +396,8 @@ public final class SimHypervisor implements SimWorkload { double load = rate / Math.min(1.0, capacity); - if (!scalingGovernors.isEmpty()) { - for (ScalingGovernor governor : scalingGovernors) { - governor.onLimit(load); - } + if (scalingGovernor != null) { + scalingGovernor.onLimit(load); } return Long.MAX_VALUE; @@ -446,27 +436,25 @@ public final class SimHypervisor implements SimWorkload { @Override public double getMax() { - return cpu.getModel().getFrequency(); + return cpu.getCpuModel().getTotalCapacity(); } } /** * A virtual machine running on the hypervisor. */ - private class VirtualMachine extends SimAbstractMachine implements SimVirtualMachine { + public class SimVirtualMachine extends SimAbstractMachine { private boolean isClosed; private final VmCounters counters = new VmCounters(this); - private VirtualMachine(MachineModel model) { + private SimVirtualMachine(MachineModel model) { super(model); } - @Override public SimHypervisorCounters getCounters() { return counters; } - @Override public double getCpuDemand() { final VmContext context = (VmContext) getActiveContext(); @@ -477,7 +465,6 @@ public final class SimHypervisor implements SimWorkload { return context.previousDemand; } - @Override public double getCpuUsage() { final VmContext context = (VmContext) getActiveContext(); @@ -488,7 +475,6 @@ public final class SimHypervisor implements SimWorkload { return context.usage; } - @Override public double getCpuCapacity() { final VmContext context = (VmContext) getActiveContext(); @@ -505,13 +491,13 @@ public final class SimHypervisor implements SimWorkload { } @Override - protected Context createContext( + protected SimAbstractMachineContext createContext( SimWorkload workload, Map<String, Object> meta, Consumer<Exception> completion) { if (isClosed) { throw new IllegalStateException("Virtual machine does not exist anymore"); } - final SimHypervisor.Context context = activeContext; + final SimHyperVisorContext context = activeContext; if (context == null) { throw new IllegalStateException("Hypervisor is inactive"); } @@ -529,7 +515,7 @@ public final class SimHypervisor implements SimWorkload { } @Override - public Context getActiveContext() { + public SimAbstractMachineContext getActiveContext() { return super.getActiveContext(); } @@ -544,10 +530,11 @@ public final class SimHypervisor implements SimWorkload { } /** - * A {@link SimAbstractMachine.Context} for a virtual machine instance. + * A {@link SimAbstractMachine.SimAbstractMachineContext} for a virtual machine instance. */ - private static final class VmContext extends SimAbstractMachine.Context implements FlowStageLogic { - private final Context context; + private static final class VmContext extends SimAbstractMachine.SimAbstractMachineContext + implements FlowStageLogic { + private final SimHyperVisorContext simHyperVisorContext; private final SplittableRandom random; private final VmCounters vmCounters; private final HvCounters hvCounters; @@ -556,7 +543,7 @@ public final class SimHypervisor implements SimWorkload { private final FlowMultiplexer multiplexer; private final InstantSource clock; - private final List<VCpu> cpus; + private final VCpu cpu; private final SimAbstractMachine.Memory memory; private final List<SimAbstractMachine.NetworkAdapter> net; private final List<SimAbstractMachine.StorageDevice> disk; @@ -574,8 +561,8 @@ public final class SimHypervisor implements SimWorkload { private float previousCapacity; private VmContext( - Context context, - VirtualMachine machine, + SimHyperVisorContext simHyperVisorContext, + SimVirtualMachine machine, SplittableRandom random, VmInterferenceDomain interferenceDomain, VmCounters vmCounters, @@ -585,11 +572,11 @@ public final class SimHypervisor implements SimWorkload { Consumer<Exception> completion) { super(machine, workload, meta, completion); - this.context = context; + this.simHyperVisorContext = simHyperVisorContext; this.random = random; this.vmCounters = vmCounters; this.hvCounters = hvCounters; - this.clock = context.clock; + this.clock = simHyperVisorContext.clock; final VmInterferenceProfile interferenceProfile = (VmInterferenceProfile) meta.get("interference-profile"); VmInterferenceMember interferenceMember = null; @@ -599,45 +586,36 @@ public final class SimHypervisor implements SimWorkload { } this.interferenceMember = interferenceMember; - final FlowGraph graph = context.ctx.getGraph(); + final FlowGraph graph = simHyperVisorContext.ctx.getGraph(); final FlowStage stage = graph.newStage(this); this.stage = stage; this.lastUpdate = clock.millis(); this.lastCounterUpdate = clock.millis(); - final FlowMultiplexer multiplexer = context.multiplexer; + final FlowMultiplexer multiplexer = simHyperVisorContext.multiplexer; this.multiplexer = multiplexer; final MachineModel model = machine.getModel(); - final List<ProcessingUnit> cpuModels = model.getCpus(); - final Inlet[] muxInlets = new Inlet[cpuModels.size()]; - final ArrayList<VCpu> cpus = new ArrayList<>(); + final Cpu cpuModel = model.getCpu(); + final Inlet[] muxInlets = new Inlet[1]; this.muxInlets = muxInlets; - this.cpus = cpus; - - float capacity = 0.f; - for (int i = 0; i < cpuModels.size(); i++) { - final Inlet muxInlet = multiplexer.newInput(); - muxInlets[i] = muxInlet; + final Inlet muxInlet = multiplexer.newInput(); + muxInlets[0] = muxInlet; - final InPort input = stage.getInlet("cpu" + i); - final OutPort output = stage.getOutlet("mux" + i); + final InPort input = stage.getInlet("cpu"); + final OutPort output = stage.getOutlet("mux"); - final Handler handler = new Handler(this, input, output); - input.setHandler(handler); - output.setHandler(handler); + final Handler handler = new Handler(this, input, output); + input.setHandler(handler); + output.setHandler(handler); - final ProcessingUnit cpuModel = cpuModels.get(i); - capacity += cpuModel.getFrequency(); + this.cpu = new VCpu(cpuModel, input); - final VCpu cpu = new VCpu(cpuModel, input); - cpus.add(cpu); + graph.connect(output, muxInlet); - graph.connect(output, muxInlet); - } - this.d = cpuModels.size() / capacity; + this.d = 1 / cpuModel.getTotalCapacity(); this.memory = new SimAbstractMachine.Memory(graph, model.getMemory()); @@ -664,7 +642,7 @@ public final class SimHypervisor implements SimWorkload { void updateCounters(long now) { long lastUpdate = this.lastCounterUpdate; this.lastCounterUpdate = now; - long delta = now - lastUpdate; + long delta = now - lastUpdate; // time between updates if (delta > 0) { final VmCounters counters = this.vmCounters; @@ -673,7 +651,7 @@ public final class SimHypervisor implements SimWorkload { float rate = this.usage; float capacity = this.previousCapacity; - final double factor = this.d * delta; + final double factor = this.d * delta; // time between divided by total capacity final double active = rate * factor; counters.cpuActiveTime += Math.round(active); @@ -695,8 +673,8 @@ public final class SimHypervisor implements SimWorkload { } @Override - public List<? extends SimProcessingUnit> getCpus() { - return cpus; + public SimProcessingUnit getCpu() { + return cpu; } @Override @@ -746,7 +724,7 @@ public final class SimHypervisor implements SimWorkload { } // Invalidate the FlowStage of the hypervisor to update its counters (via onUpdate) - context.invalidate(); + simHyperVisorContext.invalidate(); return Long.MAX_VALUE; } @@ -776,14 +754,14 @@ public final class SimHypervisor implements SimWorkload { * A {@link SimProcessingUnit} of a virtual machine. */ private static final class VCpu implements SimProcessingUnit { - private final ProcessingUnit model; + private final Cpu model; private final InPort input; - private VCpu(ProcessingUnit model, InPort input) { + private VCpu(Cpu model, InPort input) { this.model = model; this.input = input; - input.pull((float) model.getFrequency()); + input.pull((float) model.getTotalCapacity()); } @Override @@ -807,7 +785,7 @@ public final class SimHypervisor implements SimWorkload { } @Override - public ProcessingUnit getModel() { + public Cpu getCpuModel() { return model; } @@ -901,7 +879,7 @@ public final class SimHypervisor implements SimWorkload { @Override public void sync() { - final Context context = activeContext; + final SimHyperVisorContext context = activeContext; if (context != null) { context.updateCounters(); @@ -913,13 +891,13 @@ public final class SimHypervisor implements SimWorkload { * Implementation of {@link SimHypervisorCounters} for the virtual machine. */ private static class VmCounters implements SimHypervisorCounters { - private final VirtualMachine vm; + private final SimVirtualMachine vm; private long cpuActiveTime; private long cpuIdleTime; private long cpuStealTime; private long cpuLostTime; - private VmCounters(VirtualMachine vm) { + private VmCounters(SimVirtualMachine vm) { this.vm = vm; } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimVirtualMachine.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimVirtualMachine.java deleted file mode 100644 index fdf5e47f..00000000 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimVirtualMachine.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.simulator.compute.kernel; - -import org.opendc.simulator.compute.SimMachine; - -/** - * A virtual {@link SimMachine} running on top of another {@link SimMachine}. - */ -public interface SimVirtualMachine extends SimMachine { - /** - * Return the performance counters associated with the virtual machine. - */ - SimHypervisorCounters getCounters(); - - /** - * Return the CPU usage of the VM in MHz. - */ - double getCpuUsage(); - - /** - * Return the CPU usage of the VM in MHz. - */ - double getCpuDemand(); - - /** - * Return the CPU capacity of the VM in MHz. - */ - double getCpuCapacity(); -} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/Cpu.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/Cpu.java new file mode 100644 index 00000000..c319ae1a --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/Cpu.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2022 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.simulator.compute.model; + +import java.util.Objects; + +/** + * A single logical compute unit of processor node, either virtual or physical. + */ +public final class Cpu { + private final int id; + private final int coreCount; + private final double coreSpeed; + private final double totalCapacity; + + private final String vendor; + private final String modelName; + private final String arch; + + /** + * Construct a {@link Cpu} instance. + * + * @param id The identifier of the CPU core within the processing node. + * @param coreCount The number of cores present in the CPU + * @param coreSpeed The speed of a single core + * @param vendor The vendor of the CPU + * @param modelName The name of the CPU + * @param arch The architecture of the CPU + */ + public Cpu(int id, int coreCount, double coreSpeed, String vendor, String modelName, String arch) { + this.id = id; + this.coreCount = coreCount; + this.coreSpeed = coreSpeed; + this.totalCapacity = coreSpeed * coreCount; + this.vendor = vendor; + this.modelName = modelName; + this.arch = arch; + } + + public Cpu(int id, int coreCount, double coreSpeed) { + this(id, coreCount, coreSpeed, "unkown", "unkown", "unkown"); + } + + /** + * Return the identifier of the CPU core within the processing node. + */ + public int getId() { + return id; + } + + /** + * Return the number of logical CPUs in the processor node. + */ + public int getCoreCount() { + return coreCount; + } + + /** + * Return the clock rate of a single core of the CPU MHz. + */ + public double getCoreSpeed() { + return coreSpeed; + } + + /** + * Return the clock rate of the CPU in MHz. + */ + public double getTotalCapacity() { + return totalCapacity; + } + + /** + * Return the vendor of the storage device. + */ + public String getVendor() { + return vendor; + } + + /** + * Return the model name of the device. + */ + public String getModelName() { + return modelName; + } + + /** + * Return the micro-architecture of the processor node. + */ + public String getArchitecture() { + return arch; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Cpu that = (Cpu) o; + return id == that.id + && Double.compare(that.totalCapacity, totalCapacity) == 0 + && Double.compare(that.coreSpeed, coreSpeed) == 0 + && Objects.equals(vendor, that.vendor) + && Objects.equals(modelName, that.modelName) + && Objects.equals(arch, that.arch); + } + + @Override + public int hashCode() { + return Objects.hash(id, coreCount, coreSpeed, totalCapacity, vendor, modelName, arch); + } + + @Override + public String toString() { + return "ProcessingUnit[" + "id= " + id + ", coreCount= " + coreCount + ", coreSpeed= " + coreSpeed + + ", frequency= " + totalCapacity + ", vendor= " + vendor + ", modelName= " + modelName + ", arch= " + + arch + "]"; + } +} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/MachineModel.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/MachineModel.java index 2c625fce..e4019dac 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/MachineModel.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/MachineModel.java @@ -31,29 +31,23 @@ import java.util.Objects; * A description of the physical or virtual machine on which a bootable image runs. */ public final class MachineModel { - private final List<ProcessingUnit> cpus; - private final List<MemoryUnit> memory; + private final Cpu cpu; + private final MemoryUnit memory; private final List<NetworkAdapter> net; private final List<StorageDevice> storage; /** * Construct a {@link MachineModel} instance. * - * @param cpus The list of processing units available to the image. + * @param cpu The cpu available to the image. * @param memory The list of memory units available to the image. * @param net A list of network adapters available to the machine. * @param storage A list of storage devices available to the machine. */ - public MachineModel( - Iterable<ProcessingUnit> cpus, - Iterable<MemoryUnit> memory, - Iterable<NetworkAdapter> net, - Iterable<StorageDevice> storage) { - this.cpus = new ArrayList<>(); - cpus.forEach(this.cpus::add); + public MachineModel(Cpu cpu, MemoryUnit memory, Iterable<NetworkAdapter> net, Iterable<StorageDevice> storage) { + this.cpu = cpu; - this.memory = new ArrayList<>(); - memory.forEach(this.memory::add); + this.memory = memory; this.net = new ArrayList<>(); net.forEach(this.net::add); @@ -62,54 +56,50 @@ public final class MachineModel { storage.forEach(this.storage::add); } + public MachineModel(Cpu cpu, MemoryUnit memory) { + this(cpu, memory, Collections.emptyList(), Collections.emptyList()); + } + /** * Construct a {@link MachineModel} instance. + * A list of the same cpus, are automatically converted to a single CPU with the number of cores of + * all cpus in the list combined. * * @param cpus The list of processing units available to the image. * @param memory The list of memory units available to the image. */ - public MachineModel(Iterable<ProcessingUnit> cpus, Iterable<MemoryUnit> memory) { - this(cpus, memory, Collections.emptyList(), Collections.emptyList()); + public MachineModel( + List<Cpu> cpus, MemoryUnit memory, Iterable<NetworkAdapter> net, Iterable<StorageDevice> storage) { + + this( + new Cpu( + cpus.get(0).getId(), + cpus.get(0).getCoreCount() * cpus.size(), + cpus.get(0).getCoreSpeed(), + cpus.get(0).getVendor(), + cpus.get(0).getModelName(), + cpus.get(0).getArchitecture()), + memory, + net, + storage); } - /** - * Optimize the [MachineModel] by merging all resources of the same type into a single resource with the combined - * capacity. Such configurations can be simulated more efficiently by OpenDC. - */ - public MachineModel optimize() { - ProcessingUnit originalCpu = cpus.get(0); - - double freq = 0.0; - for (ProcessingUnit cpu : cpus) { - freq += cpu.getFrequency(); - } - - ProcessingNode originalNode = originalCpu.getNode(); - ProcessingNode processingNode = new ProcessingNode( - originalNode.getVendor(), originalNode.getModelName(), originalNode.getArchitecture(), 1); - ProcessingUnit processingUnit = new ProcessingUnit(processingNode, originalCpu.getId(), freq); - - long memorySize = 0; - for (MemoryUnit mem : memory) { - memorySize += mem.getSize(); - } - MemoryUnit memoryUnit = new MemoryUnit("Generic", "Generic", 3200.0, memorySize); - - return new MachineModel(List.of(processingUnit), List.of(memoryUnit)); + public MachineModel(List<Cpu> cpus, MemoryUnit memory) { + this(cpus, memory, Collections.emptyList(), Collections.emptyList()); } /** * Return the processing units of this machine. */ - public List<ProcessingUnit> getCpus() { - return Collections.unmodifiableList(cpus); + public Cpu getCpu() { + return this.cpu; } /** * Return the memory units of this machine. */ - public List<MemoryUnit> getMemory() { - return Collections.unmodifiableList(memory); + public MemoryUnit getMemory() { + return memory; } /** @@ -131,7 +121,7 @@ public final class MachineModel { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MachineModel that = (MachineModel) o; - return cpus.equals(that.cpus) + return cpu.equals(that.cpu) && memory.equals(that.memory) && net.equals(that.net) && storage.equals(that.storage); @@ -139,11 +129,11 @@ public final class MachineModel { @Override public int hashCode() { - return Objects.hash(cpus, memory, net, storage); + return Objects.hash(cpu, memory, net, storage); } @Override public String toString() { - return "MachineModel[cpus=" + cpus + ",memory=" + memory + ",net=" + net + ",storage=" + storage + "]"; + return "MachineModel[cpus=" + cpu + ",memory=" + memory + ",net=" + net + ",storage=" + storage + "]"; } } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/ProcessingUnit.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/ProcessingUnit.java deleted file mode 100644 index 0bead16a..00000000 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/ProcessingUnit.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.simulator.compute.model; - -import java.util.Objects; - -/** - * A single logical compute unit of processor node, either virtual or physical. - */ -public final class ProcessingUnit { - private final ProcessingNode node; - private final int id; - private final double frequency; - - /** - * Construct a {@link ProcessingUnit} instance. - * - * @param node The processing node containing the CPU core. - * @param id The identifier of the CPU core within the processing node. - * @param frequency The clock rate of the CPU in MHz. - */ - public ProcessingUnit(ProcessingNode node, int id, double frequency) { - this.node = node; - this.id = id; - this.frequency = frequency * node.getCoreCount(); - } - - /** - * Return the processing node containing the CPU core. - */ - public ProcessingNode getNode() { - return node; - } - - /** - * Return the identifier of the CPU core within the processing node. - */ - public int getId() { - return id; - } - - /** - * Return the clock rate of the CPU in MHz. - */ - public double getFrequency() { - return frequency; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ProcessingUnit that = (ProcessingUnit) o; - return id == that.id && Double.compare(that.frequency, frequency) == 0 && Objects.equals(node, that.node); - } - - @Override - public int hashCode() { - return Objects.hash(node, id, frequency); - } - - @Override - public String toString() { - return "ProcessingUnit[node=" + node + ",id=" + id + ",frequency=" + frequency + "]"; - } -} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimChainWorkload.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimChainWorkload.java index edf201a7..1dcb3674 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimChainWorkload.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimChainWorkload.java @@ -41,7 +41,7 @@ final class SimChainWorkload implements SimWorkload { private final SimWorkload[] workloads; private int activeWorkloadIndex; - private Context activeContext; + private SimChainWorkloadContext activeContext; private long checkpointInterval = 0; private long checkpointDuration = 0; @@ -108,7 +108,7 @@ final class SimChainWorkload implements SimWorkload { return; } - final Context context = new Context(ctx); + final SimChainWorkloadContext context = new SimChainWorkloadContext(ctx); activeContext = context; if (checkpointInterval > 0) { @@ -128,7 +128,7 @@ final class SimChainWorkload implements SimWorkload { return; } - final Context context = activeContext; + final SimChainWorkloadContext context = activeContext; activeContext = null; if (this.checkpointModel != null) { @@ -174,7 +174,7 @@ final class SimChainWorkload implements SimWorkload { private Boolean firstCheckPoint = true; CheckPointModel( - Context context, + SimChainWorkloadContext context, SimChainWorkload workload, long checkpointInterval, long checkpointDuration, @@ -228,11 +228,11 @@ final class SimChainWorkload implements SimWorkload { /** * A {@link SimMachineContext} that intercepts the shutdown calls. */ - private class Context implements SimMachineContext { + private class SimChainWorkloadContext implements SimMachineContext { private final SimMachineContext ctx; private SimWorkload snapshot; - private Context(SimMachineContext ctx) { + private SimChainWorkloadContext(SimMachineContext ctx) { this.ctx = ctx; } @@ -247,8 +247,8 @@ final class SimChainWorkload implements SimWorkload { } @Override - public List<? extends SimProcessingUnit> getCpus() { - return ctx.getCpus(); + public SimProcessingUnit getCpu() { + return ctx.getCpu(); } @Override diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimFlopsWorkload.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimFlopsWorkload.java index 06fcb2bc..5311fa38 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimFlopsWorkload.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimFlopsWorkload.java @@ -22,7 +22,6 @@ package org.opendc.simulator.compute.workload; -import java.util.List; import org.opendc.simulator.compute.SimMachineContext; import org.opendc.simulator.compute.SimProcessingUnit; import org.opendc.simulator.flow2.FlowGraph; @@ -92,17 +91,14 @@ public class SimFlopsWorkload implements SimWorkload, FlowStageLogic { final FlowStage stage = graph.newStage(this); this.stage = stage; - final List<? extends SimProcessingUnit> cpus = ctx.getCpus(); - final OutPort[] outputs = new OutPort[cpus.size()]; + final SimProcessingUnit cpu = ctx.getCpu(); + final OutPort[] outputs = new OutPort[1]; this.outputs = outputs; - for (int i = 0; i < cpus.size(); i++) { - final SimProcessingUnit cpu = cpus.get(i); - final OutPort output = stage.getOutlet("cpu" + i); + final OutPort output = stage.getOutlet("cpu"); - graph.connect(output, cpu.getInput()); - outputs[i] = output; - } + graph.connect(output, cpu.getInput()); + outputs[0] = output; this.remainingAmount = flops; this.lastUpdate = graph.getEngine().getClock().millis(); diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimRuntimeWorkload.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimRuntimeWorkload.java index 64b1a10b..be4cc2f5 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimRuntimeWorkload.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimRuntimeWorkload.java @@ -22,7 +22,6 @@ package org.opendc.simulator.compute.workload; -import java.util.List; import org.opendc.simulator.compute.SimMachineContext; import org.opendc.simulator.compute.SimProcessingUnit; import org.opendc.simulator.flow2.FlowGraph; @@ -122,17 +121,14 @@ public class SimRuntimeWorkload implements SimWorkload, FlowStageLogic { final FlowStage stage = graph.newStage(this); this.stage = stage; - final List<? extends SimProcessingUnit> cpus = ctx.getCpus(); - final OutPort[] outputs = new OutPort[cpus.size()]; + final OutPort[] outputs = new OutPort[1]; this.outputs = outputs; - for (int i = 0; i < cpus.size(); i++) { - final SimProcessingUnit cpu = cpus.get(i); - final OutPort output = stage.getOutlet("cpu" + i); + final SimProcessingUnit cpu = ctx.getCpu(); + final OutPort output = stage.getOutlet("cpu"); - graph.connect(output, cpu.getInput()); - outputs[i] = output; - } + graph.connect(output, cpu.getInput()); + outputs[0] = output; this.remainingDuration = duration; this.lastUpdate = graph.getEngine().getClock().millis(); 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 384907b2..b8445a9c 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 @@ -210,11 +210,7 @@ public final class SimTrace { @Override public void onStart(SimMachineContext ctx) { final WorkloadStageLogic logic; - if (ctx.getCpus().size() == 1) { - logic = new SingleWorkloadLogic(ctx, offset, fragments.iterator()); - } else { - logic = new MultiWorkloadLogic(ctx, offset, fragments.iterator()); - } + logic = new SingleWorkloadLogic(ctx, offset, fragments.iterator()); this.logic = logic; } @@ -325,11 +321,9 @@ public final class SimTrace { this.fragments = fragments; final FlowGraph graph = ctx.getGraph(); - final List<? extends SimProcessingUnit> cpus = ctx.getCpus(); - stage = graph.newStage(this); - final SimProcessingUnit cpu = cpus.get(0); + final SimProcessingUnit cpu = ctx.getCpu(); final OutPort output = stage.getOutlet("cpu"); this.output = output; @@ -416,149 +410,4 @@ public final class SimTrace { 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 = 0; - - private final int coreCount; - - private Iterator<SimTraceFragment> fragments; - private SimTraceFragment currentFragment; - private long startOffFragment; - - private final SimMachineContext ctx; - - private MultiWorkloadLogic(SimMachineContext ctx, long offset, Iterator<SimTraceFragment> fragments) { - this.ctx = ctx; - this.fragments = fragments; - - final FlowGraph graph = ctx.getGraph(); - final List<? extends SimProcessingUnit> cpus = ctx.getCpus(); - - stage = graph.newStage(this); - this.coreCount = cpus.size(); - - final OutPort[] outputs = new OutPort[cpus.size()]; - this.outputs = outputs; - - for (int i = 0; i < cpus.size(); i++) { - final SimProcessingUnit cpu = cpus.get(i); - final OutPort output = stage.getOutlet("cpu" + i); - - 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; - } - - public long getPassedTime(long now) { - return now - this.startOffFragment; - } - - @Override - public void updateFragments(Iterator<SimTraceFragment> newFragments, long offset) { - this.fragments = newFragments; - - // Start the first Fragment - 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 passedTime = now - this.startOffFragment; - long duration = this.currentFragment.duration(); - - // 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) { - - // Stop running - if (!this.fragments.hasNext()) { - final SimMachineContext machineContext = this.ctx; - if (machineContext != null) { - machineContext.shutdown(); - } - ctx.close(); - return Long.MAX_VALUE; - } - - passedTime = passedTime - duration; - - // get next Fragment - this.index++; - currentFragment = this.fragments.next(); - 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; - - final OutPort[] outputs = this.outputs; - - // 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); - } - - // Return the time when the current fragment will complete - return now + (duration - passedTime); - } - - @Override - public FlowStage getStage() { - return stage; - } - - @Override - public int getIndex() { - return index; - } - } } |
