diff options
12 files changed, 72 insertions, 32 deletions
diff --git a/frontend/src/components/app/map/MapConstants.js b/frontend/src/components/app/map/MapConstants.js index 0a970701..d6ea1f84 100644 --- a/frontend/src/components/app/map/MapConstants.js +++ b/frontend/src/components/app/map/MapConstants.js @@ -23,6 +23,6 @@ export const MAP_SCALE_PER_EVENT = 1.1 export const MAP_MIN_SCALE = 0.5 export const MAP_MAX_SCALE = 1.5 -export const MAX_NUM_UNITS_PER_MACHINE = 4 +export const MAX_NUM_UNITS_PER_MACHINE = 6 export const DEFAULT_RACK_SLOT_CAPACITY = 42 export const DEFAULT_RACK_POWER_CAPACITY = 10000 diff --git a/frontend/src/components/app/sidebars/topology/machine/MachineSidebarComponent.js b/frontend/src/components/app/sidebars/topology/machine/MachineSidebarComponent.js index 02e7b8d4..7c78cf9e 100644 --- a/frontend/src/components/app/sidebars/topology/machine/MachineSidebarComponent.js +++ b/frontend/src/components/app/sidebars/topology/machine/MachineSidebarComponent.js @@ -6,7 +6,7 @@ import UnitTabsContainer from '../../../../../containers/app/sidebars/topology/m const MachineSidebarComponent = ({ machineId }) => { return ( - <div> + <div className="h-100 overflow-auto"> <MachineNameContainer /> <BackToRackContainer /> <DeleteMachineContainer /> diff --git a/frontend/src/components/app/sidebars/topology/machine/UnitAddComponent.js b/frontend/src/components/app/sidebars/topology/machine/UnitAddComponent.js index d5ecbce3..4e9dbc7e 100644 --- a/frontend/src/components/app/sidebars/topology/machine/UnitAddComponent.js +++ b/frontend/src/components/app/sidebars/topology/machine/UnitAddComponent.js @@ -11,7 +11,7 @@ class UnitAddComponent extends React.Component { return ( <div className="form-inline"> <div className="form-group w-100"> - <select className="form-control w-75 mr-1" ref={(unitSelect) => (this.unitSelect = unitSelect)}> + <select className="form-control w-70 mr-1" ref={(unitSelect) => (this.unitSelect = unitSelect)}> {this.props.units.map((unit) => ( <option value={unit._id} key={unit._id}> {unit.name} diff --git a/frontend/src/components/app/sidebars/topology/machine/UnitTabsComponent.js b/frontend/src/components/app/sidebars/topology/machine/UnitTabsComponent.js index 15c89ed5..c03b826f 100644 --- a/frontend/src/components/app/sidebars/topology/machine/UnitTabsComponent.js +++ b/frontend/src/components/app/sidebars/topology/machine/UnitTabsComponent.js @@ -22,7 +22,7 @@ const UnitTabsComponent = () => ( </li> <li className="nav-item"> <a className="nav-link" data-toggle="tab" href="#storage-units" role="tab"> - Storage + Stor. </a> </li> </ul> diff --git a/frontend/src/components/modals/custom-components/NewTopologyModalComponent.js b/frontend/src/components/modals/custom-components/NewTopologyModalComponent.js index a244b730..d8262baa 100644 --- a/frontend/src/components/modals/custom-components/NewTopologyModalComponent.js +++ b/frontend/src/components/modals/custom-components/NewTopologyModalComponent.js @@ -64,7 +64,7 @@ class NewTopologyModalComponent extends React.Component { /> </div> <div className="form-group"> - <label className="form-control-label">Topology to duplicate (not supported yet)</label> + <label className="form-control-label">Topology to duplicate</label> <select className="form-control" ref={(originTopology) => (this.originTopology = originTopology)} diff --git a/frontend/src/containers/app/sidebars/project/TopologyListContainer.js b/frontend/src/containers/app/sidebars/project/TopologyListContainer.js index f65982ef..e1de18f9 100644 --- a/frontend/src/containers/app/sidebars/project/TopologyListContainer.js +++ b/frontend/src/containers/app/sidebars/project/TopologyListContainer.js @@ -4,7 +4,7 @@ import { setCurrentTopology } from '../../../../actions/topology/building' import { openNewTopologyModal } from '../../../../actions/modals/topology' import { withRouter } from 'react-router-dom' import { getState } from '../../../../util/state-utils' -import { deleteScenario } from '../../../../actions/scenarios' +import { deleteTopology } from '../../../../actions/topologies' const mapStateToProps = (state) => { let topologies = state.objects.project[state.currentProjectId] @@ -33,7 +33,7 @@ const mapDispatchToProps = (dispatch, ownProps) => { onDeleteTopology: async (id) => { if (id) { const state = await getState(dispatch) - dispatch(deleteScenario(id)) + dispatch(deleteTopology(id)) dispatch(setCurrentTopology(state.objects.project[state.currentProjectId].topologyIds[0])) ownProps.history.push(`/projects/${state.currentProjectId}`) } diff --git a/frontend/src/index.sass b/frontend/src/index.sass index ec756bc5..77acc23a 100644 --- a/frontend/src/index.sass +++ b/frontend/src/index.sass @@ -42,3 +42,6 @@ a, a:hover .app-page-container padding-left: $side-bar-width padding-top: 15px + +.w-70 + width: 70% !important diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/PerformanceInterferenceModel.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/PerformanceInterferenceModel.kt index f458877b..3f885f89 100644 --- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/PerformanceInterferenceModel.kt +++ b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/PerformanceInterferenceModel.kt @@ -25,8 +25,7 @@ package com.atlarge.opendc.compute.core.workload import com.atlarge.opendc.compute.core.Server -import java.util.SortedSet -import java.util.TreeSet +import java.util.* import kotlin.random.Random /** @@ -44,23 +43,22 @@ class PerformanceInterferenceModel( val random: Random = Random(0) ) { private var intersectingItems: List<PerformanceInterferenceModelItem> = emptyList() - private val colocatedWorkloads = TreeSet<String>() + private val colocatedWorkloads = TreeMap<String, Int>() fun vmStarted(server: Server) { - colocatedWorkloads.add(server.image.name) + colocatedWorkloads.merge(server.image.name, 1, Int::plus) intersectingItems = items.filter { item -> doesMatch(item) } } fun vmStopped(server: Server) { - colocatedWorkloads.remove(server.image.name) + colocatedWorkloads.computeIfPresent(server.image.name) { _, v -> (v - 1).takeUnless { it == 0 } } intersectingItems = items.filter { item -> doesMatch(item) } } private fun doesMatch(item: PerformanceInterferenceModelItem): Boolean { var count = 0 - for (name in item.workloadNames.subSet(colocatedWorkloads.first(), colocatedWorkloads.last() + "\u0000")) { - if (name in colocatedWorkloads) - count++ + for (name in item.workloadNames.subSet(colocatedWorkloads.firstKey(), colocatedWorkloads.lastKey() + "\u0000")) { + count += colocatedWorkloads.getOrDefault(name, 0) if (count > 1) return true } diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Portfolios.kt b/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Portfolios.kt index b8dfb1be..09a6ce40 100644 --- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Portfolios.kt +++ b/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Portfolios.kt @@ -203,6 +203,7 @@ public class MoreHpcPortfolio(parent: Experiment, id: Int) : Portfolio(parent, i ) override val workloads = listOf( + Workload("solvinity", 0.0, samplingStrategy = SamplingStrategy.HPC), Workload("solvinity", 0.25, samplingStrategy = SamplingStrategy.HPC), Workload("solvinity", 0.5, samplingStrategy = SamplingStrategy.HPC), Workload("solvinity", 1.0, samplingStrategy = SamplingStrategy.HPC), diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetRunEventWriter.kt b/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetRunEventWriter.kt index c1724369..043e4670 100644 --- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetRunEventWriter.kt +++ b/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetRunEventWriter.kt @@ -51,6 +51,7 @@ public class ParquetRunEventWriter(path: File, bufferSize: Int) : record.put("topology", scenario.topology.name) record.put("workload_name", scenario.workload.name) record.put("workload_fraction", scenario.workload.fraction) + record.put("workload_sampler", scenario.workload.samplingStrategy) record.put("allocation_policy", scenario.allocationPolicy) record.put("failure_frequency", scenario.operationalPhenomena.failureFrequency) record.put("interference", scenario.operationalPhenomena.hasInterference) @@ -69,6 +70,7 @@ public class ParquetRunEventWriter(path: File, bufferSize: Int) : .name("topology").type().stringType().noDefault() .name("workload_name").type().stringType().noDefault() .name("workload_fraction").type().doubleType().noDefault() + .name("workload_sampler").type().stringType().noDefault() .name("allocation_policy").type().stringType().noDefault() .name("failure_frequency").type().doubleType().noDefault() .name("interference").type().booleanType().noDefault() diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/WorkloadSampler.kt b/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/WorkloadSampler.kt index b24d6de1..a46bb3e6 100644 --- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/WorkloadSampler.kt +++ b/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/WorkloadSampler.kt @@ -109,6 +109,24 @@ fun sampleHpcWorkload( name.matches(pattern) } + val hpcSequence = generateSequence(0) { it + 1 } + .map { index -> + val res = mutableListOf<TraceEntry<VmWorkload>>() + hpc.mapTo(res) { sample(it, index) } + res.shuffle(random) + res + } + .flatten() + + val nonHpcSequence = generateSequence(0) { it + 1 } + .map { index -> + val res = mutableListOf<TraceEntry<VmWorkload>>() + nonHpc.mapTo(res) { sample(it, index) } + res.shuffle(random) + res + } + .flatten() + logger.debug { "Found ${hpc.size} HPC workloads and ${nonHpc.size} non-HPC workloads" } val totalLoad = if (workload is CompositeWorkload) { @@ -117,45 +135,60 @@ fun sampleHpcWorkload( trace.sumByDouble { it.workload.image.tags.getValue("total-load") as Double } } + logger.debug { "Total trace load: $totalLoad" } + var hpcCount = 0 + var hpcLoad = 0.0 + var nonHpcCount = 0 + var nonHpcLoad = 0.0 + val res = mutableListOf<TraceEntry<VmWorkload>>() if (sampleOnLoad) { var currentLoad = 0.0 var i = 0 - while (true) { - // Sample random HPC entry with replacement - val entry = sample(hpc.random(random), i++) - + for (entry in hpcSequence) { val entryLoad = entry.workload.image.tags.getValue("total-load") as Double - if ((currentLoad + entryLoad) / totalLoad > fraction || res.size > trace.size) { + if ((currentLoad + entryLoad) / totalLoad > fraction) { break } + hpcLoad += entryLoad + hpcCount += 1 currentLoad += entryLoad res += entry } - (nonHpc as MutableList<TraceEntry<VmWorkload>>).shuffle(random) - for (entry in nonHpc) { + for (entry in nonHpcSequence) { val entryLoad = entry.workload.image.tags.getValue("total-load") as Double - if ((currentLoad + entryLoad) / totalLoad > 1 || res.size > trace.size) { + if ((currentLoad + entryLoad) / totalLoad > 1) { break } + nonHpcLoad += entryLoad + nonHpcCount += 1 currentLoad += entryLoad res += entry } } else { - repeat((fraction * trace.size).toInt()) { i -> - // Sample random HPC entry with replacement - val entry = sample(hpc.random(random), i) - res.add(entry) - } + hpcSequence + .take((fraction * trace.size).toInt()) + .forEach { entry -> + hpcLoad += entry.workload.image.tags.getValue("total-load") as Double + hpcCount += 1 + res.add(entry) + } - (nonHpc as MutableList<TraceEntry<VmWorkload>>).shuffle(random) - res.addAll(nonHpc.subList(0, ((1 - fraction) * trace.size).toInt())) + nonHpcSequence + .take(((1 - fraction) * trace.size).toInt()) + .forEach { entry -> + nonHpcLoad += entry.workload.image.tags.getValue("total-load") as Double + nonHpcCount += 1 + res.add(entry) + } } + logger.debug { "HPC $hpcCount (load $hpcLoad) and non-HPC $nonHpcCount (load $nonHpcLoad)" } + logger.debug { "Total sampled load: ${hpcLoad + nonHpcLoad}" } logger.info { "Sampled ${trace.size} VMs (fraction $fraction) into subset of ${res.size} VMs" } return res @@ -168,13 +201,13 @@ private fun sample(entry: TraceEntry<VmWorkload>, i: Int): TraceEntry<VmWorkload val id = UUID.nameUUIDFromBytes("${entry.workload.image.uid}-$i".toByteArray()) val image = VmImage( id, - entry.workload.image.name + "-$i", + entry.workload.image.name, entry.workload.image.tags, entry.workload.image.flopsHistory, entry.workload.image.maxCores, entry.workload.image.requiredMemory ) - val vmWorkload = entry.workload.copy(uid = id, image = image, name = entry.workload.name + "-$i") + val vmWorkload = entry.workload.copy(uid = id, image = image, name = entry.workload.name) return VmTraceEntry(vmWorkload, entry.submissionTime) } diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/resources/log4j2.xml b/simulator/opendc/opendc-experiments-sc20/src/main/resources/log4j2.xml index f47a6da8..6906bfc3 100644 --- a/simulator/opendc/opendc-experiments-sc20/src/main/resources/log4j2.xml +++ b/simulator/opendc/opendc-experiments-sc20/src/main/resources/log4j2.xml @@ -39,6 +39,9 @@ <Logger name="com.atlarge.opendc.experiments.sc20" level="info" additivity="false"> <AppenderRef ref="Console"/> </Logger> + <Logger name="com.atlarge.opendc.experiments.sc20.trace" level="debug" additivity="false"> + <AppenderRef ref="Console"/> + </Logger> <Logger name="org.apache.hadoop" level="warn" additivity="false"> <AppenderRef ref="Console"/> </Logger> |
