github.com/minio/madmin-go/v2@v2.2.1/timings.go (about) 1 // 2 // Copyright (c) 2015-2022 MinIO, Inc. 3 // 4 // This file is part of MinIO Object Storage stack 5 // 6 // This program is free software: you can redistribute it and/or modify 7 // it under the terms of the GNU Affero General Public License as 8 // published by the Free Software Foundation, either version 3 of the 9 // License, or (at your option) any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU Affero General Public License for more details. 15 // 16 // You should have received a copy of the GNU Affero General Public License 17 // along with this program. If not, see <http://www.gnu.org/licenses/>. 18 // 19 20 package madmin 21 22 import ( 23 "math" 24 "sort" 25 "time" 26 ) 27 28 // Timings captures all latency metrics 29 type Timings struct { 30 Avg time.Duration `json:"avg"` // Average duration per sample 31 P50 time.Duration `json:"p50"` // 50th %ile of all the sample durations 32 P75 time.Duration `json:"p75"` // 75th %ile of all the sample durations 33 P95 time.Duration `json:"p95"` // 95th %ile of all the sample durations 34 P99 time.Duration `json:"p99"` // 99th %ile of all the sample durations 35 P999 time.Duration `json:"p999"` // 99.9th %ile of all the sample durations 36 Long5p time.Duration `json:"l5p"` // Average duration of the longest 5% 37 Short5p time.Duration `json:"s5p"` // Average duration of the shortest 5% 38 Max time.Duration `json:"max"` // Max duration 39 Min time.Duration `json:"min"` // Min duration 40 StdDev time.Duration `json:"sdev"` // Standard deviation among all the sample durations 41 Range time.Duration `json:"range"` // Delta between Max and Min 42 } 43 44 // Measure - calculate all the latency measurements 45 func (ts TimeDurations) Measure() Timings { 46 if len(ts) == 0 { 47 return Timings{ 48 Avg: 0, 49 P50: 0, 50 P75: 0, 51 P95: 0, 52 P99: 0, 53 P999: 0, 54 Long5p: 0, 55 Short5p: 0, 56 Min: 0, 57 Max: 0, 58 Range: 0, 59 StdDev: 0, 60 } 61 } 62 sort.Slice(ts, func(i, j int) bool { 63 return int64(ts[i]) < int64(ts[j]) 64 }) 65 return Timings{ 66 Avg: ts.avg(), 67 P50: ts[ts.Len()/2], 68 P75: ts.p(0.75), 69 P95: ts.p(0.95), 70 P99: ts.p(0.99), 71 P999: ts.p(0.999), 72 Long5p: ts.long5p(), 73 Short5p: ts.short5p(), 74 Min: ts.min(), 75 Max: ts.max(), 76 Range: ts.srange(), 77 StdDev: ts.stdDev(), 78 } 79 } 80 81 // TimeDurations is time.Duration segments. 82 type TimeDurations []time.Duration 83 84 func (ts TimeDurations) Len() int { return len(ts) } 85 86 func (ts TimeDurations) avg() time.Duration { 87 var total time.Duration 88 for _, t := range ts { 89 total += t 90 } 91 return time.Duration(int(total) / ts.Len()) 92 } 93 94 func (ts TimeDurations) p(p float64) time.Duration { 95 return ts[int(float64(ts.Len())*p+0.5)-1] 96 } 97 98 func (ts TimeDurations) stdDev() time.Duration { 99 m := ts.avg() 100 s := 0.00 101 102 for _, t := range ts { 103 s += math.Pow(float64(m-t), 2) 104 } 105 106 msq := s / float64(ts.Len()) 107 108 return time.Duration(math.Sqrt(msq)) 109 } 110 111 func (ts TimeDurations) long5p() time.Duration { 112 set := ts[int(float64(ts.Len())*0.95+0.5):] 113 114 if len(set) <= 1 { 115 return ts[ts.Len()-1] 116 } 117 118 var t time.Duration 119 var i int 120 for _, n := range set { 121 t += n 122 i++ 123 } 124 125 return time.Duration(int(t) / i) 126 } 127 128 func (ts TimeDurations) short5p() time.Duration { 129 set := ts[:int(float64(ts.Len())*0.05+0.5)] 130 131 if len(set) <= 1 { 132 return ts[0] 133 } 134 135 var t time.Duration 136 var i int 137 for _, n := range set { 138 t += n 139 i++ 140 } 141 142 return time.Duration(int(t) / i) 143 } 144 145 func (ts TimeDurations) min() time.Duration { 146 return ts[0] 147 } 148 149 func (ts TimeDurations) max() time.Duration { 150 return ts[ts.Len()-1] 151 } 152 153 func (ts TimeDurations) srange() time.Duration { 154 return ts.max() - ts.min() 155 }