144 lines
2.8 KiB
Go
144 lines
2.8 KiB
Go
package profiler
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"maps"
|
|
"math"
|
|
"slices"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
const PROFILER_DEFAULT_MAX_COUNT uint32 = 1000
|
|
const PROFILER_DEFAULT_UNIT string = ""
|
|
|
|
type Data struct {
|
|
count uint32
|
|
mean float64
|
|
min time.Duration
|
|
max time.Duration
|
|
lastValue time.Duration
|
|
unit string
|
|
}
|
|
|
|
type Profile struct {
|
|
sync.RWMutex
|
|
unit string
|
|
count uint32
|
|
maxCount uint32
|
|
index uint32
|
|
sum time.Duration
|
|
mean float64
|
|
values []time.Duration
|
|
lastValue time.Duration
|
|
}
|
|
|
|
var profiles map[string]*Profile = make(map[string]*Profile)
|
|
|
|
func Register(entry string, maxValues uint32, unit string) {
|
|
var profile *Profile
|
|
var exist bool
|
|
profile, exist = profiles[entry]
|
|
|
|
if exist && (profile != nil) {
|
|
return
|
|
}
|
|
|
|
profile = new(Profile)
|
|
profile.maxCount = maxValues
|
|
profile.values = make([]time.Duration, profile.maxCount)
|
|
profile.unit = unit
|
|
profiles[entry] = profile
|
|
}
|
|
|
|
func Add(entry string, duration time.Duration) {
|
|
var profile *Profile
|
|
var exist bool
|
|
profile, exist = profiles[entry]
|
|
|
|
if !exist || (profile == nil) {
|
|
profile = new(Profile)
|
|
profile.maxCount = PROFILER_DEFAULT_MAX_COUNT
|
|
profile.values = make([]time.Duration, profile.maxCount)
|
|
profile.unit = PROFILER_DEFAULT_UNIT
|
|
profiles[entry] = profile
|
|
}
|
|
|
|
profile.Lock()
|
|
|
|
var lastValue time.Duration = profile.values[profile.index]
|
|
profile.values[profile.index] = duration
|
|
profile.index++
|
|
if profile.index >= profile.maxCount {
|
|
profile.index = 0
|
|
}
|
|
|
|
if profile.count < profile.maxCount {
|
|
profile.count++
|
|
}
|
|
|
|
profile.sum += duration - lastValue
|
|
profile.mean = (((float64)(profile.sum)) / (float64)(time.Duration(profile.count)))
|
|
profile.lastValue = duration
|
|
|
|
profile.Unlock()
|
|
}
|
|
|
|
func GetAll(entries *[]string) {
|
|
*entries = slices.Collect(maps.Keys(profiles))
|
|
}
|
|
|
|
func Get(entry string) Data {
|
|
var profile *Profile
|
|
var exist bool
|
|
profile, exist = profiles[entry]
|
|
|
|
if !exist || (profile == nil) {
|
|
profile = new(Profile)
|
|
profiles[entry] = profile
|
|
}
|
|
|
|
var data Data
|
|
|
|
profile.RLock()
|
|
|
|
data.mean = profile.mean
|
|
data.min = math.MaxInt64
|
|
data.max = 0
|
|
data.count = profile.count
|
|
data.unit = profile.unit
|
|
data.lastValue = profile.lastValue
|
|
for i := range profile.count {
|
|
value := profile.values[i]
|
|
if value < data.min {
|
|
data.min = value
|
|
}
|
|
if value > data.max {
|
|
data.max = value
|
|
}
|
|
}
|
|
|
|
profile.RUnlock()
|
|
|
|
if data.count == 0 {
|
|
data.min = 0
|
|
}
|
|
|
|
return data
|
|
}
|
|
|
|
func (data Data) ToString() string {
|
|
return fmt.Sprintf(`
|
|
- Last value : %d %s
|
|
- Mean : %f %s
|
|
- Min : %d %s
|
|
- Max : %d %s
|
|
- Number of values : %d
|
|
`, data.lastValue, data.unit, data.mean, data.unit, data.min, data.unit, data.max, data.unit, data.count)
|
|
}
|
|
|
|
func Log(entry string) {
|
|
log.Println(Get(entry).ToString())
|
|
}
|