-
Notifications
You must be signed in to change notification settings - Fork 29
Implementation of several scheduling methods to improve the performance of static analyses #263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
aa8d780
0d3ba57
3edb263
3734dc6
72b54c1
e72ffbd
6ed388a
1c1d60d
8d3bcb2
e9a16fd
b67b8c9
b5369ce
15f87cd
7112bd4
b885136
a4bc582
549c800
9dd0e39
091a44b
222bd23
ac69a41
64783db
a97eef9
b581e28
e6f08b4
688ea35
ba21166
2e1f95f
fd3e6fa
93e5369
a5e777c
10ecf4f
517f288
17f8770
beaeaab
dce5ad2
88c1e7b
5d89f47
1767f13
e0a44d9
c369bbc
4d5e53a
2bb7618
9d1ad3b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -620,13 +620,12 @@ abstract class PropertyStore { | |
// Save the information about the finalization order (of properties which are | ||
// collaboratively computed). | ||
val cleanUpSubPhase = | ||
(propertyKindsComputedInThisPhase -- finalizationOrder.flatten.toSet) + AnalysisKey | ||
this.subPhaseFinalizationOrder = | ||
if (cleanUpSubPhase.isEmpty) { | ||
finalizationOrder.toArray | ||
(propertyKindsComputedInThisPhase -- finalizationOrder.flatten.toSet) | ||
this.subPhaseFinalizationOrder = (if (cleanUpSubPhase.isEmpty) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not pretty. Can it be cleaned up? At least it should be documented what it's doing. |
||
finalizationOrder.zipWithIndex.map(x => if(x._2 == 0) x._1 :+ AnalysisKey else x._1) | ||
} else { | ||
(finalizationOrder :+ cleanUpSubPhase.toList).toArray | ||
} | ||
(finalizationOrder.zipWithIndex.map(x => if(x._2 == 0) x._1 :+ AnalysisKey else x._1) :+ cleanUpSubPhase.toList) | ||
}).toArray | ||
|
||
subPhaseId = 0 | ||
hasSuppressedNotifications = suppressInterimUpdates.nonEmpty | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,6 @@ import org.scalatest.BeforeAndAfterEach | |
import org.scalatest.funspec.AnyFunSpec | ||
import org.scalatest.matchers.should.Matchers | ||
import org.scalatestplus.junit.JUnitRunner | ||
|
||
import org.opalj.fpcf.fixtures.PropertyStoreConfigurationRecorder | ||
import org.opalj.log.GlobalLogContext | ||
|
||
|
@@ -34,8 +33,8 @@ class PropertyComputationsSchedulerTest extends AnyFunSpec with Matchers with Be | |
override def uses(ps: PropertyStore): Set[PropertyBounds] = uses | ||
} | ||
|
||
val pks: Array[PropertyKind] = new Array[PropertyKind](12) | ||
(0 to 11).foreach { i => pks(i) = PropertyKey.create[Null, Null]("p" + (i)) } | ||
val pks: Array[PropertyKind] = new Array[PropertyKind](21) | ||
(0 to 20).foreach { i => pks(i) = PropertyKey.create[Null, Null]("p" + (i)) } | ||
|
||
val c1 = BasicComputationSpecification( | ||
"c1", | ||
|
@@ -44,6 +43,114 @@ class PropertyComputationsSchedulerTest extends AnyFunSpec with Matchers with Be | |
derivesEagerly = Set(PropertyBounds.lub(pks(1))) | ||
) | ||
|
||
def analysis1IsScheduledBeforeOrAtTheSameBatchAsAnalysis2( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What are these methods for? They don't seem to be used |
||
schedule: Schedule[Unit], | ||
analysis1: BasicComputationSpecification, | ||
analysis2: BasicComputationSpecification | ||
): Unit = { | ||
var analysis1AlreadyComputed = false | ||
var analysis1phase = 0 | ||
schedule.batches.foreach { batch => | ||
if (batch.scheduled.contains(analysis1)) { | ||
if (!analysis1AlreadyComputed) { | ||
analysis1AlreadyComputed = true | ||
} | ||
} else if (!analysis1AlreadyComputed) { | ||
analysis1phase += 1 | ||
} | ||
} | ||
|
||
var analysis2AlreadyComputed = false | ||
var analysis2phase = 0 | ||
schedule.batches.foreach { batch => | ||
if (batch.scheduled.contains(analysis2)) { | ||
if (!analysis2AlreadyComputed) { | ||
analysis2AlreadyComputed = true | ||
} | ||
} else if (!analysis2AlreadyComputed) { | ||
analysis2phase += 1 | ||
} | ||
} | ||
|
||
if (analysis1phase <= analysis2phase) { | ||
println("Success") | ||
} else { | ||
fail(s"$analysis1 is not scheduled before or in the same batch as $analysis2!") | ||
} | ||
} | ||
|
||
def analysis1IsScheduledBeforeAnalysis2( | ||
schedule: Schedule[Unit], | ||
analysis1: BasicComputationSpecification, | ||
analysis2: BasicComputationSpecification | ||
): Unit = { | ||
var analysis1AlreadyComputed = false | ||
var analysis1phase = 0 | ||
schedule.batches.foreach { batch => | ||
if (batch.scheduled.contains(analysis1)) { | ||
if (!analysis1AlreadyComputed) { | ||
analysis1AlreadyComputed = true | ||
} | ||
} else if (!analysis1AlreadyComputed) { | ||
analysis1phase += 1 | ||
} | ||
} | ||
|
||
var analysis2AlreadyComputed = false | ||
var analysis2phase = 0 | ||
schedule.batches.foreach { batch => | ||
if (batch.scheduled.contains(analysis2)) { | ||
if (!analysis2AlreadyComputed) { | ||
analysis2AlreadyComputed = true | ||
} | ||
} else if (!analysis2AlreadyComputed) { | ||
analysis2phase += 1 | ||
} | ||
} | ||
|
||
if (analysis1phase < analysis2phase) { | ||
println("Success") | ||
} else { | ||
fail(s"$analysis1 is not scheduled before $analysis2!") | ||
} | ||
} | ||
|
||
def analysis1IsScheduledInTheSameBatchAsAnalysis2( | ||
schedule: Schedule[Unit], | ||
analysis1: BasicComputationSpecification, | ||
analysis2: BasicComputationSpecification | ||
): Unit = { | ||
var analysis1AlreadyComputed = false | ||
var analysis1phase = 0 | ||
schedule.batches.foreach { batch => | ||
if (batch.scheduled.contains(analysis1)) { | ||
if (!analysis1AlreadyComputed) { | ||
analysis1AlreadyComputed = true | ||
} | ||
} else if (!analysis1AlreadyComputed) { | ||
analysis1phase += 1 | ||
} | ||
} | ||
|
||
var analysis2AlreadyComputed = false | ||
var analysis2phase = 0 | ||
schedule.batches.foreach { batch => | ||
if (batch.scheduled.contains(analysis2)) { | ||
if (!analysis2AlreadyComputed) { | ||
analysis2AlreadyComputed = true | ||
} | ||
} else if (!analysis2AlreadyComputed) { | ||
analysis2phase += 1 | ||
} | ||
} | ||
|
||
if (analysis1phase == analysis2phase) { | ||
println("Success") | ||
} else { | ||
fail(s"$analysis1 is not scheduled in the same batch as $analysis2!") | ||
} | ||
} | ||
|
||
// ********************************************************************************************** | ||
// | ||
// TESTS | ||
|
@@ -68,6 +175,94 @@ class PropertyComputationsSchedulerTest extends AnyFunSpec with Matchers with Be | |
ps.phaseConfigurations.head should be((Set.empty, Set.empty, Map.empty)) | ||
} | ||
|
||
it("an mixed analysis scenario") { | ||
val lazy1 = BasicComputationSpecification( | ||
"lazy1", | ||
LazyComputation, | ||
derivesLazily = Option(PropertyBounds.lub(pks(10))) | ||
) | ||
val eager1 = BasicComputationSpecification( | ||
"eager1", | ||
EagerComputation, | ||
derivesEagerly = Set(PropertyBounds.lub(pks(1))), | ||
uses = Set(PropertyBounds.lub(pks(10))) | ||
) | ||
val eager4 = BasicComputationSpecification( | ||
"eager4", | ||
EagerComputation, | ||
derivesCollaboratively = Set(PropertyBounds.lub(pks(13))), | ||
uses = Set(PropertyBounds.lub(pks(1))) | ||
) | ||
val transformer1 = | ||
BasicComputationSpecification( | ||
"transformer1", | ||
Transformer, | ||
derivesLazily = Option(PropertyBounds.lub(pks(7))), | ||
uses = Set(PropertyBounds.finalP(pks(1))) | ||
) | ||
val eager5 = BasicComputationSpecification( | ||
"eager5", | ||
EagerComputation, | ||
derivesCollaboratively = Set(PropertyBounds.lub(pks(13))), | ||
uses = Set(PropertyBounds.lub(pks(7))) | ||
) | ||
val eager6 = BasicComputationSpecification( | ||
"eager6", | ||
EagerComputation, | ||
derivesCollaboratively = Set(PropertyBounds.lub(pks(13))) | ||
) | ||
val lazy2 = BasicComputationSpecification( | ||
"lazy2", | ||
LazyComputation, | ||
derivesLazily = Option(PropertyBounds.lub(pks(11))), | ||
uses = Set(PropertyBounds.lub(pks(13))) | ||
) | ||
val lazy3 = BasicComputationSpecification( | ||
"lazy3", | ||
LazyComputation, | ||
derivesLazily = Option(PropertyBounds.lub(pks(12))), | ||
uses = Set(PropertyBounds.lub(pks(13))) | ||
) | ||
val eager2 = BasicComputationSpecification( | ||
"eager2", | ||
EagerComputation, | ||
derivesEagerly = Set(PropertyBounds.lub(pks(2))), | ||
uses = Set(PropertyBounds.lub(pks(12))) | ||
) | ||
val eager3 = BasicComputationSpecification( | ||
"eager3", | ||
EagerComputation, | ||
derivesEagerly = Set(PropertyBounds.lub(pks(3))), | ||
uses = Set(PropertyBounds.lub(pks(13))) | ||
) | ||
val triggered1 = | ||
BasicComputationSpecification( | ||
"triggered1", | ||
TriggeredComputation, | ||
derivesEagerly = Set(PropertyBounds.lub(pks(4))), | ||
uses = Set(PropertyBounds.lub(pks(3)), PropertyBounds.lub(pks(6))) | ||
) | ||
val triggered2 = | ||
BasicComputationSpecification( | ||
"triggered2", | ||
TriggeredComputation, | ||
derivesEagerly = Set(PropertyBounds.lub(pks(5))), | ||
uses = Set(PropertyBounds.lub(pks(4))) | ||
) | ||
val triggered3 = | ||
BasicComputationSpecification( | ||
"triggered3", | ||
TriggeredComputation, | ||
derivesEagerly = Set(PropertyBounds.lub(pks(6))), | ||
uses = Set(PropertyBounds.lub(pks(5))) | ||
) | ||
|
||
val ps = new PropertyStoreConfigurationRecorder() | ||
val scenario = AnalysisScenario(Set(eager1, eager3, eager4, eager5, eager6, eager2, lazy1, lazy2, lazy3, transformer1, triggered1, triggered2, triggered3), ps) | ||
val schedule = scenario.computeSchedule(ps) | ||
|
||
print(schedule.batches) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't a test if it just prints stuff |
||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please revert this change