summaryrefslogtreecommitdiff
path: root/opendc-simulator/opendc-simulator-compute/src/main/java
diff options
context:
space:
mode:
authorDante Niewenhuis <d.niewenhuis@hotmail.com>2024-09-16 11:29:26 +0200
committerGitHub <noreply@github.com>2024-09-16 11:29:26 +0200
commit4a010c6b9e033314a2624a0756dcdc7f17010d9d (patch)
tree70dc26e98cf8421eb5db7f62cf63d4ea2399c505 /opendc-simulator/opendc-simulator-compute/src/main/java
parent5047e4a25a0814f96852882f02c4017e1d5f81e7 (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')
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimAbstractMachine.java43
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimBareMetalMachine.java78
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMachineContext.java2
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMemory.java3
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimProcessingUnit.java4
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java4
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java8
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimHypervisor.java158
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimVirtualMachine.java50
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/Cpu.java137
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/MachineModel.java80
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/ProcessingUnit.java86
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimChainWorkload.java16
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimFlopsWorkload.java14
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimRuntimeWorkload.java14
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTrace.java155
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;
- }
- }
}