Made sure that the victim that is capped the most is the one picked to be uncapped. This is to reduce the chances of benchmark starvation. Refined comments and logging.

This commit is contained in:
Pradyumna Kaushik 2017-02-22 20:09:04 -05:00
parent 64de61ac4e
commit 2939943afd

View file

@ -14,6 +14,7 @@ import (
"strings" "strings"
"syscall" "syscall"
"time" "time"
"bitbucket.org/sunybingcloud/electron/utilities"
) )
func round(num float64) int { func round(num float64) int {
@ -84,11 +85,13 @@ func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, pref
// Throw away first set of results // Throw away first set of results
scanner.Scan() scanner.Scan()
// cappedHosts := make(map[string]bool) // To keep track of the capped states of the capped victims
// Keep track of the capped victims and the corresponding cap value.
cappedVictims := make(map[string]float64) cappedVictims := make(map[string]float64)
// TODO: Come with a better name for this.
orderCapped := make([]string, 0, 8) orderCapped := make([]string, 0, 8)
orderCappedVictims := make(map[string]float64) // Parallel data structure to orderCapped to make it possible to search victims, that are to be uncapped, faster. // TODO: Change this to a priority queue ordered by the cap value. This will get rid of the sorting performed in the code.
// Parallel data structure to orderCapped to keep track of the uncapped states of the uncapped victims
orderCappedVictims := make(map[string]float64)
clusterPowerHist := ring.New(5) clusterPowerHist := ring.New(5)
seconds := 0 seconds := 0
@ -122,8 +125,8 @@ func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, pref
if clusterMean >= hiThreshold { if clusterMean >= hiThreshold {
log.Println("Need to cap a node") log.Println("Need to cap a node")
log.Println(cappedVictims) log.Printf("Cap values of capped victims: %v", cappedVictims)
log.Println(orderCappedVictims) log.Printf("Cap values of victims to uncap: %v", orderCappedVictims)
// Create statics for all victims and choose one to cap // Create statics for all victims and choose one to cap
victims := make([]Victim, 0, 8) victims := make([]Victim, 0, 8)
@ -140,88 +143,98 @@ func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, pref
// Finding the best victim to cap in a round robin manner // Finding the best victim to cap in a round robin manner
newVictimFound := false newVictimFound := false
alreadyCappedHosts := []string{} // Hosts of already capped hosts in decreasing order of recent power consumption alreadyCappedHosts := []string{} // Host-names of victims that are already capped
for i := 0; i < len(victims); i++ { for i := 0; i < len(victims); i++ {
// Try to pick a victim that hasn't been capped yet. // Try to pick a victim that hasn't been capped yet
if _, ok := cappedVictims[victims[i].Host]; !ok { if _, ok := cappedVictims[victims[i].Host]; !ok {
// If this victim can't be capped further, then we move on to find another victim that we can cap. // If this victim can't be capped further, then we move on to find another victim
if _, ok := orderCappedVictims[victims[i].Host]; ok { if _, ok := orderCappedVictims[victims[i].Host]; ok {
continue continue
} }
// Need to cap this victim and add it to the cappedVictims // Need to cap this victim
if err := rapl.Cap(victims[i].Host, "rapl", 50.0); err != nil { if err := rapl.Cap(victims[i].Host, "rapl", 50.0); err != nil {
log.Printf("Error capping host %s", victims[i].Host) log.Printf("Error capping host %s", victims[i].Host)
} else { } else {
log.Printf("Capped host[%s] at %f", victims[i].Host, 50.0) log.Printf("Capped host[%s] at %f", victims[i].Host, 50.0)
// Keeping track of this victim and it's cap value
cappedVictims[victims[i].Host] = 50.0 cappedVictims[victims[i].Host] = 50.0
newVictimFound = true newVictimFound = true
// This node can be uncapped and hence adding to orderCapped // This node can be uncapped and hence adding to orderCapped
orderCapped = append(orderCapped, victims[i].Host) orderCapped = append(orderCapped, victims[i].Host)
orderCappedVictims[victims[i].Host] = 50.0 orderCappedVictims[victims[i].Host] = 50.0
break // breaking only on successful cap break // Breaking only on successful cap
} }
} else { } else {
alreadyCappedHosts = append(alreadyCappedHosts, victims[i].Host) alreadyCappedHosts = append(alreadyCappedHosts, victims[i].Host)
} }
} }
// If no new victim found, then we need to cap the best victim among the already capped victims // If no new victim found, then we need to cap the best victim among the ones that are already capped
if !newVictimFound { if !newVictimFound {
for i := 0; i < len(alreadyCappedHosts); i++ { for i := 0; i < len(alreadyCappedHosts); i++ {
// If already capped then the host must be present in orderCappedVictims // If already capped then the host must be present in orderCappedVictims
capValue := orderCappedVictims[alreadyCappedHosts[i]] capValue := orderCappedVictims[alreadyCappedHosts[i]]
// if capValue is greater than the threshold then cap, else continue // If capValue is greater than the threshold then cap, else continue
if capValue > constants.CapThreshold { if capValue > constants.CapThreshold {
newCapValue := getNextCapValue(capValue, 2) newCapValue := getNextCapValue(capValue, 2)
log.Printf("CurrentCapValue for host[%s] is %f", alreadyCappedHosts[i], capValue)
log.Printf("NewCapValue for host[%s] is %f", alreadyCappedHosts[i], newCapValue)
if err := rapl.Cap(alreadyCappedHosts[i], "rapl", newCapValue); err != nil { if err := rapl.Cap(alreadyCappedHosts[i], "rapl", newCapValue); err != nil {
log.Printf("Error capping host %s", alreadyCappedHosts[i]) log.Printf("Error capping host[%s]", alreadyCappedHosts[i])
} else { } else {
// successful cap // Successful cap
log.Printf("Capped host[%s] at %f", alreadyCappedHosts[i], newCapValue) log.Printf("Capped host[%s] at %f", alreadyCappedHosts[i], newCapValue)
// Checking whether this victim can be capped further // Checking whether this victim can be capped further
if newCapValue <= constants.CapThreshold { if newCapValue <= constants.CapThreshold {
// deleting victim from cappedVictims // Deleting victim from cappedVictims
delete(cappedVictims, alreadyCappedHosts[i]) delete(cappedVictims, alreadyCappedHosts[i])
// updating the cap value in orderCappedVictims // Updating the cap value in orderCappedVictims
orderCappedVictims[alreadyCappedHosts[i]] = newCapValue orderCappedVictims[alreadyCappedHosts[i]] = newCapValue
} else { } else {
// updating the cap value // Updating the cap value
cappedVictims[alreadyCappedHosts[i]] = newCapValue cappedVictims[alreadyCappedHosts[i]] = newCapValue
orderCappedVictims[alreadyCappedHosts[i]] = newCapValue orderCappedVictims[alreadyCappedHosts[i]] = newCapValue
} }
break // exiting only on a successful cap. break // Breaking only on successful cap.
} }
} else { } else {
// Do nothing // Do nothing
// Continue to find another victim to cap. // Continue to find another victim to cap.
// If cannot find any victim, then all nodes have been capped to the maximum and we stop capping at that point. // If cannot find any victim, then all nodes have been capped to the maximum and we stop capping at this point.
} }
} }
} }
} else if clusterMean < loThreshold { } else if clusterMean < loThreshold {
log.Println("Need to uncap a node") log.Println("Need to uncap a node")
log.Println(cappedVictims) log.Printf("Cap values of capped victims: %v", cappedVictims)
log.Println(orderCappedVictims) log.Printf("Cap values of victims to uncap: %v", orderCappedVictims)
if len(orderCapped) > 0 { if len(orderCapped) > 0 {
host := orderCapped[len(orderCapped)-1] // We pick the host that is capped the most to uncap
// Uncapping the host and removing it from orderCapped if we cannot uncap it further orderCappedToSort := utilities.GetPairList(orderCappedVictims)
newUncapValue := orderCappedVictims[host] * 2.0 sort.Sort(orderCappedToSort) // Sorted hosts in non-decreasing order of capped states
if err := rapl.Cap(host, "rapl", newUncapValue); err != nil { hostToUncap := orderCappedToSort[0].Key
log.Printf("Error uncapping host %s", host) // Uncapping the host
newUncapValue := orderCappedVictims[hostToUncap] * 2.0
if err := rapl.Cap(hostToUncap, "rapl", newUncapValue); err != nil {
log.Printf("Error uncapping host[%s]", hostToUncap)
} else { } else {
// Successful uncap // Successful uncap
log.Printf("Uncapped host[%s] to %f", host, newUncapValue) log.Printf("Uncapped host[%s] to %f", hostToUncap, newUncapValue)
// Can we uncap this host further. If not, then we remove its entry from orderCapped
if newUncapValue >= 100.0 { // can compare using == if newUncapValue >= 100.0 { // can compare using ==
orderCapped = orderCapped[:len(orderCapped)-1] // Deleting entry from orderCapped
delete(orderCappedVictims, host) for i, victimHost := range orderCapped {
// removing entry from cappedVictims as this host is no longer capped if victimHost == hostToUncap {
delete(cappedVictims, host) orderCapped = append(orderCapped[:i], orderCapped[i+1:]...)
break // We are done removing host from orderCapped
}
}
// Removing entry for host from the parallel data structure
delete(orderCappedVictims, hostToUncap)
// Removing entry from cappedVictims as this host is no longer capped
delete(cappedVictims, hostToUncap)
} else if newUncapValue > constants.CapThreshold { // this check is unnecessary and can be converted to 'else' } else if newUncapValue > constants.CapThreshold { // this check is unnecessary and can be converted to 'else'
// Updating the cap value in orderCappedVictims and cappedVictims // Updating the cap value
orderCappedVictims[host] = newUncapValue orderCappedVictims[hostToUncap] = newUncapValue
cappedVictims[host] = newUncapValue cappedVictims[hostToUncap] = newUncapValue
} }
} }
} else { } else {