All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ca.appsimulations.jlqninterface.bottleneck.BottleneckAlgorithm Maven / Gradle / Ivy

Go to download

Java API to solve, analyze and manipulate Layered Qeueuing Network (LQN) models

There is a newer version: 1.1.0
Show newest version
package ca.appsimulations.jlqninterface.bottleneck;

import ca.appsimulations.jlqninterface.algorithm.Algorithm;
import ca.appsimulations.jlqninterface.configuration.ConfigurationService;
import ca.appsimulations.jlqninterface.lqn.entities.*;
import ca.appsimulations.jlqninterface.lqn.model.LqnModel;
import ca.appsimulations.jlqninterface.lqn.model.handler.LqnModifier;
import ca.appsimulations.jlqninterface.lqn.model.handler.LqnSolver;
import ca.appsimulations.jlqninterface.lqn.model.parser.LqnInputParser;
import ca.appsimulations.jlqninterface.lqn.model.parser.LqnResultParser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * @author Yasir Shoaib (2011,2012) Contributors: Yasir Shoaib - Implementation
 * 

* Some LQN classes and their members are outlined as UML class diagrams * in LQNS User Manual. For details regarding these LQN classes and * members refer to LQNS User Manual. */ @Slf4j @Component public class BottleneckAlgorithm extends Algorithm { private LqnInputParser lqnInputParser; private LqnResultParser lqnResultParser; private LqnModifier lqnModifier; private BottleneckIdentifier bottleneckIdentifier; private ArrayList messages; @Autowired public BottleneckAlgorithm(ConfigurationService configurationService, LqnModel lqnModel) { super(configurationService, lqnModel); this.lqnInputParser = new LqnInputParser(lqnModel, true); this.lqnResultParser = new LqnResultParser(lqnModel); this.lqnModifier = new LqnModifier(lqnModel); this.bottleneckIdentifier = new BottleneckIdentifier(lqnModel); this.messages = new ArrayList(); } @Override public void setup() { log.info( "==============================================================================================================="); log.info("Setting up algorithm..."); lqnModel.resetAll(); log.debug("Parsing input file " + this.configurationService.inputFilePath()); try { lqnInputParser.parseFile(this.configurationService.inputFilePath()); } catch (FileNotFoundException fnfe) { log.debug("[FileNotFoundException]: " + fnfe.getMessage()); fnfe.printStackTrace(); } log.debug("Linking entries..."); log.debug("Building DestTree..."); lqnModel.buildDestTree(); try { lqnModel.organizeTasksBasedBelowSize(); } catch (Exception e) { log.debug("[Exception]: " + e.getMessage()); e.printStackTrace(); return; } log.debug(""); lqnModel.printDestTree(); log.debug(""); log.info("Initial model details:"); bottleneckIdentifier.printBStrengthTable(); log.info(""); log.info("DONE Initializing."); log.info(""); } //return false if problem solving private boolean findBottlenecks(ArrayList bStrengthTable, ArrayList unchangeable, boolean solveModel) { log.info("Finding bottleneck..."); log.info(""); bStrengthTable.clear(); if (solveModel) { boolean isSolved = solveAndParseModel(); if (!isSolved) { return false; } } bStrengthTable.addAll(bottleneckIdentifier.buildBStrengthTable(this.configurationService.satThreshold(), unchangeable, this.configurationService .bottleneckMaxBStrengthTaskOnly())); log.info("FindingBottleneck...DONE"); log.info(""); return true; } private boolean solveAndParseModel() { log.info("Solving model..."); log.info(""); log.debug("Linking Entries..."); lqnModel.linkEntries(); log.debug("Building Dest Tree..."); lqnModel.buildDestTree(); try { lqnModel.organizeTasksBasedBelowSize(); } catch (Exception e) { log.debug("[Exception]: " + e.getMessage()); e.printStackTrace(); System.exit(1); } lqnModel.printDestTree(); log.debug(""); log.debug("Parsing and updating XML model"); log.debug("input file: " + configurationService.inputFilePath()); log.debug("output model to: " + configurationService.autoInputFilePath()); log.debug(""); //update from in-memory representation of the model, output the updated model to outputFilePath lqnModifier.parseAndUpdateXML(lqnInputParser.getLQXCData(false), configurationService.inputFilePath(), configurationService.autoInputFilePath()); boolean result = LqnSolver.solveLqns(configurationService.autoInputFilePath(), lqnResultParser, configurationService.lqnXmlOutputFilePath()); if (result == false) { log.info("Problem solving."); return false; } log.info("Solving Model...DONE."); log.info(""); return true; } //return response time of first ref type task public double findMaxResourcePerformance(ArrayList bSet) { log.info("Finding max resource performance..."); boolean flag = false; HashMap hMap = new HashMap(); int tmpMaxVMReplicas = this.configurationService.maxVMReplicas(); int tmpMaxProcsPerVM = this.configurationService.maxProcsPerVM(); while (!flag && (tmpMaxProcsPerVM >= 1 || tmpMaxVMReplicas >= 1)) { log.info("-----------------------------------------------------------------------------"); log.info("Solving to find maxResourcePerformance: maxVMReplicas: " + tmpMaxVMReplicas + " maxProcsPerVM: " + tmpMaxProcsPerVM); log.info("-----------------------------------------------------------------------------"); for (Processor p : lqnModel.processors()) { if (tmpMaxProcsPerVM >= 1 || tmpMaxVMReplicas >= 1) { if (p.getMultiplicity() != LqnConstants.INFINITY.getConstantValue() && p.getScheduling() != ProcessorSchedulingType.INF) { p.setMultiplicity(Math.max(tmpMaxVMReplicas, tmpMaxProcsPerVM)); } } if (tmpMaxVMReplicas >= 1) { for (Task t : p.getTasks()) { if (t.getMultiplicity() != LqnConstants.INFINITY.getConstantValue() && t.getScheduling() != TaskSchedulingType.INF && t.getScheduling() != TaskSchedulingType.REF) { int mult = t.getMultiplicity(); if (!hMap.containsKey(t)) { hMap.put(t, t.getMultiplicity()); } else { mult = hMap.get(t); } //System.out.println("[Algorithm1] Replicating: " + t); t.setMultiplicity((tmpMaxVMReplicas) * mult); } } } } bSet.clear(); flag = findBottlenecks(bSet, null, true); if (!flag) { flag = true; if (tmpMaxVMReplicas > 1) { tmpMaxVMReplicas--; flag = false; } if (tmpMaxProcsPerVM > 1) { tmpMaxProcsPerVM--; flag = false; } } } if (!flag) { return LqnConstants.UNDEF.getConstantValue(); } log.info("=============================================================="); log.info("maxReplicasPerVM tried: " + tmpMaxVMReplicas); log.info("maxProcessorsPerVM tried: " + tmpMaxProcsPerVM); log.info("Max resource performance"); double responseTime = this.getFirstRefTaskResponseTime(); log.info("=============================================================="); log.info("Finding max resource performance...DONE"); return responseTime; } private double getFirstRefTaskResponseTime() { ArrayList refTasks = lqnModel.buildRefTasksFromExistingTasks(); double responseTime = this.getFirstRefTaskResponseTime(refTasks, true); return responseTime; } private double getFirstRefTaskResponseTime(ArrayList refTasks, boolean printInfo) { Task t = refTasks.get(0); Entry e = refTasks.get(0).getEntries().get(0); ActivityPhases ap = (ActivityPhases) refTasks.get(0).getEntries().get(0).getActivityAtPhase(1); double responseTime = ap.getResult().getService_time(); if (printInfo) { log.info("Task " + t + " entry: " + e + " activity " + ap + " ph1 response time: " + responseTime); } return responseTime; } private int setupInitialSolvableConf_OLD(ArrayList bSet, ArrayList unchangeable, String initialTry) { boolean endLoop = false; String strChange; int changeCount = 0; int addedVMs = 0; int loopCount = 0; Task initialTask = null; log.info("Finding initial configuration that solves model..."); log.info(""); while (!endLoop) { loopCount++; //unable to solve model in first try //therefore go in a loop until model is solvable. if (loopCount == 1) { if (initialTry.equals("") || initialTry == null) { continue; } Task t = lqnModel.taskByName(initialTry); if (t == null) { continue; } initialTask = t; boolean wasDuplicated = this.processTaskDuplication(t, 1, unchangeable, addedVMs); if (!wasDuplicated) { log.debug("Task " + t + " was not replicated"); continue; } changeCount++; addedVMs++; log.info("======================================="); strChange = "InitialSolvableConf Change" + changeCount + ": " + "TASK: " + t + " VM = " + t.getDuplicationCount() + " in next loop"; log.info(strChange); log.info("======================================="); messages.add(strChange); } else { ArrayList ent = (ArrayList) lqnModel.tasks().clone(); for (Task t : ent) { if (t.getMultiplicity() != LqnConstants.INFINITY.getConstantValue() && t.getScheduling() != TaskSchedulingType.INF && t.getScheduling() != TaskSchedulingType.REF) { if (loopCount == 2) { if (initialTask != null) { if (t == initialTask) { continue; } } } boolean wasDuplicated = this.processTaskDuplication(t, 1, unchangeable, addedVMs); if (!wasDuplicated) { log.debug("Task " + t + " was not replicated"); continue; } changeCount++; addedVMs++; log.info("======================================="); strChange = "InitialSolvableConf Change" + changeCount + ": " + "TASK: " + t + " VM = " + t.getDuplicationCount() + " in next loop"; log.info(strChange); log.info("======================================="); messages.add(strChange); } } } endLoop = findBottlenecks(bSet, unchangeable, true); log.info("Bottlenecks: " + bSet.toString()); log.info("Unchangeable: " + unchangeable.toString()); if (!endLoop && ((bSet == null) || (bSet.isEmpty()))) { if (loopCount > 4) { endLoop = true; } continue; } else if ((bSet == null) || (bSet.isEmpty())) { log.info("No more bottlenecks - DONE"); endLoop = true; } } log.info("Finding initial configuration that solves model...DONE"); log.info(""); return changeCount; } private int setupInitialSolvableConf(ArrayList bSet, ArrayList unchangeable, String initialTry) { boolean endLoop = false; String strChange; int changeCount = 0; int addedVMs = 0; int loopCount = 0; Task initialTask = lqnModel.taskByName(initialTry); log.info("Finding initial configuration that solves model..."); log.info(""); log.info("Bottlenecks: " + bSet.toString()); log.info("Unchangeable: " + unchangeable.toString()); if (initialTask != null) { if (!bSet.contains(initialTask)) { bSet.add(0, initialTask); } } ArrayList bSetClone = (ArrayList) bSet.clone(); bSet.clear(); for (Entity b : bSetClone) { if (b instanceof Task) { Task t = lqnModel.taskByName(((Task) b).getName()); if (bSet.contains(t.getProcessor())) { //since processor of this task is also a bottleneck, first add the processor log.info("Skipping task " + t + " duplication as parent processor is also bottleneck"); continue; } boolean wasDuplicated = this.processTaskDuplication(t, 1, unchangeable, addedVMs); if (!wasDuplicated) { log.debug("Task " + t + " was not replicated"); continue; } changeCount++; addedVMs++; log.info("======================================="); strChange = "InitialSolvableConf Change" + changeCount + ": " + "TASK: " + t + " VM = " + t.getDuplicationCount() + " in next loop"; log.info(strChange); log.info("======================================="); messages.add(strChange); } else if (b instanceof Processor) { Processor p = lqnModel.processorByName(((Processor) b).getName()); boolean wasMultiplicated = processProcessorMultiplication(p, 1, unchangeable); if (!wasMultiplicated) { log.debug("Processor " + p + " was not duplicated"); continue; } changeCount++; log.info("======================================="); strChange = "InitialSolvableConf Change" + changeCount + ": " + "PROC: " + p + " multiplicity = " + p.getMultiplicity() + " in next loop"; log.info(strChange); log.info("======================================="); messages.add(strChange); } endLoop = findBottlenecks(bSet, unchangeable, true); log.info("Bottlenecks: " + bSet.toString()); log.info("Unchangeable: " + unchangeable.toString()); if (endLoop) { log.info("No more bottlenecks - DONE"); break; } else if (!endLoop && ((bSet == null) || (bSet.isEmpty()))) { if (loopCount > 4) { endLoop = true; break; } } else if ((bSet == null) || (bSet.isEmpty())) { log.info("No more bottlenecks - DONE"); endLoop = true; break; } } //bSet.clear(); while (!endLoop) { loopCount++; //unable to solve model in first try //therefore go in a loop until model is solvable. ArrayList ent = (ArrayList) lqnModel.tasks().clone(); for (Task t : ent) { if (t.getMultiplicity() != LqnConstants.INFINITY.getConstantValue() && t.getScheduling() != TaskSchedulingType.INF && t.getScheduling() != TaskSchedulingType.REF) { boolean wasDuplicated = this.processTaskDuplication(t, 1, unchangeable, addedVMs); if (!wasDuplicated) { log.debug("Task " + t + " was not replicated"); continue; } changeCount++; addedVMs++; log.info("======================================="); strChange = "InitialSolvableConf Change" + changeCount + ": " + "TASK: " + t + " VM = " + t.getDuplicationCount() + " in next loop"; log.info(strChange); log.info("======================================="); messages.add(strChange); } } endLoop = findBottlenecks(bSet, unchangeable, true); log.info("Bottlenecks: " + bSet.toString()); log.info("Unchangeable: " + unchangeable.toString()); if (endLoop) { log.info("No more bottlenecks - DONE"); break; } else if (!endLoop && ((bSet == null) || (bSet.isEmpty()))) { if (loopCount > 4) { endLoop = true; } continue; } else if ((bSet == null) || (bSet.isEmpty())) { log.info("No more bottlenecks - DONE"); endLoop = true; } } log.info("Finding initial configuration that solves model...DONE"); log.info(""); return changeCount; } /** * @param t * @param duplicationAdded * @param unchangeable * @param addedVMs * @return if process was duplicated */ private boolean processTaskDuplication(Task t, int duplicationAdded, ArrayList unchangeable, int addedVMs) { boolean wasDuplicated = true; if (t.getDuplicationCount() >= configurationService.maxVMReplicas()) { if (unchangeable != null && (!unchangeable.contains(t))) { unchangeable.add(t); } log.info(t.getName() + " has reached maxReplicas: "); return false; } else if (addedVMs >= configurationService.spareVMs()) { if (unchangeable != null && (!unchangeable.contains(t))) { unchangeable.add(t); } log.info("No more VMs available."); return false; } wasDuplicated = t.getProcessor().duplicateSelfAndTasksDepth(); return wasDuplicated; } private boolean processProcessorMultiplication(Processor p, int multiplicityAdded, ArrayList unchangeable) { if (p.getMultiplicity() >= configurationService.maxProcsPerVM()) { if (!unchangeable.contains(p)) { unchangeable.add(p); } log.info(p.getName() + " " + "multiplicity: " + p.getMultiplicity() + " has reached maxReplicas: " + configurationService.maxProcsPerVM()); return false; } p.setMultiplicity(p.getMultiplicity() + multiplicityAdded); return true; } @PostConstruct @Override public void run() { String strMsg; int addedVMs = 0; int noChangesCount = 0; ArrayList bSet = new ArrayList(); ArrayList bSetMaxRes = new ArrayList(); setup(); double maxResResponse = findMaxResourcePerformance(bSet); bSetMaxRes = (ArrayList) bSet.clone(); if (maxResResponse == LqnConstants.UNDEF.getConstantValue()) { bottleneckIdentifier.printBStrengthTable(); log.info("Unable to find model solution for maximum resources. DONE."); return; } else if (maxResResponse > configurationService.responseTimeObjective()) { bottleneckIdentifier.printBStrengthTable(); log.info("Max Resource ResponseTime: " + maxResResponse); log.info("ResponseTime Objective: " + configurationService.responseTimeObjective()); log.info("Unable to find model solution: Max Resource ResponseTime > responseTimeObjective. DONE"); return; } //get maxBStrength task name based on model run for findMaxResourcePerformance. String initialTry = null; if (bottleneckIdentifier.getMaxBStrengthTask() == null) { log.info("No maximum bottleneck Task"); } else { initialTry = bottleneckIdentifier.getMaxBStrengthTask().getName(); setup(); } int loopCount = 1; int changeCount = 0; ArrayList refTasks = lqnModel.buildRefTasksFromExistingTasks(); ArrayList unchangeable = new ArrayList(); int curChangesCount = 0; while (true) { bSet.clear(); boolean flag = findBottlenecks(bSet, unchangeable, true); //if unable to solve model in the first try if (flag == false && (loopCount == 1)) { int initialChanges = this.setupInitialSolvableConf(bSetMaxRes, unchangeable, initialTry); findBottlenecks(bSet, unchangeable, true); changeCount = changeCount + initialChanges; if (initialChanges == 0) { log.info("Unable to find model solution"); break; } } else if (flag == false) { bottleneckIdentifier.printBStrengthTable(); log.info("Unable to find model solution"); break; } double responseTime = this.getFirstRefTaskResponseTime(refTasks, false); if (configurationService.responseTimeObjective() >= responseTime) { log.info("Met response Time Objectives - DONE"); log.info(String.format("Objective: %.3f, ResponseTime: %.3f", configurationService.responseTimeObjective(), responseTime)); break; } log.info("Bottlenecks: " + bSet.toString()); log.info("Unchangeable: " + unchangeable.toString()); if ((bSet == null) || (bSet.isEmpty())) { log.info("No more bottlenecks - DONE"); break; } curChangesCount = 0; for (Entity b : bSet) { if (b instanceof Task) { Task t = (Task) b; if (bSet.contains(t.getProcessor())) { //since processor of this task is also a bottleneck, first add the processor log.info("Skipping task " + t + " duplication as parent processor is also bottleneck"); continue; } boolean wasDuplicated = this.processTaskDuplication(t, 1, unchangeable, addedVMs); if (!wasDuplicated) { strMsg = "Loop" + loopCount + " Limit reached: TASK: " + t + " VM not replicated in next loop"; messages.add(strMsg); log.info(strMsg); continue; } changeCount++; addedVMs++; log.info("======================================="); strMsg = "Loop" + loopCount + " Change" + changeCount + ": " + "TASK: " + t + " VM = " + t.getDuplicationCount() + " in next loop"; log.info(strMsg); log.info("======================================="); messages.add(strMsg); curChangesCount++; } else if (b instanceof Processor) { Processor p = (Processor) b; boolean wasMultiplicated = processProcessorMultiplication(p, 1, unchangeable); if (!wasMultiplicated) { strMsg = "Loop" + loopCount + " Limit reached: PROC: " + p + " not duplicated in next loop"; messages.add(strMsg); log.info(strMsg); continue; } changeCount++; log.info("======================================="); strMsg = "Loop" + loopCount + " Change" + changeCount + ": " + "PROC: " + p + " multiplicity = " + p.getMultiplicity() + " in next loop"; log.info(strMsg); log.info("======================================="); messages.add(strMsg); curChangesCount++; } } log.info("Loop " + loopCount + " DONE------------------------------------------------------------------------------"); log.info("Running..."); log.info(""); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (curChangesCount == 0) { noChangesCount++; } else { noChangesCount = 0; } if (noChangesCount >= 5) { log.info("No changes for previous 5 loops. DONE"); break; } loopCount++; } log.info("Summary of changes"); log.info("----------------------"); for (int i = 0; i < messages.size(); i++) { log.info(messages.get(i)); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy