EMMA Coverage Report (generated Sun Feb 05 10:43:15 CET 2012)
[all classes][de.uka.ipd.sdq.dsexplore.opt4j.optimizer.heuristic.operators.impl]

COVERAGE SUMMARY FOR SOURCE FILE [ServerConsolidationImpl.java]

nameclass, %method, %block, %line, %
ServerConsolidationImpl.java0%   (0/1)0%   (0/6)0%   (0/328)0%   (0/74)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ServerConsolidationImpl0%   (0/1)0%   (0/6)0%   (0/328)0%   (0/74)
<static initializer> 0%   (0/1)0%   (0/5)0%   (0/3)
ServerConsolidationImpl (Copy, DSEIndividualBuilder, DSEWorkflowConfiguration... 0%   (0/1)0%   (0/37)0%   (0/10)
doesMatchPrecondition (DSEIndividual): boolean 0%   (0/1)0%   (0/11)0%   (0/1)
getCandidateWeight (UtilisationResult): double 0%   (0/1)0%   (0/9)0%   (0/1)
getHeuristicCandidateForResourceType (DSEIndividual, ResourceType): List 0%   (0/1)0%   (0/234)0%   (0/53)
getHeuristicCandidates (DSEIndividual, UtilisationResultCacheAndHelper): List 0%   (0/1)0%   (0/32)0%   (0/6)

1package de.uka.ipd.sdq.dsexplore.opt4j.optimizer.heuristic.operators.impl;
2 
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.List;
6import java.util.Random;
7import java.util.Set;
8 
9import org.apache.log4j.Logger;
10import org.eclipse.emf.ecore.EObject;
11import org.opt4j.core.problem.Genotype;
12import org.opt4j.operator.copy.Copy;
13 
14import de.uka.ipd.sdq.dsexplore.helper.EMFHelper;
15import de.uka.ipd.sdq.dsexplore.launch.DSEWorkflowConfiguration;
16import de.uka.ipd.sdq.dsexplore.opt4j.genotype.DesignDecisionGenotype;
17import de.uka.ipd.sdq.dsexplore.opt4j.optimizer.heuristic.operators.AbstractTactic;
18import de.uka.ipd.sdq.dsexplore.opt4j.optimizer.heuristic.operators.TacticsResultCandidate;
19import de.uka.ipd.sdq.dsexplore.opt4j.optimizer.heuristic.operators.UtilisationResultCacheAndHelper;
20import de.uka.ipd.sdq.dsexplore.opt4j.representation.DSEIndividual;
21import de.uka.ipd.sdq.dsexplore.opt4j.representation.DSEIndividualBuilder;
22import de.uka.ipd.sdq.dsexplore.qml.handling.QMLConstantsContainer;
23import de.uka.ipd.sdq.pcm.designdecision.AllocationDegree;
24import de.uka.ipd.sdq.pcm.designdecision.Choice;
25import de.uka.ipd.sdq.pcm.designdecision.DegreeOfFreedomInstance;
26import de.uka.ipd.sdq.pcm.designdecision.ClassChoice;
27import de.uka.ipd.sdq.pcm.designdecision.ClassDegree;
28import de.uka.ipd.sdq.pcm.resourceenvironment.ResourceContainer;
29import de.uka.ipd.sdq.pcm.resourcetype.ResourceType;
30import de.uka.ipd.sdq.pcm.resultdecorator.resourceenvironmentdecorator.ProcessingResourceSpecificationResult;
31import de.uka.ipd.sdq.pcm.resultdecorator.resourceenvironmentdecorator.UtilisationResult;
32 
33/**
34 * Implements a server consolidation heuristic. This heuristic finds two
35 * hardly utilised resource containers and reallocates all components of these
36 * two resource containers to one resource container
37 * @author martens, Tom Beyer
38 */
39public class ServerConsolidationImpl extends AbstractTactic {
40        /**
41         * If utilisation is smaller than this double it will be considered
42         * a low utilisation
43         */
44        private double thresholdLowUtilisation;        
45        
46        private double maxUtilisationForOtherServers = 0.9;
47        
48        private Random generator = new Random();
49 
50        private UtilisationResultCacheAndHelper resultCache = new UtilisationResultCacheAndHelper();
51        
52        protected static Logger logger = Logger.getLogger(ServerConsolidationImpl.class
53                        .getName());
54 
55        /**
56         * 
57         * @param copy Used to copy genotype
58         * @param individualBuilder Used to build individual
59         */
60        public ServerConsolidationImpl(Copy<Genotype> copy,
61                        DSEIndividualBuilder individualBuilder, DSEWorkflowConfiguration configuration) {
62                super(copy, individualBuilder, configuration, 
63                                new String[] {
64                                        QMLConstantsContainer.QUALITY_ATTRIBUTE_DIMENSION_COST_DEFINITION_PATH,
65                                        QMLConstantsContainer.QUALITY_ATTRIBUTE_DIMENSION_POFOD_DEFINITION_PATH});
66                // set config
67                setHeuristicWeight(configuration.getServerConsolidationWeight());
68                thresholdLowUtilisation = configuration.getServerConsolidationThresholdLowUtilisation();
69        }
70        
71        
72        /**
73         * Checks the precondition by trying to generate candidates and see whether 
74         * the list is larger than 0.  
75         * @param individual
76         * @return
77         */
78        public boolean doesMatchPrecondition(DSEIndividual individual) {
79                return getHeuristicCandidates(individual, this.resultCache).size() > 0;
80        }
81 
82        /**
83         * Generates collection of candidates by applying the server consolidation heuristic
84         * 
85         * Checks whether there is one resource container r with a 
86         * utilisation_r <= THRESHOLD_LOW_UTILISATION and whether 
87         * there are another n used resource containers x_1 to x_n with 
88         * enough free capacity (keeping the utilisation under 0.9) so that 
89         * the the load of r could be distributed: 
90         * Sum_{i=1}^{n} utilisation_x_i + utilisation_r < 0.9*n
91         * The number of free resource container n must not exceed the number of components
92         * deployed to r.
93         * 
94         * TODO: take resource demand of deployed components into account.
95         * TODO: take utilisation of other resources into account.
96         * TODO: The counting of deployed components does not take into account that some
97         * allocation degrees are inactive if subsystems are exchanged. Thus, only genomes where all 
98         * allocation options are active are supported. 
99         * 
100         * 
101         * @param individual Individual which the heuristic should be applied to
102         * @param resultsHelper 
103         */
104        public List<TacticsResultCandidate> getHeuristicCandidates(DSEIndividual individual, UtilisationResultCacheAndHelper resultsHelper) {
105                this.resultCache = resultsHelper;
106                
107                List<TacticsResultCandidate> candidates = new ArrayList<TacticsResultCandidate>();
108                
109                Set<ResourceType> resourceTypes = this.resultCache.getResourceTypes(individual);
110                
111                for (ResourceType resourceType : resourceTypes) {
112                        candidates.addAll(getHeuristicCandidateForResourceType(individual, resourceType));
113                }
114                return candidates;
115        }
116 
117 
118        private List<TacticsResultCandidate> getHeuristicCandidateForResourceType(
119                        DSEIndividual individual, ResourceType cpu) {
120                List<TacticsResultCandidate> candidates = new ArrayList<TacticsResultCandidate>();
121                
122                // FIXME: This should actually look for a server that is below the threshold for all its resources. 
123                ProcessingResourceSpecificationResult minUtilisationResult = this.resultCache
124                        .getMinProcUtilisationResult(individual, cpu);
125                
126                if (minUtilisationResult == null 
127                                || minUtilisationResult.getResourceUtilisation() > thresholdLowUtilisation
128                                || cpu == null ){
129                        return candidates;
130                }
131                
132                double utilisation = minUtilisationResult.getResourceUtilisation();
133                ResourceContainer identifiedContainer = minUtilisationResult.getProcessingResourceSpecification_ProcessingResourceSpecificationResult().getResourceContainer_ProcessingResourceSpecification();                
134 
135                TacticsResultCandidate candidate = individualBuilder.buildCandidate(copy.copy(individual.getGenotype()), individual);
136                
137                //Get components deployed to that resource container
138                DesignDecisionGenotype genotype = candidate.getGenotype();
139                List<ClassChoice> componentAllocationToRChoices = new ArrayList<ClassChoice>(genotype.size());
140                for (Choice choice : genotype) {
141                        if (choice instanceof ClassChoice){
142                                ClassChoice enumChoice = (ClassChoice) choice;
143                                DegreeOfFreedomInstance degree = enumChoice.getDegreeOfFreedomInstance();
144                                if (degree instanceof AllocationDegree){
145                                        if (EMFHelper.checkIdentity(enumChoice.getChosenValue(), identifiedContainer)){
146                                                componentAllocationToRChoices.add(enumChoice);
147                                                logger.debug("Found component allocated to underutilised container "+identifiedContainer.getEntityName());
148                                        }
149                                }
150                        }
151                }
152                int numberOfComponentDeployedToR = componentAllocationToRChoices.size();
153                
154                // There should be at least one component to redeploy.
155                if (numberOfComponentDeployedToR > 0){
156 
157                        //Get n servers with lowest utilisation
158                        List<ProcessingResourceSpecificationResult> procUtils = UtilisationResultCacheAndHelper.getProcessingResourceUtilisationResults(individual);
159                        Collections.sort(procUtils, new UtilisationResultCacheAndHelper.UtilisationComparator());
160 
161                        //assume that the load of the server to be removed is caused in equal shares by each deployed component
162                        //then, calculate each components utilisation share 
163                        //TODO: use real share here. 
164                        double utilSharePerComponent = utilisation / numberOfComponentDeployedToR;
165 
166                        //Choose numberOfServersToSpreadTheLoadTo servers to put the components to. 
167                        //can choose a server twice if it has a much lower utilisation that the latter
168                        //tries sort of greedy bin packing. 
169                        for (ProcessingResourceSpecificationResult processingResourceSpecificationResult : procUtils) {
170                                ResourceContainer targetContainer = processingResourceSpecificationResult.getProcessingResourceSpecification_ProcessingResourceSpecificationResult().getResourceContainer_ProcessingResourceSpecification();
171                                if (targetContainer != identifiedContainer
172                                                && EMFHelper.contains(resultCache.getAvailableResourceContainers(individual), targetContainer) // only deploy to allowed containers
173                                                && !EMFHelper.contains(resultCache.getUnusedAvailableResourceContainers(individual), targetContainer)// new container must be used already 
174                                                && EMFHelper.checkIdentity( // and the PR result must be about the same resource type. 
175                                                                processingResourceSpecificationResult.getProcessingResourceSpecification_ProcessingResourceSpecificationResult().getActiveResourceType_ActiveResourceSpecification(),
176                                                                minUtilisationResult.getProcessingResourceSpecification_ProcessingResourceSpecificationResult().getActiveResourceType_ActiveResourceSpecification())){
177                                        
178                                        double util = processingResourceSpecificationResult.getResourceUtilisation();
179                                        int numberOfComponentsToDeployHere =  (int)( (this.maxUtilisationForOtherServers - util) / utilSharePerComponent);
180 
181                                        for (int i = 0; i < numberOfComponentsToDeployHere && componentAllocationToRChoices.size() > 0; i++) {
182                                                ClassChoice reallocateChoice = componentAllocationToRChoices.get(generator.nextInt(componentAllocationToRChoices.size()));
183                                                componentAllocationToRChoices.remove(reallocateChoice);
184                                                EObject newContainer = EMFHelper.retrieveEntityByID(
185                                                                ((ClassDegree)reallocateChoice.getDegreeOfFreedomInstance()).getClassDesignOptions(),
186                                                                targetContainer);
187                                                if (newContainer != null){
188                                                        reallocateChoice.setChosenValue(newContainer);
189                                                } else {
190                                                        // this component cannot be put to the chosen container...
191                                                        // TODO: then put this component to another server instead of just giving up...
192                                                        i--; // will terminate at some point because list componentAllocationToRChoices is also reduced. 
193                                                }
194                                                logger.debug("Reallocate component "+reallocateChoice.getDegreeOfFreedomInstance().getPrimaryChanged()+" to server "+targetContainer);
195                                        }
196                                        if (componentAllocationToRChoices.size() == 0 )
197                                                break;
198                                }
199                        }
200                        if (componentAllocationToRChoices.size() == 0){
201                                //successfully redeployed all components
202                                candidates.add(candidate);
203                                candidate.setCandidateWeight(getCandidateWeight(minUtilisationResult));
204                                candidate.setHeuristic(this);
205                                increaseCounterOfGeneratedCandidates();
206                                //XXX: consider to create several possible reallocations?
207                        }
208                }
209                // else: some components could not be redeployed, return empty list. 
210 
211                /*        if (doesMatchPrecondition(individual)) {
212                        /*
213                 * 1. Find lowest and 2nd lowest utilised resource containers
214                 * 2. Copy individual
215                 * 3. Reallocate all components from one resource container
216                 *    to the other
217                 *
218                        // 1. Find lowest and 2nd lowest utilised resource containers
219                        UtilisationResult minUtilisationResult = UtilisationHelper.getMinProcUtilisationResult(individual);
220                        UtilisationResult minUtilisationResult2 = UtilisationHelper.get2ndMinUtilisationResult(individual);
221                        // 2. Copy individual
222                        TacticsResultCandidate candidate = individualBuilder.buildCandidate(copy.copy(individual.getGenotype()), individual);
223                        ProcessingResourceSpecification minProcessingResourceSpec = ((ProcessingResourceSpecificationResultImpl) minUtilisationResult)
224                                        .getProcessingresourcespecification();
225                        ProcessingResourceSpecification minProcessingResourceSpec2 = ((ProcessingResourceSpecificationResultImpl) minUtilisationResult2)
226                                        .getProcessingresourcespecification();
227                        ResourceContainer resourceContainer = ((ResourceContainer) minProcessingResourceSpec.eContainer());
228                        ResourceContainer resourceContainer2 = ((ResourceContainer) minProcessingResourceSpec2.eContainer());
229                        // 3. Reallocate all components from one resource container to the other
230                        for (Choice choice : candidate.getGenotype()) {
231                                if (choice instanceof ClassChoice) {
232                                        ClassChoice ClassChoice = (ClassChoice)choice;
233                                        if (ClassChoice.getDegreeOfFreedomInstance() instanceof AllocationDegree) {
234                                                if (EMFHelper.checkIdentity(ClassChoice.getEntity(),resourceContainer)) {
235                                                        // deploy all the components you can find to resourceContainer2
236                                                        ClassChoice.setEntity(resourceContainer2);
237                                                }
238                                        }
239                                }
240                        }
241                        candidate.setCandidateWeight(getCandidateWeight(minUtilisationResult, minUtilisationResult2));
242                        candidate.setHeuristic(this);
243                        candidates.add(candidate);
244                        increaseCounterOfGeneratedCandidates();
245                } */
246                return candidates;
247        }
248        
249        /**
250         * Set weight to 1 at this point.
251         * @param u1 Lowest utilised resource container
252         * @return Weight of candidate
253         */
254        private double getCandidateWeight(UtilisationResult u1) {
255                 return ((thresholdLowUtilisation - u1.getResourceUtilisation())/thresholdLowUtilisation);
256        }
257 
258 
259        
260}

[all classes][de.uka.ipd.sdq.dsexplore.opt4j.optimizer.heuristic.operators.impl]
EMMA 2.0.9414 (unsupported private build) (C) Vladimir Roubtsov