Chromagies/src/profiler/profiler.go
2025-04-28 22:37:17 +02:00

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())
}