| /******************************************************************************* |
| * Copyright (c) 2009, 2012 SAP AG and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * SAP AG - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.ocl.examples.impactanalyzer.configuration; |
| |
| import org.eclipse.ocl.examples.impactanalyzer.ImpactAnalyzer; |
| import org.eclipse.ocl.examples.impactanalyzer.instanceScope.InstanceScopeAnalysis; |
| import org.eclipse.ocl.examples.impactanalyzer.instanceScope.NavigationStep; |
| import org.eclipse.ocl.examples.impactanalyzer.instanceScope.traceback.TracebackStep; |
| |
| /** |
| * Configures the {@link ImpactAnalyzer} and the {@link InstanceScopeAnalysis} components and choose between different |
| * implementation styles. A singleton instance of this class is managed by {@link OptimizationActivation}. The following options |
| * can be configured, either by invoking a setter or by passing the respective argument to the constructor: |
| * |
| * <ul> |
| * <li><b>deltaPropagationActive</b> (see {@link #isDeltaPropagationActive()} and {@link #setDeltaPropagationActive(boolean)}: |
| * Tells if the instance scope analysis shall use a delta propagation and partial evaluation mechanism to decide early on if the |
| * subexpression(s) immediately affected by the change may propagate the change all the way to the overall expression's evaluation |
| * result. This will trigger OCL evaluations for subexpressions, some of which may fail for unknown variables, some of which may |
| * prove that the subexpression where the change "hit" doesn't propagate the change, leaving the overall expression unchanged. By |
| * and large, this saves significant efforts during re-evaluation as it reduces the set of context instances returned by |
| * {@link ImpactAnalyzer#getContextObjects(org.eclipse.emf.common.notify.Notification)} for many cases. Our measurements show that |
| * the additional efforts spent for the analysis gets amortized in all cases we have measured. Recommendation: set to |
| * <code>true</code>.</li> |
| * |
| * <li><b>tracebackStepISAActive</b>: (see {@link #isTracebackStepISAActive()} and {@link #setTracebackStepISAActive(boolean)}: |
| * Currently, there are two fundamentally different implementation strategies for the instance scope analysis (see also |
| * {@link InstanceScopeAnalysis}). One pre-computes one {@link TracebackStep step} object per (sub-)expression contained in the |
| * OCL expression's AST and executes them when |
| * {@link ImpactAnalyzer#getContextObjects(org.eclipse.emf.common.notify.Notification)} is invoked. This strategy lends itself |
| * well for an additional early pruning of options related to the <b>unusedDetectionActive</b> option explained below. If |
| * deselected by setting this option to <code>false</code>, a strategy is selected which materialized only those |
| * {@link NavigationStep steps} that actually perform some navigation or filtering on the model graph. The construction of this |
| * tree, according to our measurements, is slightly more expensive than the construction of the {@link TracebackStep more |
| * elaborate} step graph. On average, the two perform fairly similar. The key difference, as already mentioned, is that only when |
| * setting this option to <code>true</code>, the <b>unusedDetectionActive</b> option has any effect.</li> |
| * |
| * <li><b>unusedDetectionActive</b> (see {@link #isUnusedDetectionActive()} and {@link #setUnusedDetectionActive(boolean)}: |
| * Activates a performance improvement measure which aims to prove that the sub-expression where the change occurred is not used |
| * under the variable/parameter/self settings inferred from the information delivered about the change in the change |
| * {@link Notification}. For example, if a change occurs in an <code>else</code> branch of an <code>if</code>-expression and the |
| * condition can be proven to evaluate to <code>true</code> based on the information taken from the {@link Notification}, this |
| * proves that the subexpression that changed its value is not used in evaluating the overall expression. Therefore, the change |
| * does not impact the overall expression at all. This technique involves some up-front cost for determining the various checks to |
| * be performed. During {@link ImpactAnalyzer#getContextObjects(org.eclipse.emf.common.notify.Notification)} some additional cost |
| * is incurred for evaluating sub-expressions (such as an <code>if</code>-expression's condition, as exemplified above). For |
| * smaller models, performance seem to be on-par for both settings of this switch. We hope to prove that for certain cases where |
| * we see really bad performance without this option being used, using it would significantly shrink the number of elements |
| * considered to potentially have changed. This option can only be selected, if {@link #isTracebackStepISAActive()} |
| * is <code>true</code>.</li> |
| * |
| * <li><b>operationCallSelectionActive</b> (see {@link #isOperationCallSelectionActive()} and |
| * {@link #setOperationCallSelectionActive(boolean)}: Activates a performance improvement measure which aims to minimize |
| * the {@link OperationCallExp} considered when tracing back through a <code>self</code> or parameter variable inside an |
| * operation body. Without this measure, all results obtained from tracing back through all possible calls to the |
| * operation considered will be used. With the measure activated, while all results will be computed and cached, |
| * only those specific to the call considered will be used further on. This makes the results crisper and smaller but |
| * may consume a little more performance during evaluation time because results need to be keyed by {@link OperationCallExp} |
| * expressions, causing more data structures to be maintained. This option can only be selected, if {@link #isTracebackStepISAActive()} |
| * is <code>true</code>.</li> |
| * </ul> |
| * |
| */ |
| public class ActivationOption { |
| // Level 2 Optimizations |
| private boolean isDeltaPropagationActive = true; |
| private boolean isTracebackStepISAActive = true; // if set to false, NavigationStep method will be used |
| private boolean isUnusedDetectionActive = true; |
| private boolean isOperationCallSelectionActive = true; |
| |
| private final String optionDescription; |
| |
| public ActivationOption(boolean isDeltaPropagationActive, boolean isUnusedDetectionActive, boolean isTracebackStepISAActive, |
| boolean isOperationCallSelectionActive, String description) { |
| this.isDeltaPropagationActive = isDeltaPropagationActive; |
| this.isUnusedDetectionActive = isUnusedDetectionActive; |
| this.isTracebackStepISAActive = isTracebackStepISAActive; |
| this.isOperationCallSelectionActive = isOperationCallSelectionActive; |
| this.optionDescription = description; |
| } |
| |
| public void setDeltaPropagationActive(boolean isDeltaPropagationActive) { |
| this.isDeltaPropagationActive = isDeltaPropagationActive; |
| } |
| |
| public boolean isDeltaPropagationActive() { |
| return isDeltaPropagationActive; |
| } |
| |
| public void setTracebackStepISAActive(boolean isTracebackStepISAActive){ |
| this.isTracebackStepISAActive = isTracebackStepISAActive; |
| } |
| |
| public boolean isTracebackStepISAActive(){ |
| return isTracebackStepISAActive; |
| } |
| |
| public boolean isUnusedDetectionActive() { |
| return isUnusedDetectionActive; |
| } |
| |
| public void setUnusedDetectionActive(boolean isUnusedDetectionActive) { |
| this.isUnusedDetectionActive = isUnusedDetectionActive; |
| } |
| |
| public boolean isOperationCallSelectionActive() { |
| return isOperationCallSelectionActive; |
| } |
| |
| public void setOperationCallSelectionActive(boolean isOperationCallSelectionActive) { |
| this.isOperationCallSelectionActive = isOperationCallSelectionActive; |
| } |
| |
| public String getActivationString() { |
| StringBuilder activationInformation = new StringBuilder(); |
| |
| activationInformation.append("[TM="); |
| activationInformation.append(isTracebackStepISAActive); |
| activationInformation.append("]"); |
| |
| activationInformation.append("[DP="); |
| activationInformation.append(isDeltaPropagationActive); |
| activationInformation.append("]"); |
| |
| activationInformation.append("[UD="); |
| activationInformation.append(isUnusedDetectionActive); |
| activationInformation.append("]"); |
| |
| return activationInformation.toString(); |
| } |
| |
| // Level 3 Optimization |
| // TODO: Add level 3 optimizations |
| |
| public String getOptionDescription() { |
| return optionDescription; |
| } |
| |
| } |