Skip to content
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

Add Support for Predictive Scaling #49

Open
wants to merge 52 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
194d08a
Add trigger that can scale in+out periodically
berbjs Jul 26, 2024
e3d65c4
[WIP] Interpretation of Models + Aggregation of Stimuli
berbjs Jul 31, 2024
c9ad4c2
Improved Model Evaluation + Aggregation
berbjs Aug 14, 2024
4248fb3
Move the model evaluator package + update models for rewards
berbjs Aug 14, 2024
8f69d9c
Improve Aggregation for Model-based triggers
berbjs Aug 19, 2024
5a3088b
Improve (reward) aggregation + evaluation
berbjs Aug 20, 2024
d15a9c9
Add functional Version of RateOfChange aggregation
berbjs Aug 20, 2024
d655c0f
Improved Reward Evaluation + Model Interpretation
berbjs Aug 20, 2024
a56dfcb
Don't register new event handlers for RepeatedSimulationTimeReached
berbjs Aug 24, 2024
2880d5b
ModelInterpreter: Handle non-aggregated stimuli
berbjs Aug 26, 2024
07dcacf
Restructuring of Trigger Checker for models
berbjs Aug 26, 2024
39da9cf
Refactor Aggregation to allow for averaging of non-aggregated stimuli
berbjs Aug 26, 2024
2675cf7
Modify MANIFEST
berbjs Aug 27, 2024
befa2aa
Adjustments to support the new ScalingTriggers
berbjs Aug 27, 2024
ef49330
Small naming + code style improvements
berbjs Aug 28, 2024
5c426be
Implement more useful random model (see SPD metamodel)
berbjs Aug 28, 2024
ba52044
Change implementation for fixed rewards metamodel
berbjs Sep 8, 2024
1a0b625
Improved Aggregator emit error messages, throw custom Exception
berbjs Sep 3, 2024
586b8ad
Change implementation according to new model metamodel
berbjs Sep 5, 2024
76ee90a
Change implementation according to new model metamodel
berbjs Sep 5, 2024
aa47a45
Fix typos + make exceptions less generic
berbjs Sep 11, 2024
5dd2356
Enable adjustment on measurements and/or intervals
berbjs Sep 11, 2024
ec8d2c4
Remove support for AggregatedStimulus
berbjs Sep 16, 2024
a427514
Remove old TODOs
berbjs Sep 17, 2024
10c6c12
Fix getting model scaling decision twice
berbjs Sep 17, 2024
23d5295
Add update function to LearningBasedModelEvaluator
berbjs Sep 24, 2024
e5c537c
Cleanup: Remove OutputInterpreter
berbjs Sep 24, 2024
70a5041
Cleanup: Formating, TODOs, unneeded methods + comments
berbjs Sep 24, 2024
c576429
Less Adjustment Logging spam, debug -> info for relevant information
berbjs Sep 25, 2024
f4f40b6
"Fix" TargetGroupChecker for ElasticInfrastructureMeasuringPoint
berbjs Sep 26, 2024
3ade3dd
Implement percentile aggregation method
berbjs Oct 1, 2024
aa835f2
Reduce logspam: Move failed filter logs from info to debug
berbjs Oct 9, 2024
f643ca4
Improve LearningBasedModelEvaluator
berbjs Oct 21, 2024
37e066e
Remove old models
berbjs Oct 21, 2024
d6f306e
Initial implementation of Fuzzy-Q-Learning
berbjs Oct 21, 2024
4347330
More logging for learning-based models
berbjs Oct 21, 2024
14322c9
Fix Fuzzy Q-Learning bugs
berbjs Oct 21, 2024
06d5027
Fix + Refactor FuzzyQLearningModelEvaluator
berbjs Oct 22, 2024
eef2aff
Add Fuzzy SARSA Model Evaluator
berbjs Oct 22, 2024
861bc51
Fuzzy Learning Optimizations
berbjs Oct 24, 2024
0bd0fac
Improved Logging for Fuzzy Q-Learning
Oct 25, 2024
8480fe3
Implement maximum container count for fuzzy scaling
berbjs Oct 30, 2024
3f85fa5
Fix wrong fuzzy state calculation
berbjs Nov 5, 2024
c73031b
Use Slingshot constructs for interval + max container count
berbjs Nov 8, 2024
17a148d
Use actual scaling action as basis for reward
berbjs Nov 8, 2024
e050e3d
Bugfix: Use long
berbjs Nov 8, 2024
b625bca
Bugfix: Don't use IntervalConstraintFilter for model-based scaling
berbjs Nov 8, 2024
7728b8c
Fix wrong container count clipping
berbjs Nov 12, 2024
1d240ce
Rely on container bounding by Slingshot
berbjs Nov 13, 2024
76b1f3b
Fixed wrongly constructed RepeatedSimulationTimeReached event
berbjs Nov 14, 2024
5467728
Support thrashing constraints for model-based scaling policies
berbjs Nov 16, 2024
e8fa1c7
Support initialization type
berbjs Nov 20, 2024
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

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -11,118 +11,119 @@
import org.palladiosimulator.analyzer.slingshot.behavior.spd.adjustment.qvto.QVToModelTransformation;

/**
* This cache implementation is used to store QVTo transformations (in terms
* of {@link TransformationData} objects) that can be executed by QVTo executors
* during reconfigurations. To store a transformation in the cache, its corresponding
* {@link URI} is used as tag.
* This cache implementation is used to store QVTo transformations (in terms of
* {@link TransformationData} objects) that can be executed by QVTo executors during
* reconfigurations. To store a transformation in the cache, its corresponding {@link URI} is used
* as tag.
*
* @author Florian Rosenthal
*
*/
public class ModelTransformationCache {

private static final Logger LOGGER = Logger.getLogger(ModelTransformationCache.class);
private final Map<URI, QVToModelTransformation> cache;
private final ModelTransformationFactory modelTransformationFactory;
/**
* Initializes a new instance of the {@link ModelTransformationCache} class.
*
* @param initialTransformations
* A set of transformation {@link URI URIs} that shall be stored
* in the cache, might be empty.
*/
public ModelTransformationCache(final URI... initialTransformations) {
this.cache = new HashMap<>();
this.modelTransformationFactory = new ModelTransformationFactory();
store(initialTransformations);
}
/**
* Stores the QVTo transformations specified by the given URIs in the cache.
*
* @param transformationUris
* A set of {@link URI URIs} that point to QVTo transformations.
* @throws NullPointerException
* In case {@code transformationUris == null}.
* @throws IllegalArgumentException
* In case any of the transformations is already present in the
* cache.
*/
public final void store(final URI... transformationUris) {
final URI[] uris = Objects.requireNonNull(transformationUris);
for (final URI transformationUri : uris) {
if (contains(transformationUri)) {
throw new IllegalArgumentException("Transformation " + transformationUri + " already in store.");
}
LOGGER.debug("Cache reconfiguration rule \"" + transformationUri + "\"");
this.cache.put(transformationUri, this.modelTransformationFactory.createModelTransformation(transformationUri));
}
}
/**
* Attempts to retrieve the QVTo transformation that is associated with the
* given URI from the cache.
*
* @param transformationUri
* A {@link URI} that points to a QVTo transformation.
* @return The {@link TransformationData} of the transformation, or
* {@code null} if it is not present in the cache.
* @throws NullPointerException
* In case the given URI is {@code null}.
* @see #contains(URI)
*/
public Optional<QVToModelTransformation> get(final URI transformationUri) {
if (!this.contains(transformationUri)) {
this.store(transformationUri);
}
return Optional.ofNullable(this.cache.get(Objects.requireNonNull(transformationUri)));
}
/**
private static final Logger LOGGER = Logger.getLogger(ModelTransformationCache.class);

private final Map<URI, QVToModelTransformation> cache;
private final ModelTransformationFactory modelTransformationFactory;

/**
* Initializes a new instance of the {@link ModelTransformationCache} class.
*
* @param initialTransformations
* A set of transformation {@link URI URIs} that shall be stored in the cache, might
* be empty.
*/
public ModelTransformationCache(final URI... initialTransformations) {
this.cache = new HashMap<>();
this.modelTransformationFactory = new ModelTransformationFactory();
store(initialTransformations);
}

/**
* Stores the QVTo transformations specified by the given URIs in the cache.
*
* @param transformationUris
* A set of {@link URI URIs} that point to QVTo transformations.
* @throws NullPointerException
* In case {@code transformationUris == null}.
* @throws IllegalArgumentException
* In case any of the transformations is already present in the cache.
*/
public final void store(final URI... transformationUris) {
final URI[] uris = Objects.requireNonNull(transformationUris);
for (final URI transformationUri : uris) {
if (contains(transformationUri)) {
throw new IllegalArgumentException("Transformation " + transformationUri + " already in store.");
}
LOGGER.debug("Cache reconfiguration rule \"" + transformationUri + "\"");
this.cache.put(transformationUri,
this.modelTransformationFactory.createModelTransformation(transformationUri));
}
}

/**
* Attempts to retrieve the QVTo transformation that is associated with the given URI from the
* cache.
*
* @param transformationUri
* A {@link URI} that points to a QVTo transformation.
* @return The {@link TransformationData} of the transformation, or {@code null} if it is not
* present in the cache.
* @throws NullPointerException
* In case the given URI is {@code null}.
* @see #contains(URI)
*/
public Optional<QVToModelTransformation> get(final URI transformationUri) {
if (!this.contains(transformationUri)) {
this.store(transformationUri);
}
return Optional.ofNullable(this.cache.get(Objects.requireNonNull(transformationUri)));
}

/**
* Removes the QVTo transformations specified by the given URIs from this cache, if present.
*
* @param transformationUris
* A set of {@link URI URIs} that point to QVTo transformations.
* @throws NullPointerException
* In case any of the given uris is {@code null}.
*/
public final void remove(final URI... transformationUris) {
final URI[] uris = Objects.requireNonNull(transformationUris);
Arrays.stream(uris).map(Objects::requireNonNull).forEach(this.cache::remove);
}

/**
* Gets whether the QVTo transformation which the given URI points to, is
* currently in the cache.
*
* @param transformationUri
* A {@link URI} that points to a QVTo transformation.
* @return {@code true}, iff the transformation is stored, {@code false}
* otherwise
*
* @throws NullPointerException
* In case the given URI is {@code null}.
*/
public boolean contains(final URI transformationUri) {
return this.cache.containsKey(Objects.requireNonNull(transformationUri));
}

/**
* Gets all the transformations, in terms of the respective
* {@link TransformationData} currently stored in this cache.
*
* @return An {@link Iterable} of all the stored transformations.
*/
public Iterable<QVToModelTransformation> getAll() {
return this.cache.values();
}

/**
* Clears the cache, that is, all content is discarded.
*/
public void clear() {
this.cache.clear();
}
public final void remove(final URI... transformationUris) {
final URI[] uris = Objects.requireNonNull(transformationUris);
Arrays.stream(uris)
.map(Objects::requireNonNull)
.forEach(this.cache::remove);
}

/**
* Gets whether the QVTo transformation which the given URI points to, is currently in the
* cache.
*
* @param transformationUri
* A {@link URI} that points to a QVTo transformation.
* @return {@code true}, iff the transformation is stored, {@code false} otherwise
*
* @throws NullPointerException
* In case the given URI is {@code null}.
*/
public boolean contains(final URI transformationUri) {
return this.cache.containsKey(Objects.requireNonNull(transformationUri));
}

/**
* Gets all the transformations, in terms of the respective {@link TransformationData} currently
* stored in this cache.
*
* @return An {@link Iterable} of all the stored transformations.
*/
public Iterable<QVToModelTransformation> getAll() {
return this.cache.values();
}

/**
* Clears the cache, that is, all content is discarded.
*/
public void clear() {
this.cache.clear();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ Automatic-Module-Name: org.palladiosimulator.analyzer.slingshot.behavior.spd.dat
Bundle-RequiredExecutionEnvironment: JavaSE-17
Require-Bundle: org.palladiosimulator.analyzer.slingshot.common;bundle-version="1.0.0",
org.palladiosimulator.spd,
org.palladiosimulator.monitorrepository
org.palladiosimulator.monitorrepository,
org.palladiosimulator.analyzer.slingshot.eventdriver
Export-Package: org.palladiosimulator.analyzer.slingshot.behavior.spd.data
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,21 @@
import org.palladiosimulator.spd.ScalingPolicy;

/**
* Tells that a certain adjustment to the PCM model is requested. An adjustor
* module can then perform these adjustments.
* <br>
* This event holds the enacted scaling policy that was fired as well as
* the target group.
* Tells that a certain adjustment to the PCM model is requested. An adjustor module can then
* perform these adjustments. <br>
* This event holds the enacted scaling policy that was fired as well as the target group.
*
* @author Julijan Katic
*/
public final class ModelAdjustmentRequested extends AbstractSimulationEvent implements SpdBasedEvent {

private final ScalingPolicy scalingPolicy;

public ModelAdjustmentRequested(final ScalingPolicy scalingPolicy) {
this.scalingPolicy = Objects.requireNonNull(scalingPolicy);
}

public ScalingPolicy getScalingPolicy() {
return this.scalingPolicy;
}

private final ScalingPolicy scalingPolicy;

public ModelAdjustmentRequested(final ScalingPolicy scalingPolicy) {
this.scalingPolicy = Objects.requireNonNull(scalingPolicy);
}

public ScalingPolicy getScalingPolicy() {
return this.scalingPolicy;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.palladiosimulator.analyzer.slingshot.behavior.spd.data;

import org.palladiosimulator.analyzer.slingshot.common.events.AbstractSimulationEvent;

/**
* An event that is scheduled at an exact simulation time and repeats on a schedule. In context of
* SPD, this is needed especially for predictive triggers that recompute some measures on a
* schedule.
*
* This event also carries a necessary target group (identifier) in order to correctly identify
* whether this event belongs to the right scaling policy.
*
* @author Jens Berberich, Julijan Katic
*/
public class RepeatedSimulationTimeReached extends AbstractSimulationEvent implements SpdBasedEvent {

private final String targetGroupId;
private double repetitionTime;

public RepeatedSimulationTimeReached(String targetGroupId, double simulationTime, double delay,
double repetitionTime) {
super(delay);
this.targetGroupId = targetGroupId;
this.setTime(simulationTime);
this.repetitionTime = repetitionTime;
}

public double getRepetitionTime() {
return repetitionTime;
}

public String getTargetGroupId() {
return targetGroupId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*
* @author Julijan Katic
*/
public final class SimulationTimeReached extends AbstractSimulationEvent implements SpdBasedEvent {
public class SimulationTimeReached extends AbstractSimulationEvent implements SpdBasedEvent {

private final String targetGroupId;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: Spd
Bundle-SymbolicName: org.palladiosimulator.analyzer.slingshot.behavior.spd;singleton:=true
Bundle-Version: 1.0.0.qualifier
Import-Package: org.apache.commons.math3.stat.regression
Automatic-Module-Name: org.palladiosimulator.analyzer.slingshot.behavior.spd
Bundle-RequiredExecutionEnvironment: JavaSE-17
Require-Bundle: org.palladiosimulator.analyzer.slingshot.core;bundle-version="1.0.0",
Expand All @@ -13,4 +14,6 @@ Require-Bundle: org.palladiosimulator.analyzer.slingshot.core;bundle-version="1.
org.palladiosimulator.analyzer.slingshot.ui.events;bundle-version="1.0.0",
org.palladiosimulator.analyzer.slingshot.workflow.events;bundle-version="1.0.0",
org.palladiosimulator.pcm.edp2.measuringpoint,
org.palladiosimulator.spd.semantic
org.palladiosimulator.spd.semantic,
org.palladiosimulator.spd,
org.palladiosimulator.spd.measuringpoint
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.palladiosimulator.analyzer.slingshot.behavior.spd.interpreter;

import org.palladiosimulator.analyzer.slingshot.behavior.spd.interpreter.entity.aggregator.AnyStimulusAggregator;
import org.palladiosimulator.analyzer.slingshot.behavior.spd.interpreter.entity.aggregator.ManagedElementAggregator;
import org.palladiosimulator.analyzer.slingshot.behavior.spd.interpreter.entity.aggregator.ModelAggregatorWrapper;
import org.palladiosimulator.analyzer.slingshot.behavior.spd.interpreter.entity.model.FuzzyQLearningModelEvaluator;
import org.palladiosimulator.analyzer.slingshot.behavior.spd.interpreter.entity.model.FuzzySARSAModelEvaluator;
import org.palladiosimulator.analyzer.slingshot.behavior.spd.interpreter.entity.model.ModelEvaluator;
import org.palladiosimulator.analyzer.slingshot.behavior.spd.interpreter.entity.model.RandomModelEvaluator;
import org.palladiosimulator.spd.models.FuzzyQLearningModel;
import org.palladiosimulator.spd.models.FuzzySARSAModel;
import org.palladiosimulator.spd.models.LearningBasedModel;
import org.palladiosimulator.spd.models.RandomModel;
import org.palladiosimulator.spd.models.util.ModelsSwitch;
import org.palladiosimulator.spd.triggers.AGGREGATIONMETHOD;
import org.palladiosimulator.spd.triggers.stimuli.ManagedElementsStateStimulus;
import org.palladiosimulator.spd.triggers.stimuli.Stimulus;

public class ModelInterpreter extends ModelsSwitch<ModelEvaluator> {

@SuppressWarnings("rawtypes")
public ModelAggregatorWrapper getAggregatorForStimulus(final Stimulus stimulus, final LearningBasedModel model) {
if (stimulus instanceof final ManagedElementsStateStimulus managedElementsStateStimulus) {
return new ManagedElementAggregator<>(managedElementsStateStimulus, model.getInterval());
} else {
// TODO currently using average aggregation by default for non-aggregated
// stimuli, this might need to be changed
return this.getAggregatorForStimulus(stimulus, model, AGGREGATIONMETHOD.AVERAGE);
}
}

public <T extends Stimulus> ModelAggregatorWrapper<T> getAggregatorForStimulus(final T stimulus,
final LearningBasedModel model, final AGGREGATIONMETHOD aggregationMethod) {
return new AnyStimulusAggregator<>(stimulus, model.getInterval(), aggregationMethod);
}

@Override
public ModelEvaluator caseRandomModel(final RandomModel model) {
return new RandomModelEvaluator(model);
}

@Override
public ModelEvaluator caseFuzzySARSAModel(FuzzySARSAModel model) {
return new FuzzySARSAModelEvaluator(model, this);
}

@Override
public ModelEvaluator caseFuzzyQLearningModel(FuzzyQLearningModel model) {
return new FuzzyQLearningModelEvaluator(model, this);
}
}
Loading