Skip to content

Commit 1539d80

Browse files
authored
Compile progress (#353)
Adds an optional progressFn to Compiler, which is regularly called and updated with the overall compilation progress. Each block has some progress value, defined as the total compilation progress (0-1) completed when the block and its subtree are fully compiled. The top block's progress value is 1, and each block's progress is the parent's progress divided by the immediate number of siblings plus 1 (the extra 1 is for the parent itself - updated when the block is compiled). In practice this isn't linear, since units of work get progressively smaller, but it's probably better than nothing.
1 parent 451de23 commit 1539d80

File tree

3 files changed

+42
-20
lines changed

3 files changed

+42
-20
lines changed

compiler/src/main/scala/edg/compiler/Compiler.scala

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ object ElaborateRecord {
1919
sealed trait ElaborateDependency extends ElaborateRecord // an elaboration dependency source
2020

2121
// step 1/2 for blocks: replaces library reference blocks with the concrete block from the library
22-
case class ExpandBlock(blockPath: DesignPath, blockClass: ref.LibraryPath) extends ElaborateTask
22+
// progress defined as the amount of progress done when the block and its entire subtree are fully compiled
23+
case class ExpandBlock(blockPath: DesignPath, blockClass: ref.LibraryPath, progress: Float) extends ElaborateTask
2324
// step 2/2 for blocks, when generators are ready: processes the subtree (including connects and assigns)
24-
case class Block(blockPath: DesignPath) extends ElaborateTask
25+
case class Block(blockPath: DesignPath, progress: Float) extends ElaborateTask
2526
case class Link(linkPath: DesignPath) extends ElaborateTask
2627
case class LinkArray(linkPath: DesignPath) extends ElaborateTask
2728

@@ -132,16 +133,19 @@ class Compiler private (
132133
val library: edg.wir.Library,
133134
val refinements: Refinements,
134135
val partial: PartialCompile,
135-
initialize: Boolean
136+
initialize: Boolean,
137+
progressFn: Option[Float => Unit],
138+
var currentProgress: Float
136139
) {
137140
// public constructor that does not expose init, which is internal only
138141
def this(
139142
inputDesignPb: schema.Design,
140143
library: edg.wir.Library,
141144
refinements: Refinements = Refinements(),
142-
partial: PartialCompile = PartialCompile()
145+
partial: PartialCompile = PartialCompile(),
146+
progressFn: Option[Float => Unit] = None
143147
) = {
144-
this(inputDesignPb, library, refinements, partial, true)
148+
this(inputDesignPb, library, refinements, partial, true, progressFn, 0.0f)
145149
}
146150

147151
// Working design tree data structure
@@ -171,7 +175,7 @@ class Compiler private (
171175
constProp.addAssignEqual(path.asIndirect, source.asIndirect, DesignPath(), "path refinement", forced = true)
172176
}
173177

174-
elaboratePending.addNode(ElaborateRecord.Block(DesignPath()), Seq()) // seed with root
178+
elaboratePending.addNode(ElaborateRecord.Block(DesignPath(), 1.0f), Seq()) // seed with root
175179

176180
// this is done inside expandBlock which isn't called for the root
177181
constProp.addAssignValue(IndirectDesignPath() + IndirectStep.Name, TextValue(""), DesignPath(), "name")
@@ -198,7 +202,15 @@ class Compiler private (
198202
// Creates a new copy of this compiler including all the work done already.
199203
// Useful for design space exploration, where the non-search portions of the design have been compiled.
200204
def fork(additionalRefinements: Refinements = Refinements(), partial: PartialCompile = PartialCompile()): Compiler = {
201-
val cloned = new Compiler(inputDesignPb, library, refinements ++ additionalRefinements, partial, initialize = false)
205+
val cloned = new Compiler(
206+
inputDesignPb,
207+
library,
208+
refinements ++ additionalRefinements,
209+
partial,
210+
initialize = false,
211+
progressFn,
212+
currentProgress
213+
)
202214
cloned.root = root.cloned
203215
cloned.elaboratePending.initFrom(elaboratePending)
204216
cloned.constProp.initFrom(constProp)
@@ -549,7 +561,7 @@ class Compiler private (
549561
// a separate phase that (for generators) may be gated on additional parameters.
550562
// Handles class type refinements and adds default parameters and class-based value refinements
551563
// For the generator, this will be a skeleton block.
552-
protected def expandBlock(path: DesignPath): Unit = {
564+
protected def expandBlock(path: DesignPath, progress: Float): Unit = {
553565
val block = resolveBlock(path).asInstanceOf[wir.BlockLibrary]
554566

555567
val prerefineBlockPb = library.getBlock(block.target, block.mixins) match {
@@ -647,7 +659,7 @@ class Compiler private (
647659
}
648660
case _ => Seq()
649661
}
650-
elaboratePending.addNode(ElaborateRecord.Block(path), deps)
662+
elaboratePending.addNode(ElaborateRecord.Block(path, progress), deps)
651663
}
652664

653665
// Given a link library at some path, expand it and return the instantiated block.
@@ -754,7 +766,7 @@ class Compiler private (
754766
/** Elaborate a block, mainly processing its internal blocks, links, and connected and parameter constraints. The
755767
* block should already have had its interface (ports and parameters) expanded.
756768
*/
757-
protected def elaborateBlock(path: DesignPath): Unit = {
769+
protected def elaborateBlock(path: DesignPath, progress: Float): Unit = {
758770
val block = resolveBlock(path).asInstanceOf[wir.Block]
759771

760772
block match {
@@ -763,9 +775,16 @@ class Compiler private (
763775
}
764776

765777
// Queue up sub-trees that need elaboration - needs to be post-generate for generators
778+
val subblockProgress = progress / (block.getBlocks.size + 1)
779+
currentProgress += subblockProgress
780+
progressFn.foreach(_(currentProgress))
766781
block.getBlocks.foreach { case (innerBlockName, innerBlock) =>
767782
elaboratePending.addNode(
768-
ElaborateRecord.ExpandBlock(path + innerBlockName, innerBlock.asInstanceOf[BlockLibrary].target),
783+
ElaborateRecord.ExpandBlock(
784+
path + innerBlockName,
785+
innerBlock.asInstanceOf[BlockLibrary].target,
786+
subblockProgress
787+
),
769788
Seq()
770789
)
771790
}
@@ -1615,15 +1634,15 @@ class Compiler private (
16151634
readyList.foreach { elaborateRecord =>
16161635
try {
16171636
elaborateRecord match {
1618-
case elaborateRecord @ ElaborateRecord.ExpandBlock(blockPath, blockClass) =>
1637+
case elaborateRecord @ ElaborateRecord.ExpandBlock(blockPath, blockClass, blockProgress) =>
16191638
if (partial.blocks.contains(blockPath) || partial.classes.contains(blockClass)) {
16201639
partialCompileIgnoredRecords.add(elaborateRecord)
16211640
} else {
1622-
expandBlock(blockPath)
1641+
expandBlock(blockPath, blockProgress)
16231642
elaboratePending.setValue(elaborateRecord, None)
16241643
}
1625-
case elaborateRecord @ ElaborateRecord.Block(blockPath) =>
1626-
elaborateBlock(blockPath)
1644+
case elaborateRecord @ ElaborateRecord.Block(blockPath, blockProgress) =>
1645+
elaborateBlock(blockPath, blockProgress)
16271646
elaboratePending.setValue(elaborateRecord, None)
16281647
case elaborateRecord @ ElaborateRecord.Link(linkPath) =>
16291648
elaborateLink(linkPath)

compiler/src/main/scala/edg/compiler/CompilerError.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ object CompilerError {
2121
override def toIr: edgcompiler.ErrorRecord = {
2222
val missingStr = "missing " + missing.map(_.toString).mkString(", ")
2323
val (kind, path) = record match {
24-
case ElaborateRecord.ExpandBlock(path, _) =>
24+
case ElaborateRecord.ExpandBlock(path, _, _) =>
2525
(f"Uncompiled block, $missingStr", Some(path.asIndirect.toLocalPath))
26-
case ElaborateRecord.Block(path) => (f"Uncompiled block, $missingStr", Some(path.asIndirect.toLocalPath))
26+
case ElaborateRecord.Block(path, _) => (f"Uncompiled block, $missingStr", Some(path.asIndirect.toLocalPath))
2727
case ElaborateRecord.Link(path) => (f"Uncompiled link, $missingStr", Some(path.asIndirect.toLocalPath))
2828
case ElaborateRecord.LinkArray(path) =>
2929
(f"Uncompiled link array, $missingStr", Some(path.asIndirect.toLocalPath))

compiler/src/test/scala/edg/compiler/CompilerPartialBlockTest.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ class CompilerPartialBlockTest extends AnyFlatSpec with CompilerTestUtil {
141141
CompilerError.Unelaborated(
142142
ElaborateRecord.ExpandBlock(
143143
DesignPath() + "source" + "inner",
144-
ElemBuilder.LibraryPath("sourceBlock")
144+
ElemBuilder.LibraryPath("sourceBlock"),
145+
1.0f / 6
145146
),
146147
Set()
147148
)
@@ -160,7 +161,8 @@ class CompilerPartialBlockTest extends AnyFlatSpec with CompilerTestUtil {
160161
CompilerError.Unelaborated(
161162
ElaborateRecord.ExpandBlock(
162163
DesignPath() + "source" + "inner",
163-
ElemBuilder.LibraryPath("sourceBlock")
164+
ElemBuilder.LibraryPath("sourceBlock"),
165+
1.0f / 6
164166
),
165167
Set()
166168
)
@@ -187,7 +189,8 @@ class CompilerPartialBlockTest extends AnyFlatSpec with CompilerTestUtil {
187189
CompilerError.Unelaborated(
188190
ElaborateRecord.ExpandBlock(
189191
DesignPath() + "source" + "inner",
190-
ElemBuilder.LibraryPath("sourceBlock")
192+
ElemBuilder.LibraryPath("sourceBlock"),
193+
1.0f / 6
191194
),
192195
Set()
193196
)

0 commit comments

Comments
 (0)