Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
0112a27
Express generic program matching as VM match instructions
unp1 Jun 14, 2026
ba86013
Express context-block program matching as VM match instructions
unp1 Jun 14, 2026
9a84e11
Add a cursor-free compiled taclet find-matcher
unp1 Jun 14, 2026
889f664
Parallelize the runAllProofs testRAP task
unp1 Jun 14, 2026
3d3ba8a
test(dev): matcher differential test + isolated benchmarks [DROP BEFO…
unp1 Jun 14, 2026
a9c9339
matcher: introduce key.ncore.compiler match-plan framework
unp1 Jun 14, 2026
0940397
matcher: build Java-DL find-matchers on the match-plan framework
unp1 Jun 14, 2026
49b33a0
matcher: route VMTacletMatcher through the match-plan framework
unp1 Jun 14, 2026
7d16e62
test(dev): differential + benchmark cover the match-plan framework [D…
unp1 Jun 14, 2026
4916ca4
matcher: collapse the hand-written matchers into the framework (singl…
unp1 Jun 15, 2026
5b11b82
test(dev): drop the oracle-based differential from the PR; framework-…
unp1 Jun 15, 2026
f263517
matcher: add a "compiled matcher" feature flag (GUI toggle)
unp1 Jun 15, 2026
5158a47
perf(matcher): enable the compiled find-matcher by default
unp1 Jun 17, 2026
aa9bbad
perf(strategy): cost reuse across createFurtherApps re-expansion
unp1 Jun 16, 2026
d5a5024
fix(strategy): make introductionTime deterministic (do not cache -1)
unp1 Jun 16, 2026
6a86b3a
refactor(strategy): name the cost-reuse INELIGIBLE sentinel
unp1 Jun 16, 2026
cac2896
perf(strategy): make goal age a first-class container-level cost term
unp1 Jun 16, 2026
1590ff8
perf(strategy): precise op-indexed parking of assumes-incomplete bases
unp1 Jun 16, 2026
4e8cccd
fix(rules): drop redundant order-fragile lenOfSeqSubEQ from automode
unp1 Jun 16, 2026
7d99ba5
perf(label): skip rebuilding unchanged term trees in removeIrrelevant…
unp1 Jun 16, 2026
5dd9819
perf(util): compute Pair.hashCode without a varargs array
unp1 Jun 16, 2026
701da96
perf(strategy): walk the find-position by index in RewriteTacletExecutor
unp1 Jun 16, 2026
da74aaa
perf(loader): release the ANTLR parser DFA caches after loading
unp1 Jun 16, 2026
2387c8e
perf(checkPrefix): skip the prefix walk when the formula has no trans…
unp1 Jun 15, 2026
2271f36
test(perf): add perfTest measurement group (opt-in via -Dkey.runallpr…
unp1 Jun 13, 2026
dd57d9e
Compute NodeInfo's active statement lazily, off the proving path
unp1 Jun 18, 2026
3e22ff6
Cache loop-invariant instantiation on the rule app, not a static field
unp1 Jun 18, 2026
4b9f7ab
Make per-call program transformers stateless
unp1 Jun 18, 2026
18e06ec
Robustly read numeric settings stored as Integer or Long
unp1 Jun 18, 2026
95a98d2
Don't crash reloading a recent file with no stored profile
unp1 Jun 18, 2026
99a12dc
Show a proof macro's aggregate statistics in the status line
unp1 Jun 18, 2026
7cf76a5
Multithreading: add thread-safe cache and interner utilities
unp1 Jun 18, 2026
8a2579f
Multithreading: add the prover-mode setting and profile capability
unp1 Jun 18, 2026
c31bf94
Multithreading: suspend non-essential proof listeners during automode
unp1 Jun 18, 2026
79bfe65
Multithreading: add the goal-level parallel proof engine
unp1 Jun 18, 2026
e62b1c7
Multithreading: make shared proving state thread-safe
unp1 Jun 18, 2026
5f27818
Multithreading: integrate the prover mode into the GUI and CLI
unp1 Jun 18, 2026
238d111
Multithreading: run proof macros on the multi-core prover
unp1 Jun 18, 2026
7cf6734
Multithreading: add benchmarks, stress tests and CI wiring
unp1 Jun 18, 2026
d4523cd
Pool the matching cursor per thread instead of behind a global lock
unp1 Jun 20, 2026
890f466
Stop multi-core workers before restoring proof listeners on cancel
unp1 Jun 21, 2026
1d9806a
perf(matcher): compile \assumes formula matching (incl. Java programs…
unp1 Jun 21, 2026
6891594
Merge remote-tracking branch 'origin/perf-round3-meta' into integrati…
unp1 Jun 22, 2026
1538e38
Merge branch 'main' into bubel/mt-perf-integration
unp1 Jun 22, 2026
5044c4b
Restore the brace closing the key.mt.jfr if-block in the test config
unp1 Jun 22, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:
strategy:
fail-fast: false
matrix:
test: [ testProveRules, testRunAllFunProofs, testRunAllInfProofs, testRunAllWdProofs ]
test: [ testProveRules, testRunAllFunProofs, testRunAllInfProofs, testRunAllWdProofs, testMtStress ]
os: [ ubuntu-latest ]
java: [ 21 ]
runs-on: ${{ matrix.os }}
Expand Down
5 changes: 5 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ subprojects {
systemProperty "RUNALLPROOFS_DIR", layout.buildDirectory.dir("report/runallproves").get().toString()

systemProperty "key.disregardSettings", "true"
// Pin the whole test suite to the single-threaded prover, so no test silently runs on the
// multi-core prover (e.g. merge-rule, slicing and symbolic-execution tests rely on single
// core). Opt-in parallel tests (equivalence, stress, benchmark) set this property at runtime,
// which overrides the baseline within their fork.
systemProperty "key.prover.parallel", "false"
maxHeapSize = "4g"

forkEvery = 0 //default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ public class JavaInfFlowProfile extends JavaProfile {
public static final String NAME = "Java InfFlow Profile";
public static final String PROFILE_ID = "java-infflow";

@Override
public boolean supportsParallelAutomode() {
// Information-flow proofs use side-proof machinery that is not thread-safe: keep
// single-core.
return false;
}

@Override
public String ident() {
return PROFILE_ID;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ public SimplifyTermProfile() {
/**
* {@inheritDoc}
*/
@Override
public boolean supportsParallelAutomode() {
// Symbolic-execution term-simplification profile: keep single-core (not audited).
return false;
}

@Override
protected ImmutableList<TermLabelConfiguration> computeTermLabelConfiguration() {
ImmutableList<TermLabelConfiguration> result = super.computeTermLabelConfiguration();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ protected ImmutableSet<GoalChooserFactory<Proof, Goal>> computeSupportedGoalChoo
.add(new SymbolicExecutionGoalChooserFactory());
}

@Override
public boolean supportsParallelAutomode() {
// The symbolic-execution debugger profile builds a shared SE tree during search and is not
// audited for thread-safety: keep single-core.
return false;
}

/**
* {@inheritDoc}
*/
Expand Down
6 changes: 6 additions & 0 deletions key.core.wd/src/main/java/de/uka/ilkd/key/wd/WdProfile.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ public WdProfile() {
defRules.standardBuiltInRules());
}

@Override
public boolean supportsParallelAutomode() {
// Well-definedness checks are not yet audited for thread-safety: keep single-core.
return false;
}

@Override
public String ident() {
return PROFILE_ID;
Expand Down
58 changes: 55 additions & 3 deletions key.core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies {
api project(':key.util')
api project(':key.ncore')
api project(':key.ncore.calculus')
api project(':key.ncore.compiler')

antlr4 "org.antlr:antlr4:4.13.2"
api "org.antlr:antlr4-runtime:4.13.2"
Expand Down Expand Up @@ -97,6 +98,30 @@ classes.dependsOn << generateSolverPropsList

tasks.withType(Test) {
enableAssertions = true
// The whole suite is pinned to the single-threaded prover in the root build (key.prover.parallel
// = false); opt-in parallel tests override it at runtime. The forwarding loop below still lets
// the Gradle command line override it (e.g. -Dkey.prover.parallel=true).
// Forward the multithreading / parallel-prover properties from the Gradle command line to the
// test JVM (Gradle does not propagate -D automatically). Lets one run e.g.
// ./gradlew :key.core:test --tests '*MtSpeedupBenchmark' -Dkey.mt.benchmark=true
// or toggle the parallel prover for any test via -Dkey.prover.parallel(.threads).
["key.mt.benchmark", "key.mt.benchmark.threads", "key.mt.benchmark.proofs",
"key.mt.benchmark.maxsteps",
"key.mt.synth.splits", "key.mt.synth.worksplits", "key.mt.synth.work",
"key.mt.synth.linear", "key.mt.synth.loop",
"key.mt.jfr.probe", "key.mt.jfr.proof", "key.mt.jfr.workers", "key.mt.jfr.reps",
"key.prover.parallel", "key.prover.parallel.threads"].each { p ->
if (System.getProperty(p) != null) {
systemProperty(p, System.getProperty(p))
}
}
// Record a Flight Recording of the test JVM when -Dkey.mt.jfr=<file> is given. Used to profile
// the parallel prover's lock contention and hot paths (see MtJfrProbe).
if (System.getProperty("key.mt.jfr") != null) {
jvmArgs += ["-XX:StartFlightRecording=filename=${System.getProperty('key.mt.jfr')}," +
"settings=profile,dumponexit=true,disk=true",
"-XX:FlightRecorderOptions=stackdepth=128"]
}
// Forward retention-probe knobs (see MtRetentionProbe) to the test JVM.
systemProperties += System.properties.findAll { it.key.toString().startsWith("key.mt.retention") }
if (project.hasProperty("stressHeap")) {
Expand Down Expand Up @@ -149,6 +174,26 @@ tasks.register('testStrictSMT', Test) {
}
}

// Stress test for the goal-level parallel prover: run a few large splitting proofs many times at a
// high (over-subscribed) worker count and assert each one closes. Slow (minutes), so it is gated out
// of the normal unit-test suite and only runs here. Guards against reintroducing a concurrency race
// that makes proofs nondeterministically fail to close. See MtStressTest.
tasks.register('testMtStress', Test) {
description = 'Stress the parallel prover at high worker counts to catch non-closure races'
group = 'verification'
systemProperty("key.mt.stress", "true")
maxParallelForks = 1
// Each class proves many full proofs; give every test class a fresh JVM so global KeY state
// (settings, static caches/interners, the script parser) cannot leak between classes -- e.g.
// MtScriptStressTest's position-sensitive script must not inherit state from earlier classes.
forkEvery = 1
filter {
includeTestsMatching "MtStressTest"
includeTestsMatching "MtMacroStressTest"
includeTestsMatching "MtScriptStressTest"
}
}

//Generation of the three version files within the resources by executing `git'.
tasks.register('generateVersionFiles') {
def outputFolder = file("build/resources/main/de/uka/ilkd/key/util")
Expand Down Expand Up @@ -250,14 +295,21 @@ tasks.register("testRAP", Test) {
dependsOn('generateRAPUnitTests', 'testClasses')

forkEvery = 1
maxParallelForks = 2
// run the regression proofs on up to 10 parallel JVMs (overridable with -PrapForks=N);
// for clean perfTest timing reproduction use -PrapForks=1
maxParallelForks = (project.findProperty('rapForks') ?: '10') as int
useJUnitPlatform()
it.filter {
it.includeTestsMatching "de.uka.ilkd.key.proof.runallproofs.gen.*"
}
// set heap size for the test JVM(s)
// forward the compiled-matcher switch to the (in-process) proof runs in each fork; default
// off, enable with -Pmatcher.compiled=true (or -Dkey.matcher.compiled=true)
systemProperty 'key.matcher.compiled',
(project.findProperty('matcher.compiled')
?: System.getProperty('key.matcher.compiled', 'false'))
// set heap size for the test JVM(s) (overridable with -PrapHeap=8g for the large examples)
minHeapSize = "1g"
maxHeapSize = "3g"
maxHeapSize = (project.findProperty('rapHeap') ?: '3g')

// set JVM arguments for the test JVM(s)
//jvmArgs('-XX:MaxPermSize=1g')
Expand Down
Loading
Loading