Objective.java revision 63360950109af2ce85a962ca61f40b8782f11100
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* ident "%Z%%M% %I% %E% SMI"
*/
/**
* An objective interface. All classes which wish to contribute to the
* Objective Function (OF hence) calculation must implement this
* interface. This interface defines a strategy which can be used to
* make a contribution to the Objective Function calculation.
*
* The OF calculation (which is implemented by <code>Poold</code>)
* consists of determining all possible resource moves across all
* resources. Once all moves are known, all registered objectives
* (i.e. instances of this interface) are called and asked to value
* the move.
*
* Note, the output of this method is constrained to be between -1 and
* 1, representing minimum and maximum desirability of this move in
* terms of this objective. This is enforced by <code>Poold</code> and
* an <code>IllegalOFValueException</code> will be thrown if this
* constraint is broken.
*/
interface Objective
{
/**
* Return the contribution of this objective. The contribution
* is constrainted to be a value between -1 and +1 to ensure
* that no objective can make a disproportionate contribution
* to the total result.
*
* The more desirable this move appears in terms of this
* objective, the closer to +1 will be the value. A value of 0
* indicates that the move is neutral in terms of the
* objective. A negative value indicates that the move is
* undesirable.
*
* @param conf The configuration which is being examined
* @param move The move under consideration
* @param elem The element to which the objective applies
*
* @throws PoolsException if there is an error manipulating
* the configuration
*/
throws PoolsException;
/**
* Set the objective's expression to the supplied parameter.
*
* @param exp An expression for this objective.
*/
/**
* Get the objective's expression.
*/
public Expression getExpression();
}
/**
* This interface must be implemented by all Objectives which are
* workload dependent. The examine method is used by a Solver to
* determine if the objective is still being satisfied.
*/
interface WorkloadDependentObjective extends Objective
{
/**
* This method returns true if the Objective is no longer
* satisfied. If the objective is still satisfied, then return
* false.
*
* @param conf The configuration to be examined
* @param solver The solving interface used to get utilization
* information
* @param elem The element to which the objective belongs
*
* @throws PoolsException if there is an error examining the
* pool configuration
* @throws StaleMonitorException if there is an error accessing
* the element's ResourceMonitor
*/
}
/**
* This class provides a skeletal implementation of the
* <code>Objective</code> interface to minimize the effort required
* to implement this interface.
*
* To implement an objective, the programmer need only to extend this
* class and add the name of the class into the appropriate element
* objectives property in the <code>poold.properties</code> file.
*/
abstract class AbstractObjective implements Objective
{
/**
* The objectives which are recognized by this class
*/
private static Map objectives;
/**
* The expression associated with this objective
*/
private Expression exp;
/**
* Set the objective's expression to the supplied parameter.
*
* @param exp An expression for this objective.
*/
{
}
/**
* Get the objective's expression.
*/
public Expression getExpression()
{
return (exp);
}
/**
* A factory method which returns a created objective which is
* associated with the supplied expression. The type and the
* expression are used to identify valid types of objectives
* to which this expression may be applied. If an acceptable
* objective cannot be found for the supplied type, then an
* <code>IllegalArgumentException</code> will be thrown.
*
* @param type The element type for which an objective must be
* found
* @param exp The expression which will be associated with the
* objective
*
* @throws IllegalArgumentExcetion if the supplied expression
* cannot be associated with an objective of the supplied type
*/
throws IllegalArgumentException
{
try {
newInstance();
} catch (Exception e) {
true);
}
}
}
throw new IllegalArgumentException(
return (ret);
}
/**
* Return a string representation of this objective.
*/
{
}
/**
* Initialize the implementation map the first time it's
* called.
*/
private static void initMapIfNecessary()
{
/*
* Setup the objectives map for the known classes
*/
if (objectives == null) {
objectives = new HashMap();
try {
new FileInputStream(
} catch (IOException ioe) {
}
}
}
/**
* Add the objectives contained in the supplied properties to
* the set of valid objectives. The objectives are updated
* with objectives of the supplied type contained in the
* properties.
*
* @param props The properties containing the objectives
* @param objectives The objectives to be updated
* @param type The type of objectives to be added
*/
{
try {
} catch (ClassNotFoundException cnfe) {
} catch (NoSuchFieldException nsfe) {
} catch (IllegalAccessException iae) {
}
}
}
/**
* Indicates whether some other Objective is "equal to this
* one.
* @param o the reference object with which to compare.
* @return <code>true</code> if this object is the same as the
* o argument; <code>false</code> otherwise.
* @see #hashCode()
*/
{
if (o == this)
return (true);
if (!(o instanceof Objective))
return (false);
}
/**
* Returns a hash code value for the object. This method is
* supported for the benefit of hashtables such as those provided by
* <code>java.util.Hashtable</code>.
*
* @return a hash code value for this object.
* @see #equals(java.lang.Object)
* @see java.util.Hashtable
*/
public int hashCode()
{
return (getExpression().hashCode());
}
}
/**
* The <code>WeightedLoadObjective</code> class implements a Weighted
* Load Objective for <code>Poold</code>.
*
* The goal is to allocate more resources to those resource partitions
* which are heavily loaded. The weighting is determined from the
* objective importance and the pool.importance.
*/
final class WeightedLoadObjective extends AbstractObjective
implements WorkloadDependentObjective
{
/**
* The name of the class.
*/
/**
* The map of calculations made during examination.
*/
/**
* Determine whether an objective is satisfied. If the
* objective is still satisfied, return false; otherwise
* return true.
*
* This objective examination determines if all resource sets
* are allocated the share of resources that their utilization
* would indicate they should be. This attempts to ensure that
* highly utilized resource sets recieve the greater
* proportion of available resources.
*
* @param conf The configuration to be examined
* @param solver The solving interface used to get utilization
* information
* @param elem The element to which the objective belongs
*
* @throws PoolsException if there is an error examining the
* pool configuration
* @throws StaleMonitorException if there is an error accessing
* the element's ResourceMonitor
*/
{
try {
} catch (StaleMonitorException sme) {
" not participating in " + toString() +
" calculatation as it has no " +
"available statistics.");
}
}
" utilization objective not satisfied " +
toString() + " with desired share " +
return (true);
}
}
return (false);
}
/**
* Holds data about weighted load calculations. This class is
* basically a structure which holds information specific to a
* weighted-load calculation
*/
static class Calculation {
/**
* The resource on which this calculation is based.
*/
/**
* The list of component resources held by this resource.
*/
/**
* The utilization of this resource.
*/
double util;
/**
* The minimum value of this resource's size.
*/
long min;
/**
* The maximum value of this resource's size.
*/
long max;
/**
* The total utilization of all instances of this class.
*/
static double totalUtil;
/**
* The total quantity of resource for all instances of
* this class.
*/
static int resQ;
/**
* Constructor. The class is immutable and holds
* information specific to a set of calculations about
* load.
*
* @param res The resource set
* @param comp The resource components
* @param util The resource utilization
* @param min The minimum qty of resource for this set
* @param max The maximum qty of resource for this set
*/
{
}
/**
* Return the share of the total resource for this
* resource.
*/
long getShare()
{
if (util == 0)
return (0);
}
{
}
}
/**
* Calculates the value of a configuration in terms of this
* objective.
*
* In the examination step, calculations of each resource's
* current and desired share were made. The moves can thus be
* assessed in terms of their impact upon the desired
* share. The current difference from desired is already
* known, so each move will serve to reduce or increase that
* difference. Moves that increase the difference have a
* negative score, those that reduce it have a positive
* score. All scores are normalized to return a value between
* -1 and 1.
*
* @param conf Configuration to be scored.
* @param move Move to be scored.
* @param elem The element to which the objective applies
* @throws PoolsException If an there is an error in execution.
*/
throws PoolsException
{
double ret = 0;
"Calculating objective type: " + name);
/*
* There shouldn't be any empty moves, but if there
* are they are rated at 0.
*/
return (0);
/*
* Find the calculations that represent the source and
* target of the move.
*/
/*
* Use the calculation details to determine the "gap"
* i.e. number of discrete resources (for a processor
* set these are CPUs), between the desired quantity in
* the set which the calculations represent. Do this
* both before and after the proposed move.
*
* The maximum possible improvement is equal to the
* total number of resources for each set participating
* in the calculation. Since there are two sets we
* know the maximum possible improvement is resQ * 2.
*
* Divide the aggregated change in gap across participating
* sets by the maximum possible improvement to obtain
* a value which scores the move and which is normalised
* between -1 <= ret <= 1.
*/
return (ret);
}
}
/**
* A locality based objective which will assess moves in terms of
* their impact on the locality of the sets of resources which are
* impacted.
*
* The objective will assess moves with respect to the type of
* locality specified in the objective:
*
* <ul>
* <li><p>
* tight - resource locality is sought
* <li><p>
* loose - resource locality is avoided
* <li><p>
* none - resource locality has no impact
* </ul>
*/
final class LocalityObjective extends AbstractObjective
{
/**
* The name of the class.
*/
/**
* The locality domain used to describe locality for this
* objective.
*/
private LocalityDomain ldom;
/**
* Prepare the calculation for this objective for the resource
* to which it applies.
*
* @param ldom LocalityDomain containing these resources.
* @param res Resource to which this objective is applied.
*
* @throws PoolsException if accessing the supplied resource
* fails.
*/
throws PoolsException
{
}
/**
* Calculates the value of a configuration in terms of this
* objective.
*
* Firstly check to see if it is possible to short-cut the
* calculation. If not, then start to examine the disposition
* of CPUs and locality groups in relation to the processor
* set being evaluated. The objective scores moves in terms of
* their impact upon the quotient of cpus contained in each
* locality group.
*
* @param conf Configuration to be scored.
* @param move Move to be scored.
* @param elem The element to which the objective applies
* @throws Exception If an there is an error in execution.
*/
throws PoolsException
{
double ret = 0;
double qA = 0;
double qB = 0;
/*
* If we are set to "none" then we don't care which
* configuration so just return 0
*/
return (ret);
/*
* If the maximum latency is 0, we don't care about
* latency
*/
return (ret);
/*
* If this element doesn't participate in the move, we
* should return 0.
*/
return (ret);
/*
* Assess the effect on lgrp quotient for all
* moves. Try to maximise lgrp quotient for "tight"
* objectives and minimize if for "loose" objectives.
*/
/*
* All contained cpus
*/
/*
* All lgrps
*/
else
/*
* Recalculate lgrps to take account of new components
*/
return (ret);
}
/**
* Calculate a quotient using the supplied list of components
* and set of locality groups. The quotient represents the
* average (as in mean) number of CPUs (from the population in
* contains) present in each of the LocalityGroups contained
* in groups.
*
* @param contains The population of Components.
* @param groups The population of LocalityGroups.
*
* @throws PoolsException if there is an error accessing the
* CPUs.
*/
{
double q = 0.0;
int intersection = 0;
double total = 0;
while (containsIt.hasNext()) {
getLongProperty("cpu.sys_id")) {
intersection++;
break;
}
}
}
double factor = 0;
factor += i;
for (int i = 1; i <= intersection; i++)
q += i * factor;
}
return (q);
}
}
/**
* A resource set utilization based objective which will assess moves
* in terms of their (likely) impact on the future performance of a
* resource set with respect to it's specified utilization objective.
*
* The utilization objective must be specified in terms of a
* KVOpExpression, see the class definition for information about the
* form of these expressions. The objective can be examined in terms
* of it's compliance with the aid of a monitoring object. The actual
* assessment of compliance is indicated by the associated monitoring
* object, with this class simply acting as a co-ordinator of the
* relevant information.
*/
final class UtilizationObjective extends AbstractObjective
implements WorkloadDependentObjective
{
/**
* The name of the class.
*/
/**
* Short run detection.
*/
/**
* Format for printing utilization.
*/
/**
* Solver used to calculate delta, i.e. gap, between target and
* actual utilization values.
*/
/**
* Determine whether an objective is satisfied. If the
* objective is still satisfied, return false; otherwise
* return true.
*
* The assessment of control is made by the monitoring class
* using the supplied Expression and resource.
*
* @param conf The configuration to be examined
* @param solver The solving interface used to get utilization
* information
* @param elem The element to which the objective belongs
*
* @throws PoolsException if there is an error examining the
* pool configuration
* @throws StaleMonitorException if there is an error accessing
* the element's ResourceMonitor
*/
{
/*
* If there is no resource monitor, then we cannot
* make an assessment of the objective's achievability.
* Log a message to make clear that this objective is
* not being assessed and then indicate that
* the objective has been achieved.
*/
try {
} catch (StaleMonitorException sme) {
" utilization objective not measured " +
toString() + " as there are no available " +
"statistics.");
return (false);
}
}
/*
* Evaluate whether or not this objective is under
* control.
*/
/*
* If the objective is GT or LT, then don't
* return true as long as the objective is
* satisfied.
*/
return (false);
return (false);
" utilization objective not satisfied " +
" (control zone bounds exceeded)");
return (true);
}
/*
* Check if our statistics need to be recalculated.
*/
return (false);
}
/**
* Calculates the value of a configuration in terms of this
* objective.
*
* Every set must be classified with a control zone when this
* function is called. The move can be assessed in terms of
* the control violation type. zone violations which are minor
* are offered a lower contribution than more significant
* violations.
*
* @param conf Configuration to be scored.
* @param move Move to be scored.
* @param elem The element to which the objective applies
* @throws Exception If an there is an error in execution.
*/
throws PoolsException
{
double ret;
/*
* If the move is from the examined element, then
* check to see if the recipient has any
* objectives. If not, score the move poorly since we
* should never want to transfer resources to a
* recipient with no objectives. If there are
* objectives, then return the delta between target
* performance and actual performance for this
* element.
*
* If the move is to the examined element, then check
* to see if the donor has any objectives. If not,
* score the move highly, since we want to favour
* those resources with objectives. If there are
* objectives, return the delta between actual and
* target performance.
*
* If the element is neither the recipient or the
* donor of this proposed move, then score the move
* neutrally as 0.
*/
try {
null) {
/*
* Moving to a resource with
* no objectives should always
* be viewed unfavourably. The
* degree of favourability is
* thus bound between 0 and
* -1. If the source gap is
* negative, then subtract it
* from -1 to get the
* score. If positive,
* just return -1.
*/
if (gap < 0) {
} else {
ret = -1;
}
} else {
}
null) {
/*
* Moving from a resource with
* no objectives should always
* be viewed favourably. The
* degree of favourability is
* thus bound between 0 and
* 1. If the destination gap
* is negative, then add to 1
* to get the score. If
* positive, just return 1.
*/
if (gap < 0) {
} else {
ret = 1;
}
} else {
}
} else {
ret = 0;
}
} catch (StaleMonitorException sme) {
/*
* We should always find a monitor,
* but if we can't then just assume
* this is a neutral move and return
* 0.
*/
ret = 0;
}
return (ret);
}
/**
* Check whether or not a set's statistics are still useful
* for making decision..
*
* Each set is controlled in terms of the zones of control
* based in terms of standard deviations from a mean. If the
* utilization of the set is not fluctuating normally around a
* mean, these checks will cause the accumulated statistics to
* be discarded and control suspended until a new sufficient
* set of data is accumulated.
*
* @param mon Resource monitor to examine.
* @param elem Element to which the resource monitor belongs.
* @param val Latest monitored value.
*/
{
boolean checkOne = true;
int checkOnePos = 0;
boolean doCheckOne = false;
if (doCheckOne) {
if (checkOne) {
!= checkOnePos) {
checkOne = false;
}
}
} else {
checkOnePos = zone &
doCheckOne = true;
}
}
}
" utilization objective statistics reinitialized " +
" (nine points on same side of mean)");
}
}
}