From aec00c5cede503e01287dc08e4732462d3e17d31 Mon Sep 17 00:00:00 2001 From: MBaczun Date: Tue, 6 Oct 2020 21:31:55 +0100 Subject: [PATCH 1/5] Setting up build and project for examples. Updates submodules. Adds output including html file adapted from Aurora. Modifies build file to include a new project and adding 0.3.1-SNAPSHOT declaration such that the project can use this snapshot - somehow the snapshot declaration was removed somewhere along the way but I think I need it now so I'm adding it back. --- .gitmodules | 3 + build.sbt | 10 ++ .../simulator/examples/Examples.scala | 89 ++++++++++++ output/Test-timeline.html | 134 ++++++++++++++++++ output/d3-timeline | 1 + 5 files changed, 237 insertions(+) create mode 100644 examples/src/main/scala/com/workflowfm/simulator/examples/Examples.scala create mode 100644 output/Test-timeline.html create mode 160000 output/d3-timeline diff --git a/.gitmodules b/.gitmodules index e69de29b..bc951af3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "d3-timeline"] + path = output/d3-timeline + url = https://github.com/workflowfm/d3-workflow-timeline diff --git a/build.sbt b/build.sbt index 795e4814..37a0cbfe 100644 --- a/build.sbt +++ b/build.sbt @@ -1,4 +1,5 @@ ThisBuild / autoAPIMappings := true +ThisBuild / version := "0.3.1-SNAPSHOT" // Fixes some sbt import problems. // https://github.com/sbt/sbt-native-packager/issues/1063 @@ -34,3 +35,12 @@ lazy val root = (project in file(".")) commonSettings, name := "wfm-simulator" ) + +lazy val examples = (project in file("examples")) + .settings( + commonSettings, + name := "examples", + libraryDependencies += "com.workflowfm" %% "wfm-simulator" % "0.3.1-SNAPSHOT", + scalaSource in Compile := baseDirectory.value / "src", + scalaSource in Test := baseDirectory.value / "test" + ) diff --git a/examples/src/main/scala/com/workflowfm/simulator/examples/Examples.scala b/examples/src/main/scala/com/workflowfm/simulator/examples/Examples.scala new file mode 100644 index 00000000..53570168 --- /dev/null +++ b/examples/src/main/scala/com/workflowfm/simulator/examples/Examples.scala @@ -0,0 +1,89 @@ +package com.workflowfm.simulator.examples + +import akka.actor.ActorSystem +import akka.util.Timeout +import akka.pattern.ask +import scala.concurrent._ +import scala.concurrent.duration._ +import com.workflowfm.simulator._ +import com.workflowfm.simulator.metrics._ +import com.workflowfm.simulator.events.{ ShutdownHandler } +import com.workflowfm.simulator.flows._ +import uk.ac.ed.inf.ppapapan.subakka.Subscriber +import java.io.File + +object Example { + //toggle for debug + val DEBUG = false + + def main(args: Array[String]): Unit = { + + implicit val system: ActorSystem = ActorSystem("ExampleCode") + implicit val executionContext: ExecutionContext = ExecutionContext.global + implicit val timeout = Timeout(2.seconds) + + val coordinator = system.actorOf(Coordinator.props(new LookaheadScheduler())) + val shutdownActor = Subscriber.actor(new ShutdownHandler()) + + val handler = SimMetricsOutputs( + new SimMetricsPrinter(), + new SimCSVFileOutput("output" + File.separator,"example"), + new SimD3Timeline("output" + File.separator,"example") + ) + + Await.result(new SimOutputHandler(handler).subAndForgetTo(coordinator,Some("MetricsHandler")), 3.seconds) + Await.result(shutdownActor ? Subscriber.SubAndForgetTo(coordinator), 3.seconds) + + if (DEBUG) { + println(s"Cores: ${Runtime.getRuntime().availableProcessors()}") + val config = system.settings.config.getConfig("akka.actor.default-dispatcher") + println(s"Parallelism: ${config.getInt("fork-join-executor.parallelism-min")}-${config.getInt("fork-join-executor.parallelism-max")} x ${config.getDouble("fork-join-executor.parallelism-factor")}") + val printer = new com.workflowfm.simulator.events.PrintEventHandler + Await.result(printer.subAndForgetTo(coordinator), 3.seconds) + } + + //========================================================================================= + + // Define resources + val r1 = new TaskResource("r1",0) + val r2 = new TaskResource("r2",0) + val r3 = new TaskResource("r3",0) + val r4 = new TaskResource("r4",0) + val r5 = new TaskResource("r5",0) + val r6 = new TaskResource("r6",0) + val r7 = new TaskResource("r7",0) + val r8 = new TaskResource("r8",0) + val resources = List (r1,r2,r3,r4,r5,r6,r7,r8) + coordinator ! Coordinator.AddResources(resources) + + { + val task1 = FlowTask(TaskGenerator("task1", "sim", ConstantGenerator(4L), ConstantGenerator(0L)) withResources(Seq("r2"))) + val task2 = FlowTask(TaskGenerator("task2", "sim", ConstantGenerator(4L), ConstantGenerator(0L)) withResources(Seq("r1"))) + val flow = task1 > task2 + + coordinator ! Coordinator.AddSim(0L,system.actorOf(FlowLookaheadActor.props("sim",coordinator,flow))) + + } + + { + val task1 = FlowTask(TaskGenerator("task1", "sim2", ConstantGenerator(4L), ConstantGenerator(0L)) withResources(Seq("r2"))) + val task2 = FlowTask(TaskGenerator("task2", "sim2", ConstantGenerator(4L), ConstantGenerator(0L)) withResources(Seq("r1"))) + val flow = task1 + task2 + + coordinator ! Coordinator.AddSim(0L,system.actorOf(FlowLookaheadActor.props("sim2",coordinator,flow))) + //todo A>B C+D example with renaming + + } + + { + val task1 = FlowTask(TaskGenerator("task1", "sim3", ConstantGenerator(4L), ConstantGenerator(0L)) withResources(Seq("r2"))) + val task2 = FlowTask(TaskGenerator("task2", "sim3", ConstantGenerator(4L), ConstantGenerator(0L)) withResources(Seq("r1"))) + val flow = task1 | task2 + + coordinator ! Coordinator.AddSim(0L,system.actorOf(FlowLookaheadActor.props("sim3",coordinator,flow))) + + } + + coordinator ! Coordinator.Start + } +} \ No newline at end of file diff --git a/output/Test-timeline.html b/output/Test-timeline.html new file mode 100644 index 00000000..086b7a04 --- /dev/null +++ b/output/Test-timeline.html @@ -0,0 +1,134 @@ + + + + + + + WorkflowFM - Results Timeline + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/output/d3-timeline b/output/d3-timeline new file mode 160000 index 00000000..1c8c00bf --- /dev/null +++ b/output/d3-timeline @@ -0,0 +1 @@ +Subproject commit 1c8c00bf7f672e850ed268e5c025d06b0a0c9d3f From de6e61d7a8020a972cc6d0d663e335003b421437 Mon Sep 17 00:00:00 2001 From: MBaczun Date: Tue, 6 Oct 2020 23:05:05 +0100 Subject: [PATCH 2/5] Creates first examples Also adds ExampleSimulation similar to Aurora simulator --- .../examples/ExampleSimulation.scala | 49 ++++++++ .../simulator/examples/Examples.scala | 117 ++++++++++-------- output/Test-timeline.html | 2 +- 3 files changed, 113 insertions(+), 55 deletions(-) create mode 100644 examples/src/main/scala/com/workflowfm/simulator/examples/ExampleSimulation.scala diff --git a/examples/src/main/scala/com/workflowfm/simulator/examples/ExampleSimulation.scala b/examples/src/main/scala/com/workflowfm/simulator/examples/ExampleSimulation.scala new file mode 100644 index 00000000..45b002f6 --- /dev/null +++ b/examples/src/main/scala/com/workflowfm/simulator/examples/ExampleSimulation.scala @@ -0,0 +1,49 @@ +package com.workflowfm.simulator.examples + +import akka.actor.{ActorSystem, ActorRef} +import akka.util.Timeout +import akka.pattern.ask +import scala.concurrent._ +import scala.concurrent.duration._ +import com.workflowfm.simulator._ +import com.workflowfm.simulator.metrics._ +import com.workflowfm.simulator.events.{ ShutdownHandler } +import com.workflowfm.simulator.flows._ +import uk.ac.ed.inf.ppapapan.subakka.Subscriber +import java.io.File +import scala.collection.mutable + +class ExampleSimulation( + outputPath:String, + outputName:String, + resources: Seq[TaskResource] +) (implicit val system: ActorSystem, implicit val context: ExecutionContext) { + + val coordinator = system.actorOf(Coordinator.props(new LookaheadScheduler())) + + val handler = SimMetricsOutputs( + new SimMetricsPrinter(), + new SimCSVFileOutput(outputPath + File.separator,outputName), + new SimD3Timeline(outputPath + File.separator,outputName) //60*1000 + ) + + val metrics = new SimOutputHandler(handler) + + /** + * Loads the specified simulations + * */ + def load(shutdownActor: ActorRef, simulations:Seq[(Long,ActorRef)]) { + implicit val timeout = Timeout(2.seconds) + + Await.result(metrics.subAndForgetTo(coordinator, Some(s"$outputName-Metrics")), 3.seconds) + Await.result(shutdownActor ? Subscriber.SubAndForgetTo(coordinator), 3.seconds) + coordinator ! Coordinator.AddResources(resources) + simulations map { case (start,sim) => + coordinator ! Coordinator.AddSim(start, sim) + } + } + + def start() = { + coordinator ! Coordinator.Start + } +} \ No newline at end of file diff --git a/examples/src/main/scala/com/workflowfm/simulator/examples/Examples.scala b/examples/src/main/scala/com/workflowfm/simulator/examples/Examples.scala index 53570168..389578d9 100644 --- a/examples/src/main/scala/com/workflowfm/simulator/examples/Examples.scala +++ b/examples/src/main/scala/com/workflowfm/simulator/examples/Examples.scala @@ -17,73 +17,82 @@ object Example { val DEBUG = false def main(args: Array[String]): Unit = { + implicit val context: ExecutionContext = ExecutionContext.global + implicit val system: ActorSystem = ActorSystem("ExampleTests") - implicit val system: ActorSystem = ActorSystem("ExampleCode") - implicit val executionContext: ExecutionContext = ExecutionContext.global - implicit val timeout = Timeout(2.seconds) - - val coordinator = system.actorOf(Coordinator.props(new LookaheadScheduler())) val shutdownActor = Subscriber.actor(new ShutdownHandler()) - val handler = SimMetricsOutputs( - new SimMetricsPrinter(), - new SimCSVFileOutput("output" + File.separator,"example"), - new SimD3Timeline("output" + File.separator,"example") - ) - - Await.result(new SimOutputHandler(handler).subAndForgetTo(coordinator,Some("MetricsHandler")), 3.seconds) - Await.result(shutdownActor ? Subscriber.SubAndForgetTo(coordinator), 3.seconds) - - if (DEBUG) { - println(s"Cores: ${Runtime.getRuntime().availableProcessors()}") - val config = system.settings.config.getConfig("akka.actor.default-dispatcher") - println(s"Parallelism: ${config.getInt("fork-join-executor.parallelism-min")}-${config.getInt("fork-join-executor.parallelism-max")} x ${config.getDouble("fork-join-executor.parallelism-factor")}") - val printer = new com.workflowfm.simulator.events.PrintEventHandler - Await.result(printer.subAndForgetTo(coordinator), 3.seconds) - } - - //========================================================================================= + def r(name: String, cost: Int = 0): TaskResource = new TaskResource(name,cost) + def t(name: String, simulation: String, resources: Seq[String], duration: ValueGenerator[Long] = ConstantGenerator(3L), cost: ValueGenerator[Long] = ConstantGenerator(0L), priority: Task.Priority = Task.Medium): Flow = + FlowTask(TaskGenerator(name,simulation,duration,cost).withResources(resources).withPriority(priority)) - // Define resources - val r1 = new TaskResource("r1",0) - val r2 = new TaskResource("r2",0) - val r3 = new TaskResource("r3",0) - val r4 = new TaskResource("r4",0) - val r5 = new TaskResource("r5",0) - val r6 = new TaskResource("r6",0) - val r7 = new TaskResource("r7",0) - val r8 = new TaskResource("r8",0) - val resources = List (r1,r2,r3,r4,r5,r6,r7,r8) - coordinator ! Coordinator.AddResources(resources) - { - val task1 = FlowTask(TaskGenerator("task1", "sim", ConstantGenerator(4L), ConstantGenerator(0L)) withResources(Seq("r2"))) - val task2 = FlowTask(TaskGenerator("task2", "sim", ConstantGenerator(4L), ConstantGenerator(0L)) withResources(Seq("r1"))) - val flow = task1 > task2 + { + val flow = t("t1","S01",Seq("r1")) + t("t2","S01",Seq("r2")) + val resources = Seq( + r("r1"), + r("r2"), + r("r3") + ) + val simulator = new ExampleSimulation("output", "Test01", resources) - coordinator ! Coordinator.AddSim(0L,system.actorOf(FlowLookaheadActor.props("sim",coordinator,flow))) - + val sims = Seq ( + (0L, system.actorOf(FlowSimulationActor.props("S01",simulator.coordinator,flow))), + ) + + simulator.load(shutdownActor,sims) + simulator.start() } - { - val task1 = FlowTask(TaskGenerator("task1", "sim2", ConstantGenerator(4L), ConstantGenerator(0L)) withResources(Seq("r2"))) - val task2 = FlowTask(TaskGenerator("task2", "sim2", ConstantGenerator(4L), ConstantGenerator(0L)) withResources(Seq("r1"))) - val flow = task1 + task2 - - coordinator ! Coordinator.AddSim(0L,system.actorOf(FlowLookaheadActor.props("sim2",coordinator,flow))) - //todo A>B C+D example with renaming + { + val flow = t("t1","S01",Seq("r1")) > t("t2","S01",Seq("r2")) + val resources = Seq( + r("r1"), + r("r2"), + r("r3") + ) + val simulator = new ExampleSimulation("output", "Test02", resources) + + val sims = Seq ( + (0L, system.actorOf(FlowSimulationActor.props("S01",simulator.coordinator,flow))), + ) + simulator.load(shutdownActor,sims) + simulator.start() } - { - val task1 = FlowTask(TaskGenerator("task1", "sim3", ConstantGenerator(4L), ConstantGenerator(0L)) withResources(Seq("r2"))) - val task2 = FlowTask(TaskGenerator("task2", "sim3", ConstantGenerator(4L), ConstantGenerator(0L)) withResources(Seq("r1"))) - val flow = task1 | task2 - - coordinator ! Coordinator.AddSim(0L,system.actorOf(FlowLookaheadActor.props("sim3",coordinator,flow))) + { + val flow = ( t("t1","S01",Seq("r1"),priority = Task.High) > t("t2","S01",Seq("r2"),priority=Task.High) ) + t("t3","S01",Seq("r2"),duration = ConstantGenerator(5L)) + val resources = Seq( + r("r1"), + r("r2"), + r("r3") + ) + val simulator = new ExampleSimulation("output", "Test03", resources) + + val sims = Seq ( + (0L, system.actorOf(FlowSimulationActor.props("S01",simulator.coordinator,flow))), + ) + simulator.load(shutdownActor,sims) + simulator.start() } - coordinator ! Coordinator.Start + { + val flow = ( t("t1","S01",Seq("r1"),priority = Task.High) > t("t2","S01",Seq("r2"),priority=Task.High) ) + t("t3","S01",Seq("r2"),duration = ConstantGenerator(5L)) + val resources = Seq( + r("r1"), + r("r2"), + r("r3") + ) + val simulator = new ExampleSimulation("output", "Test04", resources) + + val sims = Seq ( + (0L, system.actorOf(FlowLookaheadActor.props("S01",simulator.coordinator,flow))), + ) + + simulator.load(shutdownActor,sims) + simulator.start() + } } } \ No newline at end of file diff --git a/output/Test-timeline.html b/output/Test-timeline.html index 086b7a04..477e4757 100644 --- a/output/Test-timeline.html +++ b/output/Test-timeline.html @@ -30,7 +30,7 @@ displayOne("#simulations" + name, simulationData, 40, 100); } - + From f9370b776f78b19cb572a5d03a8b0e81d4901373 Mon Sep 17 00:00:00 2001 From: MBaczun Date: Wed, 7 Oct 2020 15:11:41 +0100 Subject: [PATCH 3/5] meeting changes --- build.sbt | 6 +++--- output/Test-timeline.html | 5 +++-- .../scala/com/workflowfm/simulator/Lookahead.scala | 12 ++++++------ .../scala/com/workflowfm/simulator/Scheduler.scala | 2 +- .../scala/com/workflowfm/simulator/Simulation.scala | 2 +- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/build.sbt b/build.sbt index 37a0cbfe..5df9b8b5 100644 --- a/build.sbt +++ b/build.sbt @@ -1,5 +1,4 @@ ThisBuild / autoAPIMappings := true -ThisBuild / version := "0.3.1-SNAPSHOT" // Fixes some sbt import problems. // https://github.com/sbt/sbt-native-packager/issues/1063 @@ -40,7 +39,8 @@ lazy val examples = (project in file("examples")) .settings( commonSettings, name := "examples", - libraryDependencies += "com.workflowfm" %% "wfm-simulator" % "0.3.1-SNAPSHOT", scalaSource in Compile := baseDirectory.value / "src", scalaSource in Test := baseDirectory.value / "test" - ) + ).dependsOn(rootRef) + +lazy val rootRef = LocalProject("root") diff --git a/output/Test-timeline.html b/output/Test-timeline.html index 477e4757..9e29dcb6 100644 --- a/output/Test-timeline.html +++ b/output/Test-timeline.html @@ -24,10 +24,11 @@ // div.append("h2").text("Resources:"); // div.append("div").attr("id","resources" + name); // div.append("h2").text("Simulations:"); - div.append("div").attr("id","simulations" + name); +// div.append("div").attr("id","simulations" + name); + div.append("div").attr("id","resources" + name); // displayOne("#resources" + name, resourceData, 2, 200, 30, d3.time.minutes, d3.time.format.utc("%H:%M")); // displayOne("#simulations" + name, simulationData, 2, 200, 30, d3.time.minutes, d3.time.format.utc("%H:%M")); - displayOne("#simulations" + name, simulationData, 40, 100); + displayOne("#resources" + name, resourceData, 40, 100,); } diff --git a/src/main/scala/com/workflowfm/simulator/Lookahead.scala b/src/main/scala/com/workflowfm/simulator/Lookahead.scala index 1c8820d2..0ff3d1da 100644 --- a/src/main/scala/com/workflowfm/simulator/Lookahead.scala +++ b/src/main/scala/com/workflowfm/simulator/Lookahead.scala @@ -1,6 +1,6 @@ package com.workflowfm.simulator -import scala.collection.immutable._ +import scala.collection.immutable.{Map, Queue} import java.util.UUID import akka.actor.ActorRef @@ -48,7 +48,7 @@ trait LookaheadStructure{ * @param scheduled The list of tasks that have been scheduled/completed, described with an (ID,time) tuple * @return The list of tasks that can start, described by (TaskGenerator,starting_time) tuples */ - def getTaskData(scheduled: Seq[(UUID,Long)]): Seq[(TaskGenerator,Long)] + def getTaskData(scheduled: Iterable[(UUID,Long)]): Seq[(TaskGenerator,Long)] /** * Provides a nicer interface for adding elements to the lookeahead structure. @@ -122,7 +122,7 @@ case class LookaheadStructures(handlers: Queue[LookaheadStructure]) extends Look /** * @inheritdoc */ - override def getTaskData(scheduled: Seq[(UUID, Long)]): Seq[(TaskGenerator, Long)] = handlers flatMap (_.getTaskData(scheduled)) + override def getTaskData(scheduled: Iterable[(UUID, Long)]): Seq[(TaskGenerator, Long)] = handlers flatMap (_.getTaskData(scheduled)) /** * @inheritdoc */ @@ -173,7 +173,7 @@ case class LookaheadSet( /** * @inheritdoc */ - override def getTaskData(scheduled: Seq[(UUID, Long)]): Seq[(TaskGenerator,Long)] = { + override def getTaskData(scheduled: Iterable[(UUID, Long)]): Seq[(TaskGenerator,Long)] = { val y = lookaheadSet flatMap { x: (Map[UUID, Long] => Option[Long], Seq[TaskGenerator]) => x match { case(function, data) => @@ -184,7 +184,7 @@ case class LookaheadSet( } } } - y.to[collection.immutable.Seq] + y.toSeq } } @@ -203,5 +203,5 @@ case object EmptyStructure extends LookaheadStructure { /** * @inheritdoc */ - override def getTaskData(scheduled: Seq[(UUID, Long)]): Seq[(TaskGenerator, Long)] = Seq() + override def getTaskData(scheduled: Iterable[(UUID, Long)]): Seq[(TaskGenerator, Long)] = Seq() } \ No newline at end of file diff --git a/src/main/scala/com/workflowfm/simulator/Scheduler.scala b/src/main/scala/com/workflowfm/simulator/Scheduler.scala index 1b6d2da3..7613681d 100644 --- a/src/main/scala/com/workflowfm/simulator/Scheduler.scala +++ b/src/main/scala/com/workflowfm/simulator/Scheduler.scala @@ -625,7 +625,7 @@ class LookaheadScheduler(initialTasks: Task*) extends SortedSetScheduler { scheduled: Seq[(java.util.UUID,Long)], lookaheadStructureThisIter: LookaheadStructure ): Seq[Task] = { - val taskData = lookaheadStructureThisIter.getTaskData((scheduled++completed).to[collection.immutable.Seq]) + val taskData = lookaheadStructureThisIter.getTaskData((scheduled++completed).to[collection.immutable.Seq]) //todo remove to[] (taskData map (x=> x._1.withMinStartTime(x._2).create(x._1.createTime, actor))).toSeq //todo warning if time <= currentTime. coordinator could pass log. Logging adaptor? } diff --git a/src/main/scala/com/workflowfm/simulator/Simulation.scala b/src/main/scala/com/workflowfm/simulator/Simulation.scala index b5ffe5b0..5370507e 100644 --- a/src/main/scala/com/workflowfm/simulator/Simulation.scala +++ b/src/main/scala/com/workflowfm/simulator/Simulation.scala @@ -506,7 +506,7 @@ trait Lookahead extends Simulation { abstract override def complete(task: Task, time: Long) = { completed += ((task.id,time)) lookahead = lookahead - task.id - lookahead.getTaskData(completed.to[scala.collection.immutable.Seq]) foreach { x=> lookahead = lookahead - x._1.id } + lookahead.getTaskData(completed) foreach { x=> lookahead = lookahead - x._1.id } coordinator ! Coordinator.SetSchedulerLookaheadObject(lookahead) super.complete(task,time) } From f5892df9b1181948e5afff1ae1e9b9eb0acc9565 Mon Sep 17 00:00:00 2001 From: MBaczun Date: Thu, 8 Oct 2020 13:32:24 +0100 Subject: [PATCH 4/5] fixing build file --- build.sbt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build.sbt b/build.sbt index adf34b38..5df9b8b5 100644 --- a/build.sbt +++ b/build.sbt @@ -33,7 +33,6 @@ lazy val root = (project in file(".")) .settings( commonSettings, name := "wfm-simulator" -<<<<<<< HEAD ) lazy val examples = (project in file("examples")) @@ -45,6 +44,3 @@ lazy val examples = (project in file("examples")) ).dependsOn(rootRef) lazy val rootRef = LocalProject("root") -======= - ) ->>>>>>> lookahead/main From 36a4f9bb73704f34f7ba2a038fbfb8c0439c2667 Mon Sep 17 00:00:00 2001 From: MBaczun Date: Thu, 8 Oct 2020 14:11:48 +0100 Subject: [PATCH 5/5] Adds more examples. Adds comments to examples. --- .../simulator/examples/Examples.scala | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/examples/src/main/scala/com/workflowfm/simulator/examples/Examples.scala b/examples/src/main/scala/com/workflowfm/simulator/examples/Examples.scala index 389578d9..c6e13b5b 100644 --- a/examples/src/main/scala/com/workflowfm/simulator/examples/Examples.scala +++ b/examples/src/main/scala/com/workflowfm/simulator/examples/Examples.scala @@ -28,6 +28,9 @@ object Example { { + /* Example 1 + A basic AND of two tasks (t1 and t2 happen in parallel) + */ val flow = t("t1","S01",Seq("r1")) + t("t2","S01",Seq("r2")) val resources = Seq( r("r1"), @@ -45,6 +48,9 @@ object Example { } { + /* Example 2 + A basic THEN of two tasks (t1 and t2 happen in sequence) + */ val flow = t("t1","S01",Seq("r1")) > t("t2","S01",Seq("r2")) val resources = Seq( r("r1"), @@ -62,6 +68,12 @@ object Example { } { + /* Example 3 + A basic flow ( (t1 > t2) + t3) + t2 must happen after t1, but t3 can run in parallel to t1. + Illustrates a shortcoming of non-lookahead simulation; t2 is higher prioirty than t3, but t3 starts first anyway. + Compare this to example 4, which uses the same flow but with lookahead. + */ val flow = ( t("t1","S01",Seq("r1"),priority = Task.High) > t("t2","S01",Seq("r2"),priority=Task.High) ) + t("t3","S01",Seq("r2"),duration = ConstantGenerator(5L)) val resources = Seq( r("r1"), @@ -79,6 +91,12 @@ object Example { } { + /* Example 4 + A basic flow ( (t1 > t2) + t3) + Same flow as example 3 + Shows how, by using lookahead, higher priority tasks are executed sooner. Here t2 will run before t3 thanks to lookahead, + as opposed to what happens in example 3, where t2 runs first causing t3 to be delayed. + */ val flow = ( t("t1","S01",Seq("r1"),priority = Task.High) > t("t2","S01",Seq("r2"),priority=Task.High) ) + t("t3","S01",Seq("r2"),duration = ConstantGenerator(5L)) val resources = Seq( r("r1"), @@ -94,5 +112,120 @@ object Example { simulator.load(shutdownActor,sims) simulator.start() } + + { + /* Example 5 + The flow ( t1 > (t2>t3) + (t4>t5) ) + The two "sub assemblies" run in parallel. Since we are not using lookahead, t5 prevents + t3 from starting, which is bad since t3 has higher priority. This happens because (at the time) + t5 is not competing for resources, since t3 cannot start yet. + This should be compared with example 6. + */ + val flow = (t("t1","S01",Seq("r2"),priority = Task.High) > ( + t("t2","S01",Seq("r1"),priority = Task.High) > + t("t3","S01",Seq("r2"),priority = Task.High) ) + ( + t("t4","S01",Seq("r3"),duration = ConstantGenerator(2L)) > + t("t5","S01",Seq("r2")) ) ) + val resources = Seq( + r("r1"), + r("r2"), + r("r3") + ) + val simulator = new ExampleSimulation("output", "Test05", resources) + + val sims = Seq ( + (0L, system.actorOf(FlowSimulationActor.props("S01",simulator.coordinator,flow))), + ) + + simulator.load(shutdownActor,sims) + simulator.start() + } + + { + /* Example 6 + The flow ( t1 > (t2>t3) + (t4>t5) ) + The same flow as example 5 + Unlike example 5, task 3 starts before task 5. This illustrates that our lookahead method + also considers currently-running tasks and the future tasks of those currently-running tasks + in scheduling, and the result is that task 5 is intentionally delayed. + */ + val flow = (t("t1","S01",Seq("r2"),priority = Task.High) > ( + t("t2","S01",Seq("r1"),priority = Task.High) > + t("t3","S01",Seq("r2"),priority = Task.High) ) + ( + t("t4","S01",Seq("r3"),duration = ConstantGenerator(2L)) > + t("t5","S01",Seq("r2")) ) ) + val resources = Seq( + r("r1"), + r("r2"), + r("r3") + ) + val simulator = new ExampleSimulation("output", "Test06", resources) + + val sims = Seq ( + (0L, system.actorOf(FlowLookaheadActor.props("S01",simulator.coordinator,flow))), + ) + + simulator.load(shutdownActor,sims) + simulator.start() + } + + { + /* Example 7 + The flow ( t1 > ( ( (t2+t3+t4) > t5 ) + t6 ) ) + After t1, tasks 2, 3, 4 and 6 can all start. Once tasks 2, 3, and 4 finish, t5 can begin. + Tasks 5 and 6 are competing for the same resource, task 5 has higher priority but it needs + to wait for tasks 2,3,4 to finish, so task 6 can start sooner. + Without lookahead, t6 starts as soon as t4 finishes, and this causes t5 to be delayed. + Compare this example with example 8 + */ + val flow = (t("t1","S01",Seq("r2"),priority = Task.High) > ( ( ( + t("t2","S01",Seq("r1"),priority = Task.High, duration = ConstantGenerator(4L)) + + t("t3","S01",Seq("r2"),priority = Task.High, duration = ConstantGenerator(3L)) + + t("t4","S01",Seq("r3"),priority = Task.High, duration = ConstantGenerator(2L)) ) > + t("t5","S01",Seq("r3"),priority = Task.High) ) + + t("t6","S01",Seq("r3"),priority = Task.Low, duration = ConstantGenerator(5L)) ) ) + val resources = Seq( + r("r1"), + r("r2"), + r("r3") + ) + val simulator = new ExampleSimulation("output", "Test07", resources) + + val sims = Seq ( + (0L, system.actorOf(FlowSimulationActor.props("S01",simulator.coordinator,flow))), + ) + + simulator.load(shutdownActor,sims) + simulator.start() + } + + { + /* Example 8 + The flow ( t1 > ( ( (t2+t3+t4) > t5 ) + t6 ) ) + The same flow as in example 7 + With lookahead, the scheduler is made aware of t5 and its dependency on t2,3,4. + t5 is scheduled before t6 due to its priority (and considering the prerequisites), + and thus t6 is intentionally started later so as to not delay t5. + */ + val flow = (t("t1","S01",Seq("r2"),priority = Task.High) > ( ( ( + t("t2","S01",Seq("r1"),priority = Task.High, duration = ConstantGenerator(4L)) + + t("t3","S01",Seq("r2"),priority = Task.High, duration = ConstantGenerator(3L)) + + t("t4","S01",Seq("r3"),priority = Task.High, duration = ConstantGenerator(2L)) ) > + t("t5","S01",Seq("r3"),priority = Task.High) ) + + t("t6","S01",Seq("r3"),priority = Task.Low, duration = ConstantGenerator(5L)) ) ) + val resources = Seq( + r("r1"), + r("r2"), + r("r3") + ) + val simulator = new ExampleSimulation("output", "Test08", resources) + + val sims = Seq ( + (0L, system.actorOf(FlowLookaheadActor.props("S01",simulator.coordinator,flow))), + ) + + simulator.load(shutdownActor,sims) + simulator.start() + } } } \ No newline at end of file