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