feat!: replace dependency graph with reactive invalidation - #5292
Open
DanySK wants to merge 31 commits into
Open
feat!: replace dependency graph with reactive invalidation#5292DanySK wants to merge 31 commits into
DanySK wants to merge 31 commits into
Conversation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR supersedes #5131.
It rebases the reactive-engine work on top of the current
masterand preserves the same overall direction: move the engine and the observable state model away from coarse-grained dependency recomputation and toward reactive, fine-grained invalidation.At a high level, this branch:
alchemist-apiDependencyGraph/JGraphTDependencyGraphpathEngineWhy this exists
The original goal from #5131 remains the same:
Main changes
1. Observable model infrastructure
This PR adds a substantial observation layer in
alchemist-api, including:ObservableObservableListObservableMapObservableSetLifecycle,LifecycleOwner,LifecycleRegistry,LifecycleState)These components are then used to expose mutable simulation state in a way that can notify dependent logic incrementally instead of forcing coarse global refreshes.
2. Engine architecture
The branch first introduces a separate reactive engine during development, but the final rebased result does not keep a standalone
ReactiveEngineclass.Instead, the final state:
DependencyGraphJGraphTDependencyGraphEngineAbstractEngineand related support codeThis is important because the PR is no longer “add a second engine implementation”; it is effectively “replace the old engine dependency-management model with a reactive one.”
3. Fine-grained invalidation in core model code
A large portion of the diff updates:
to subscribe to narrower observable sources and react only to relevant changes.
This includes changes in
alchemist-implementationbase, where several conditions and reaction-related classes are updated to consume the new observable semantics.4. SAPERE-focused performance work
The most performance-oriented part of the PR is the SAPERE work:
LsaNodeLsaNeighborhoodConditionLsaStandardConditionSAPEREGradientSAPEREReactionThese changes aim to stop reacting to whole-LSA-space churn when only a targeted molecule or neighborhood-relevant subset changed.
This is likely the most immediately measurable performance improvement in the branch, because SAPERE workloads often stress dependency propagation and neighborhood-sensitive invalidation patterns.
5. Incarnation and integration updates
To keep the engine/model shift coherent, the branch also updates:
This is not incidental churn; most of these changes are required to make the reactive model consistent across the simulation stack.
What changed compared to #5131
This PR should be treated as the replacement for #5131, not as an unrelated follow-up.
Compared to #5131:
mastermasterdependency versions where appropriateEngineValidation status
This branch was rebased with repository hooks enabled.
During the rebase, the only manual conflict resolutions required were:
alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/loader/LoadingSystem.ktgradle/libs.versions.tomlThe resolutions were mechanical and aligned with the final intent of the rebased commits:
Engine(environment)path after the dedicatedReactiveEngineremovalmaster's newer shared dependency versions while preserving the branch’s addedkotlinx-collectionscatalog entriesHow to assess the performance change
There does not appear to be a dedicated microbenchmark suite in the repository, so the best assessment is comparative measurement on representative workloads.
Best candidates to measure
The most relevant areas are:
Practical ways to evaluate
Compare
mastervs this branch using repeated runs of the same workloads.Focus first on SAPERE-heavy tests and simulations, because the final commits specifically optimize fine-grained SAPERE invalidation.
Use wall-clock time, CPU time, allocation rate, and GC pressure as the primary metrics.
Run on the same JVM and machine, ideally multiple times, ignoring the first run if dependency/classloading noise matters.
Concrete approaches
Run targeted Gradle test tasks repeatedly on
masterand this branch:./gradlew --parallel :alchemist-incarnation-sapere:test./gradlew --parallel :alchemist-engine:test./gradlew --parallel :alchemist-cognitive-agents:testFor scenario-level comparisons, build the simulator and execute the same representative simulations on both revisions, then compare:
If deeper profiling is needed, use JFR or an external profiler on identical simulations to confirm that:
What I would expect to improve
If the branch behaves as intended, the most likely gains are:
I would not assume uniform speedups everywhere. Some workloads may be neutral, and broad integration changes like this deserve empirical confirmation rather than a blanket performance claim.
Reference