/** * Retrieves the value associated with the provided iteration of the given optimizing job. * * @param iteration The job iteration for which to retrieve the value. * @return The value associated with the provided iteration of the given optimizing job. * @throws SLAMDException If a problem occurs while trying to determine the value for the given * optimizing job iteration. */ @Override() public double getIterationOptimizationValue(Job iteration) throws SLAMDException { StatTracker[] trackers = iteration.getStatTrackers(optimizeStat); if ((trackers == null) || (trackers.length == 0)) { throw new SLAMDException( "The provided optimizing job iteration did " + "not include any values for the statistic to " + "optimize, \"" + optimizeStat + "\"."); } StatTracker tracker = trackers[0].newInstance(); tracker.aggregate(trackers); double summaryValue = tracker.getSummaryValue(); iteration.slamdServer.logMessage( Constants.LOG_LEVEL_JOB_DEBUG, "SingleStatisticWithReplicationLatency" + "OptimizationAlgorithm." + "getIterationOptimizationValue(" + iteration.getJobID() + ") returning " + summaryValue); return summaryValue; }
/** * Indicates whether the provided job iteration has an acceptable CPU utilization. * * @param iteration The iteration for which to make the determination. * @return <CODE>true</CODE> if the CPU utilization for the provided iteration is acceptable, or * <CODE>false</CODE> if not. * @throws SLAMDException If the provided iteration does not include sufficient CPU utilization * data to make the determination. */ private boolean isAcceptableReplicationLatency(Job iteration) throws SLAMDException { boolean latencyFound = false; String className = ReplicationLatencyResourceMonitor.class.getName(); ResourceMonitorStatTracker[] monitorTrackers = iteration.getResourceMonitorStatTrackersForClass(className); for (int i = 0; i < monitorTrackers.length; i++) { StatTracker tracker = monitorTrackers[i].getStatTracker(); String name = tracker.getDisplayName(); if ((tracker instanceof TimeTracker) && name.endsWith(ReplicationLatencyResourceMonitor.STAT_TRACKER_REPLICATION_LATENCY)) { latencyFound = true; if (maxLatency > 0) { TimeTracker latencyTimer = (TimeTracker) tracker; double averageLatency = latencyTimer.getAverageDuration(); if (averageLatency > maxLatency) { return false; } int[] intervalDurations = latencyTimer.getIntervalDurations(); int[] intervalCounts = latencyTimer.getIntervalCounts(); int numIntervals = intervalCounts.length; int quarterOfIntervals = numIntervals / 4; int firstTotal = 0; int firstCount = 0; int lastTotal = 0; int lastCount = 0; for (int j = 0; j < quarterOfIntervals; j++) { firstTotal += intervalDurations[j]; firstCount += intervalCounts[j]; lastTotal += intervalDurations[numIntervals - quarterOfIntervals + j]; lastCount += intervalCounts[numIntervals - quarterOfIntervals + j]; } if ((firstCount == 0) || (lastCount == 0)) { return false; } double firstAvg = 1.0 * firstTotal / firstCount; double lastAvg = 1.0 * lastTotal / lastCount; if (lastAvg > firstAvg) { double pctIncrease = (lastAvg - firstAvg) / firstAvg * 100.0; if (pctIncrease > maxIncrease) { return false; } } } } } if (!latencyFound) { throw new SLAMDException( "The provided job iteration did not include " + "any replication latency data."); } return true; }
/** * Initializes this optimization algorithm with the provided set of parameters for the given * optimizing job. * * @param optimizingJob The optimizing job with which this optimization algorithm will be used. * @param parameters The parameter list containing the parameter values provided by the end user * when scheduling the optimizing job. * @throws InvalidValueException If the contents of the provided parameter list are not valid for * use with this optimization algorithm. */ @Override() public void initializeOptimizationAlgorithm(OptimizingJob optimizingJob, ParameterList parameters) throws InvalidValueException { this.optimizingJob = optimizingJob; String[] monitorClients = optimizingJob.getResourceMonitorClients(); if ((monitorClients == null) || (monitorClients.length == 0)) { throw new InvalidValueException( "No resource monitor clients have been " + "requested for this optimizing job. " + "At least one is required to provide " + "replication latency data."); } // Get the optimization statistic parameter and name. optimizeStatParameter = parameters.getMultiChoiceParameter(PARAM_OPTIMIZE_STAT); if ((optimizeStatParameter == null) || (!optimizeStatParameter.hasValue())) { throw new InvalidValueException("No value provided for the statistic " + "to optimize"); } optimizeStat = optimizeStatParameter.getStringValue(); // Get the optimization type parameter and value. optimizeTypeParameter = parameters.getMultiChoiceParameter(PARAM_OPTIMIZE_TYPE); if ((optimizeTypeParameter == null) || (!optimizeTypeParameter.hasValue())) { throw new InvalidValueException("No value provided for the " + "optimization type"); } String optimizeTypeStr = optimizeTypeParameter.getStringValue(); if (optimizeTypeStr.equalsIgnoreCase(Constants.OPTIMIZE_TYPE_MAXIMIZE)) { optimizeType = OPTIMIZE_TYPE_MAXIMIZE; } else if (optimizeTypeStr.equalsIgnoreCase(Constants.OPTIMIZE_TYPE_MINIMIZE)) { optimizeType = OPTIMIZE_TYPE_MINIMIZE; } else { throw new InvalidValueException( "Invalid value \"" + optimizeTypeStr + "\" for optimization type."); } // Get the maximum percent increase parameter and value. maxIncreaseParameter = parameters.getFloatParameter(PARAM_MAX_PERCENT_INCREASE); if ((maxIncreaseParameter == null) || (!maxIncreaseParameter.hasValue())) { throw new InvalidValueException( "No value provided for the maximum " + "allowed percentage increase in " + "replication latency."); } maxIncrease = maxIncreaseParameter.getFloatValue(); // Get the maximum latency parameter and value. maxLatencyParameter = parameters.getFloatParameter(PARAM_MAX_REPLICA_LATENCY); if ((maxLatencyParameter == null) || (!maxLatencyParameter.hasValue())) { maxLatency = -1.0; } else { maxLatency = maxLatencyParameter.getFloatValue(); } // Get the minimum percent improvement required for a new best iteration. minPctImprovement = 0.0F; minPctImprovementParameter = parameters.getFloatParameter(PARAM_MIN_PCT_IMPROVEMENT); if ((minPctImprovementParameter != null) && minPctImprovementParameter.hasValue()) { minPctImprovement = minPctImprovementParameter.getFloatValue(); } // See If the provided optimizing job has run any iterations so far. If so, // then look through them to determine the best value so far. bestValueSoFar = Double.NaN; Job[] iterations = optimizingJob.getAssociatedJobs(); if (iterations != null) { for (int i = 0; i < iterations.length; i++) { try { if (!isAcceptableReplicationLatency(iterations[i])) { continue; } } catch (Exception e) { } StatTracker[] trackers = iterations[i].getStatTrackers(optimizeStat); if ((trackers != null) && (trackers.length > 0)) { StatTracker tracker = trackers[0].newInstance(); tracker.aggregate(trackers); double value = tracker.getSummaryValue(); if (Double.isNaN(bestValueSoFar)) { bestValueSoFar = value; } else if ((optimizeType == OPTIMIZE_TYPE_MAXIMIZE) && (value > bestValueSoFar) && (value >= (bestValueSoFar + bestValueSoFar * minPctImprovement))) { bestValueSoFar = value; } else if ((optimizeType == OPTIMIZE_TYPE_MINIMIZE) && (value < bestValueSoFar) && (value <= (bestValueSoFar - bestValueSoFar * minPctImprovement))) { bestValueSoFar = value; } } } } SLAMDServer slamdServer = optimizingJob.slamdServer; slamdServer.logMessage( Constants.LOG_LEVEL_JOB_DEBUG, "SingleStatisticWithReplicationLatencyOptimization" + "Algorithm.initializeOptimizationAlgorith(" + optimizingJob.getOptimizingJobID() + ") best so far is " + String.valueOf(bestValueSoFar)); }
/** * Indicates whether the provided job iteration has an acceptable CPU utilization. * * @param iteration The iteration for which to make the determination. * @return <CODE>true</CODE> if the CPU utilization for the provided iteration is acceptable, or * <CODE>false</CODE> if not. * @throws SLAMDException If the provided iteration does not include sufficient CPU utilization * data to make the determination. */ private boolean isAcceptableCPUUtilization(Job iteration) throws SLAMDException { SLAMDServer slamdServer = iteration.slamdServer; boolean utilizationFound = false; String className = VMStatResourceMonitor.class.getName(); ResourceMonitorStatTracker[] monitorTrackers = iteration.getResourceMonitorStatTrackersForClass(className); for (int i = 0; i < monitorTrackers.length; i++) { StatTracker tracker = monitorTrackers[i].getStatTracker(); String name = tracker.getDisplayName(); if ((tracker instanceof StackedValueTracker) && name.endsWith(VMStatResourceMonitor.STAT_TRACKER_CPU_UTILIZATION)) { utilizationFound = true; StackedValueTracker utilizationTracker = (StackedValueTracker) tracker; double userTime = utilizationTracker.getAverageValue(VMStatResourceMonitor.UTILIZATION_CATEGORY_USER); double systemTime = utilizationTracker.getAverageValue(VMStatResourceMonitor.UTILIZATION_CATEGORY_SYSTEM); double busyTime = userTime + systemTime; switch (utilizationComponent) { case UTILIZATION_COMPONENT_USER_TIME: if (userTime > maxUtilization) { slamdServer.logMessage( Constants.LOG_LEVEL_JOB_DEBUG, "SingleStatisticWithCPUUtilization" + "OptimizationAlgorithm.isAcceptableCPU" + "Utilization(" + iteration.getJobID() + ") returning false because user time of " + userTime + " for stat " + tracker.getDisplayName() + " exceeded the maximum allowed of " + maxUtilization); return false; } break; case UTILIZATION_COMPONENT_SYSTEM_TIME: if (systemTime > maxUtilization) { slamdServer.logMessage( Constants.LOG_LEVEL_JOB_DEBUG, "SingleStatisticWithCPUUtilization" + "OptimizationAlgorithm.isAcceptableCPU" + "Utilization(" + iteration.getJobID() + ") returning false because system time " + "of " + systemTime + " for stat " + tracker.getDisplayName() + " exceeded the maximum allowed of " + maxUtilization); return false; } break; case UTILIZATION_COMPONENT_BUSY_TIME: if (busyTime > maxUtilization) { slamdServer.logMessage( Constants.LOG_LEVEL_JOB_DEBUG, "SingleStatisticWithCPUUtilization" + "OptimizationAlgorithm.isAcceptableCPU" + "Utilization(" + iteration.getJobID() + ") returning false because busy time of " + busyTime + " for stat " + tracker.getDisplayName() + " exceeded the maximum allowed of " + maxUtilization); return false; } break; default: slamdServer.logMessage( Constants.LOG_LEVEL_JOB_DEBUG, "SingleStatisticWithCPUUtilization" + "OptimizationAlgorithm.isAcceptableCPU" + "Utilization(" + iteration.getJobID() + ") returning false because an unknown " + "utilization component of " + utilizationComponent + " is in use."); return false; } } else if ((tracker instanceof IntegerValueTracker) && ((utilizationComponent == UTILIZATION_COMPONENT_USER_TIME) && name.endsWith(VMStatResourceMonitor.STAT_TRACKER_CPU_USER)) || ((utilizationComponent == UTILIZATION_COMPONENT_SYSTEM_TIME) && name.endsWith(VMStatResourceMonitor.STAT_TRACKER_CPU_SYSTEM)) || ((utilizationComponent == UTILIZATION_COMPONENT_BUSY_TIME) && name.endsWith(VMStatResourceMonitor.STAT_TRACKER_CPU_BUSY))) { utilizationFound = true; double value = ((IntegerValueTracker) tracker).getAverageValue(); if (value > maxUtilization) { slamdServer.logMessage( Constants.LOG_LEVEL_JOB_DEBUG, "SingleStatisticWithCPUUtilization" + "OptimizationAlgorithm.isAcceptableCPU" + "Utilization(" + iteration.getJobID() + ") returning false because value of " + value + " for stat " + tracker.getDisplayName() + " exceeded the maximum allowed of " + maxUtilization); return false; } } } if (!utilizationFound) { throw new SLAMDException( "The provided job iteration did not include " + "any CPU utilization data."); } slamdServer.logMessage( Constants.LOG_LEVEL_JOB_DEBUG, "SingleStatisticWithCPUUtilizationOptimization" + "Algorithm.isAcceptableCPUUtilization(" + iteration.getJobID() + ") returning true."); return true; }