@ -17,11 +17,44 @@
package cpu
package cpu
import (
import (
"fmt"
"sync"
"sync"
"time"
"time"
)
)
// rollingAvg holds the rolling average of the cpu load on the minio
// server over its lifetime
var rollingAvg * Load
// cpuMeasureInterval is the interval of time between two
// measurements of CPU load
const cpuLoadMeasureInterval = 5 * time . Second
// triggers the average load computation at server spawn
func init ( ) {
rollingAvg = & Load {
Min : float64 ( 0 ) ,
Max : float64 ( 0 ) ,
Avg : float64 ( 0 ) ,
}
var rollingSum float64
var cycles float64
go func ( ) {
for {
time . Sleep ( cpuLoadMeasureInterval )
cycles = cycles + 1
currLoad := GetLoad ( )
if rollingAvg . Max < currLoad . Max || rollingAvg . Max == 0 {
rollingAvg . Max = currLoad . Max
}
if rollingAvg . Min > currLoad . Min || rollingAvg . Min == 0 {
rollingAvg . Min = currLoad . Min
}
rollingSum = rollingSum + currLoad . Avg
rollingAvg . Avg = rollingSum / cycles
}
} ( )
}
const (
const (
// cpuLoadWindow is the interval of time for which the
// cpuLoadWindow is the interval of time for which the
// cpu utilization is measured
// cpu utilization is measured
@ -37,15 +70,34 @@ const (
// Load holds CPU utilization % measured in three intervals of 200ms each
// Load holds CPU utilization % measured in three intervals of 200ms each
type Load struct {
type Load struct {
Avg string ` json:"avg" `
Avg float64 ` json:"avg" `
Max string ` json:"max" `
Max float64 ` json:"max" `
Min string ` json:"min" `
Min float64 ` json:"min" `
Error string ` json:"error,omitempty" `
Error string ` json:"error,omitempty" `
}
}
type counter struct { }
type counter struct { }
// GetLoad returns the CPU utilization % of the current process
// GetHistoricLoad returns the historic CPU utilization of the current process
func GetHistoricLoad ( ) Load {
return * rollingAvg
}
// GetLoad returns the CPU utilization of the current process
// This function works by calcualating the amount of cpu clock
// cycles the current process used in a given time window
//
// This corresponds to the CPU utilization calculation done by
// tools like top. Here, we use the getclocktime with the
// CLOCK_PROCESS_CPUTIME_ID parameter to obtain the total number of
// clock ticks used by the process so far. Then we sleep for
// 200ms and obtain the the total number of clock ticks again. The
// difference between the two counts provides us the number of
// clock ticks used by the process in the 200ms interval.
//
// The ratio of clock ticks used (measured in nanoseconds) to number
// of nanoseconds in 200 milliseconds provides us the CPU usage
// for the process currently
func GetLoad ( ) Load {
func GetLoad ( ) Load {
vals := make ( chan time . Duration , 3 )
vals := make ( chan time . Duration , 3 )
wg := sync . WaitGroup { }
wg := sync . WaitGroup { }
@ -83,9 +135,9 @@ func GetLoad() Load {
close ( vals )
close ( vals )
avg := sum / 3
avg := sum / 3
return Load {
return Load {
Avg : fmt . Sprintf ( "%.2f%%" , toFixed4 ( float64 ( avg ) / float64 ( 200 * time . Millisecond ) ) * 100 ) ,
Avg : toFixed4 ( float64 ( avg ) / float64 ( 200 * time . Millisecond ) ) * 100 ,
Max : fmt . Sprintf ( "%.2f%%" , toFixed4 ( float64 ( max ) / float64 ( 200 * time . Millisecond ) ) * 100 ) ,
Max : toFixed4 ( float64 ( max ) / float64 ( 200 * time . Millisecond ) ) * 100 ,
Min : fmt . Sprintf ( "%.2f%%" , toFixed4 ( float64 ( min ) / float64 ( 200 * time . Millisecond ) ) * 100 ) ,
Min : toFixed4 ( float64 ( min ) / float64 ( 200 * time . Millisecond ) ) * 100 ,
Error : "" ,
Error : "" ,
}
}
}
}