Skip to content

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

Open
wants to merge 68 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
aa8d780
Fixing Error with "EagerFieldAccessInformationAnalysis", so the analy…
19Vik19 Sep 5, 2024
0d3ba57
Next Attempt
19Vik19 Sep 8, 2024
3edb263
Revert "Next Attempt"
19Vik19 Sep 8, 2024
3734dc6
Bereit für nächsten Versuch mit graph und zyklen finden ...
19Vik19 Oct 27, 2024
72b54c1
First completed approach
19Vik19 Dec 2, 2024
e72ffbd
Alle Strategien bis auf strategie 3
19Vik19 Dec 12, 2024
6ed388a
Strategie 3 funktioniert, tests wurden in PropertyComputationsSchedul…
19Vik19 Dec 20, 2024
1c1d60d
.
19Vik19 Dec 23, 2024
8d3bcb2
Merge branch '02122024' into lastbranch2024
19Vik19 Dec 23, 2024
e9a16fd
Fieldimmutability dependencies fix
19Vik19 Dec 23, 2024
b67b8c9
Immutability fix after merge
19Vik19 Dec 24, 2024
b5369ce
xcorpus runner
19Vik19 Dec 30, 2024
15f87cd
Neues Jahr neues Glück :)
19Vik19 Jan 1, 2025
7112bd4
constructor CallGraph in class CallGraph is not private anymore. For …
19Vik19 Jan 17, 2025
b885136
Prepared for testing strategie 3 true
19Vik19 Jan 18, 2025
a4bc582
Last Check
19Vik19 Jan 18, 2025
549c800
Small rollbacks
19Vik19 Jan 18, 2025
9dd0e39
Merge branch 'develop' into AUFGERÄUMT&GEUPDATED190125
19Vik19 Jan 19, 2025
091a44b
Minor changes, cleanup
19Vik19 Jan 19, 2025
222bd23
Cleanup
19Vik19 Jan 19, 2025
ac69a41
Cleanup
19Vik19 Jan 19, 2025
64783db
Documentation config
19Vik19 Jan 19, 2025
a97eef9
Bug fixes
19Vik19 Jan 20, 2025
b581e28
Cleanup and config with string-based strategy
19Vik19 Jan 20, 2025
e6f08b4
Created new Runner for immutability and Purity to schedule all analys…
19Vik19 Jan 20, 2025
688ea35
Cleanup
19Vik19 Jan 21, 2025
ba21166
Merge branch 'AUFGERÄUMT&GEUPDATED190125' into Preparation_for_the_me…
19Vik19 Jan 21, 2025
2e1f95f
Cleanup
19Vik19 Jan 21, 2025
fd3e6fa
Documentation
19Vik19 Jan 21, 2025
93e5369
Implementation of an extra check to prevent a NullPointerException fo…
19Vik19 Jan 21, 2025
a5e777c
Changed Config option “fpcf.AnalysisScenario.ScheduleStrategy” to Cla…
19Vik19 Jan 21, 2025
10ecf4f
Added config for measurement (ImmutabilityRunner - MPS - true)
19Vik19 Jan 21, 2025
517f288
Improvements
19Vik19 Jan 21, 2025
17f8770
SPS Scheduling Problem - Debugging branch
19Vik19 Feb 1, 2025
beaeaab
Formatting
Feb 3, 2025
dce5ad2
Formating
19Vik19 Feb 26, 2025
88c1e7b
Merge branch 'develop' into afterBA
19Vik19 Feb 26, 2025
5d89f47
Formatting
19Vik19 Mar 11, 2025
1767f13
Formatting
19Vik19 Mar 22, 2025
e0a44d9
Improvements, OPAL-standard config implementation
19Vik19 Mar 23, 2025
c369bbc
Minor improvements
19Vik19 Mar 23, 2025
4d5e53a
Added code documentation. Small fixes
19Vik19 Mar 23, 2025
2bb7618
reset test cases
19Vik19 Apr 18, 2025
9d1ad3b
.
19Vik19 May 6, 2025
62e5b39
Cleanup for PR
19Vik19 Jun 6, 2025
c33391e
Merge branch 'develop' of https://github.com/19Vik19/opal_bachelorarb…
19Vik19 Jun 6, 2025
40cdb64
Formatting, implementation SchdulingStrategy
19Vik19 Jun 9, 2025
b151a8f
Refactor: Remove unnecessary value declaration, enhance test implemen…
19Vik19 Jun 9, 2025
34a4e17
headerCheck
19Vik19 Jun 9, 2025
5f5c407
Merge branch 'develop' into scheduling-strategies
Jul 9, 2025
9185cca
Merge branch 'feature/format-check' into scheduling-strategies
Jul 9, 2025
011fed8
Add FIXME for subphase finalization order
Jul 9, 2025
caca611
Fix wrong package declarations and imports
Jul 9, 2025
352a653
Fix Scaladoc for scheduling strategies
Jul 9, 2025
63f1e46
Factor out topologicalSort
Jul 9, 2025
f078658
Remove spurious inheritance
Jul 9, 2025
89f3a5d
Factor out common code
Jul 9, 2025
5549e7b
Load scheduling strategy reflectively
Jul 9, 2025
eb74518
Improve PropertyComputationsSchedulerTest
Jul 9, 2025
80cf414
Improve AnalysisScenario config
Jul 11, 2025
606a5ec
Improve phase merging
Jul 11, 2025
8b29482
Fix typos in test
Jul 11, 2025
b362105
Fix test
Jul 11, 2025
62a94a3
Improve scheduling strategies
Jul 14, 2025
9403a91
Re-apply dependency management fix
Jul 14, 2025
84dec72
Set default scheduling strategy to MaximumPhaseScheduling
Jul 16, 2025
a09160e
Adapt runners to not pre-compute call graph
Jul 16, 2025
89fec75
Merge branch 'develop' into develop
errt Jul 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org
package opalj
package org.opalj
package fpcf
package analyses

Expand All @@ -19,10 +18,6 @@ import org.opalj.br.fpcf.properties.immutability.MutableType
import org.opalj.br.fpcf.properties.immutability.NonTransitivelyImmutableType
import org.opalj.br.fpcf.properties.immutability.TransitivelyImmutableType
import org.opalj.br.fpcf.properties.immutability.TypeImmutability
import org.opalj.fpcf.Entity
import org.opalj.fpcf.EPS
import org.opalj.fpcf.FPCFAnalysesManagerKey
import org.opalj.fpcf.PropertyStore
import org.opalj.tac.cg.RTACallGraphKey
import org.opalj.tac.fpcf.analyses.LazyFieldImmutabilityAnalysis
import org.opalj.tac.fpcf.analyses.LazyFieldLocalityAnalysis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ object Immutability {

var projectTime: Seconds = Seconds.None
var analysisTime: Seconds = Seconds.None
val callGraphTime: Seconds = Seconds.None

val project = time {
Project(
Expand Down Expand Up @@ -182,11 +181,13 @@ object Immutability {
val propertyStore = project.get(PropertyStoreKey)
val analysesManager = project.get(FPCFAnalysesManagerKey)

project.get(callgraphKey)
callgraphKey.requirements(project)

val allDependencies = dependencies ++ callgraphKey.allCallGraphAnalyses(project)

time {
analysesManager.runAll(
dependencies,
allDependencies,
{
(css: List[ComputationSpecification[FPCFAnalysis]]) =>
analysis match {
Expand Down Expand Up @@ -571,15 +572,14 @@ object Immutability {
|""".stripMargin
)

val totalTime = projectTime + callGraphTime + analysisTime
val totalTime = projectTime + analysisTime

stringBuilderNumber.append(
s"""
| running ${analysis.toString} analysis
| took:
| $totalTime seconds total time
| $projectTime seconds project time
| $callGraphTime seconds callgraph time
| $analysisTime seconds analysis time
|""".stripMargin
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,12 @@ import org.opalj.br.fpcf.properties.ImpureByAnalysis
import org.opalj.br.fpcf.properties.ImpureByLackOfInformation
import org.opalj.br.fpcf.properties.Pure
import org.opalj.br.fpcf.properties.SideEffectFree
import org.opalj.br.fpcf.properties.cg.Callers
import org.opalj.br.fpcf.properties.cg.NoCallers
import org.opalj.bytecode.JRELibraryFolder
import org.opalj.collection.immutable.IntTrieSet
import org.opalj.fpcf.ComputationSpecification
import org.opalj.fpcf.FinalEP
import org.opalj.fpcf.FinalP
import org.opalj.fpcf.FPCFAnalysesManagerKey
import org.opalj.fpcf.FPCFAnalysis
import org.opalj.fpcf.FPCFAnalysisScheduler
import org.opalj.fpcf.FPCFLazyAnalysisScheduler
import org.opalj.fpcf.PropertyStore
Expand Down Expand Up @@ -174,7 +171,6 @@ object Purity {
var projectTime: Seconds = Seconds.None
var propertyStoreTime: Seconds = Seconds.None
var analysisTime: Seconds = Seconds.None
var callGraphTime: Seconds = Seconds.None

// TODO: use variables for the constants
implicit var config: Config =
Expand Down Expand Up @@ -251,24 +247,18 @@ object Purity {

val manager = project.get(FPCFAnalysesManagerKey)

time {
project.get(callGraphKey)
} { t => callGraphTime = t.toSeconds }
callGraphKey.requirements(project)

val reachableMethods =
ps.entities(Callers.key).collect {
case FinalEP(m: DeclaredMethod, c: Callers) if c ne NoCallers => m
}.toSet
val allAnalyses = analysis :: support ++ callGraphKey.allCallGraphAnalyses(project)

val contextProvider = project.get(ContextProviderKey)
val analyzedContexts = projMethods.filter(reachableMethods.contains).map(contextProvider.newContext(_))
val projectMethods: Set[DeclaredMethod] = declaredMethods.declaredMethods.toSet
val analyzedContexts = projMethods.filter(projectMethods.contains).map(contextProvider.newContext(_))

time {
val analyses = analysis :: support

manager.runAll(
analyses,
(css: List[ComputationSpecification[FPCFAnalysis]]) =>
allAnalyses,
(css: List[ComputationSpecification[org.opalj.fpcf.FPCFAnalysis]]) =>
if (css.contains(analysis)) {
analyzedContexts.foreach { dm => ps.force(dm, br.fpcf.properties.Purity.key) }
}
Expand Down Expand Up @@ -340,8 +330,8 @@ object Purity {
if (newFile) {
output.createNewFile()
outputWriter.println(
"analysisName;project time;propertyStore time;" +
"callGraph time;analysis time; total time;" +
"analysisName;project time;" +
"propertyStore time;analysis time; total time;" +
"compile time pure;pure;domain-specific pure;" +
"side-effect free;domain-specific side-effect free;" +
"externally pure;domain-specific externally pure;" +
Expand All @@ -351,11 +341,10 @@ object Purity {
"side-effect free;impure;count"
)
}
val totalTime = projectTime + propertyStoreTime + callGraphTime + analysisTime
val totalTime = projectTime + propertyStoreTime + analysisTime
outputWriter.println(
s"${configurationName.get};${projectTime.toString(false)};" +
s"${propertyStoreTime.toString(false)};" +
s"${callGraphTime.toString(false)};" +
s"${analysisTime.toString(false)};" +
s"${totalTime.toString(false)};" +
s"${compileTimePure.size};${pure.size};${dPure.size};" +
Expand Down Expand Up @@ -473,7 +462,6 @@ object Purity {
"\nImpure: " + lbImpure.size +
"\nTotal: " + projectEntitiesWithPurity.size
Console.println(result)
Console.println(s"Call-graph time: $callGraphTime")
Console.println(s"Analysis time: $analysisTime")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,9 @@ object InitialEntryPointsKey extends ProjectInformationKey[Iterable[Method], Not
val epFinder = instantiateEntryPointFinder(fqn)
epFinder
}

/**
* Reflectively instantiates a ''ClosedPackagesAnalysis'' for the given project.
* The instantiated class has to satisfy the interface and needs to provide a single
* constructor parameterized over a Project.
* Reflectively instantiates an ''EntryPointFinder'' object.
*/
private[this] def instantiateEntryPointFinder(fqn: String): EntryPointFinder = {
import scala.reflect.runtime.universe._
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org
package opalj
package org.opalj
package concurrent

import java.util.concurrent.{Future => JFuture}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org
package opalj
package org.opalj

import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors
Expand Down
36 changes: 36 additions & 0 deletions OPAL/common/src/main/scala/org/opalj/graphs/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -729,4 +729,40 @@ package object graphs {
sccs
}

/**
* Provides a topological order of the given acyclic graph's nodes.
*
* @throws IllegalStateException If the graph contains cycles
*/
def topologicalSort(graph: Map[Int, List[Int]]): List[Int] = {
var sortedNodes: List[Int] = List.empty
var permanent: Set[Int] = Set.empty
var temporary: Set[Int] = Set.empty

val preparedGraph = graph.map { case (node, deps) =>
node -> deps.filter(_ != node)
}

def visit(node: Int): Unit = {
if (!permanent.contains(node)) {
if (temporary.contains(node)) {
throw new IllegalStateException("Graph contains a cycle")
}
temporary = temporary + node

preparedGraph(node).foreach { otherNode => visit(otherNode) }

permanent = permanent + node
temporary = temporary - node

sortedNodes = sortedNodes :+ node
}

}
for (node <- preparedGraph.keys) {
visit(node)
}

sortedNodes
}
}
3 changes: 1 addition & 2 deletions OPAL/common/src/main/scala/org/opalj/util/Return.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org
package opalj
package org.opalj
package util

// TODO: Replace this class by scala.util.control.NonLocalReturns in Scala 3
Expand Down
3 changes: 1 addition & 2 deletions OPAL/common/src/main/scala/org/opalj/util/package.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org
package opalj
package org.opalj

import scala.annotation.nowarn

Expand Down
38 changes: 23 additions & 15 deletions OPAL/si/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
org.opalj {

// Turns on the debugging support of the property store which is primarily meant
// to support the debugging of analyses developed using the property store.
// I.e., debug performs a wide range of additionaly checks to identify errors as
// early as possible.
fpcf.PropertyStore.Debug = false
fpcf.PropertyStore.TraceFallbacks = false
fpcf.PropertyStore.TraceSuppressedNotifications = false
fpcf.PropertyStore.Default = "Parallel"
fpcf {
PropertyStore {
// Turns on the debugging support of the property store which is primarily meant
// to support the debugging of analyses developed using the property store.
// I.e., debug performs a wide range of additionaly checks to identify errors as
// early as possible.
Debug = false
TraceFallbacks = false
TraceSuppressedNotifications = false
Default = "Parallel"
}

// For tasks managers for the seq. store see PKESequentialPropertyStore.Strategies
fpcf.seq.PKESequentialPropertyStore.TasksManager = "ManyDirectDependenciesLast"
fpcf.seq.PKESequentialPropertyStore.MaxEvaluationDepth = 32
// For tasks managers for the seq. store see PKESequentialPropertyStore.Strategies
seq.PKESequentialPropertyStore.TasksManager = "ManyDirectDependenciesLast"
seq.PKESequentialPropertyStore.MaxEvaluationDepth = 32

// For tasks managers for the par. store see PKECPropertyStore.Strategies
fpcf.par.PKECPropertyStore.TasksManager = "NoPriority"
fpcf.par.PKECPropertyStore.MaxEvaluationDepth = 32
// For tasks managers for the par. store see PKECPropertyStore.Strategies
par.PKECPropertyStore.TasksManager = "NoPriority"
par.PKECPropertyStore.MaxEvaluationDepth = 32

fpcf.AnalysisScenario.AnalysisAutoConfig = false
AnalysisScenario {
AnalysisAutoConfig = false
SchedulingStrategy = "org.opalj.fpcf.scheduling.MaximumPhaseScheduling"
ScheduleLazyInMultiplePhases = true
}
}

si.flowanalysis.StructuralAnalysis {
maxIterations = 1000
Expand Down
Loading