github.com/minio/madmin-go@v1.7.5/timings.go (about)

     1  //
     2  // MinIO Object Storage (c) 2022 MinIO, Inc.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //      http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package madmin
    18  
    19  import (
    20  	"math"
    21  	"sort"
    22  	"time"
    23  )
    24  
    25  // Timings captures all latency metrics
    26  type Timings struct {
    27  	Avg     time.Duration `json:"avg"`   // Average duration per sample
    28  	P50     time.Duration `json:"p50"`   // 50th %ile of all the sample durations
    29  	P75     time.Duration `json:"p75"`   // 75th %ile of all the sample durations
    30  	P95     time.Duration `json:"p95"`   // 95th %ile of all the sample durations
    31  	P99     time.Duration `json:"p99"`   // 99th %ile of all the sample durations
    32  	P999    time.Duration `json:"p999"`  // 99.9th %ile of all the sample durations
    33  	Long5p  time.Duration `json:"l5p"`   // Average duration of the longest 5%
    34  	Short5p time.Duration `json:"s5p"`   // Average duration of the shortest 5%
    35  	Max     time.Duration `json:"max"`   // Max duration
    36  	Min     time.Duration `json:"min"`   // Min duration
    37  	StdDev  time.Duration `json:"sdev"`  // Standard deviation among all the sample durations
    38  	Range   time.Duration `json:"range"` // Delta between Max and Min
    39  }
    40  
    41  // Measure - calculate all the latency measurements
    42  func (ts TimeDurations) Measure() Timings {
    43  	if len(ts) == 0 {
    44  		return Timings{
    45  			Avg:     0,
    46  			P50:     0,
    47  			P75:     0,
    48  			P95:     0,
    49  			P99:     0,
    50  			P999:    0,
    51  			Long5p:  0,
    52  			Short5p: 0,
    53  			Min:     0,
    54  			Max:     0,
    55  			Range:   0,
    56  			StdDev:  0,
    57  		}
    58  	}
    59  	sort.Slice(ts, func(i, j int) bool {
    60  		return int64(ts[i]) < int64(ts[j])
    61  	})
    62  	return Timings{
    63  		Avg:     ts.avg(),
    64  		P50:     ts[ts.Len()/2],
    65  		P75:     ts.p(0.75),
    66  		P95:     ts.p(0.95),
    67  		P99:     ts.p(0.99),
    68  		P999:    ts.p(0.999),
    69  		Long5p:  ts.long5p(),
    70  		Short5p: ts.short5p(),
    71  		Min:     ts.min(),
    72  		Max:     ts.max(),
    73  		Range:   ts.srange(),
    74  		StdDev:  ts.stdDev(),
    75  	}
    76  }
    77  
    78  // TimeDurations is time.Duration segments.
    79  type TimeDurations []time.Duration
    80  
    81  func (ts TimeDurations) Len() int { return len(ts) }
    82  
    83  func (ts TimeDurations) avg() time.Duration {
    84  	var total time.Duration
    85  	for _, t := range ts {
    86  		total += t
    87  	}
    88  	return time.Duration(int(total) / ts.Len())
    89  }
    90  
    91  func (ts TimeDurations) p(p float64) time.Duration {
    92  	return ts[int(float64(ts.Len())*p+0.5)-1]
    93  }
    94  
    95  func (ts TimeDurations) stdDev() time.Duration {
    96  	m := ts.avg()
    97  	s := 0.00
    98  
    99  	for _, t := range ts {
   100  		s += math.Pow(float64(m-t), 2)
   101  	}
   102  
   103  	msq := s / float64(ts.Len())
   104  
   105  	return time.Duration(math.Sqrt(msq))
   106  }
   107  
   108  func (ts TimeDurations) long5p() time.Duration {
   109  	set := ts[int(float64(ts.Len())*0.95+0.5):]
   110  
   111  	if len(set) <= 1 {
   112  		return ts[ts.Len()-1]
   113  	}
   114  
   115  	var t time.Duration
   116  	var i int
   117  	for _, n := range set {
   118  		t += n
   119  		i++
   120  	}
   121  
   122  	return time.Duration(int(t) / i)
   123  }
   124  
   125  func (ts TimeDurations) short5p() time.Duration {
   126  	set := ts[:int(float64(ts.Len())*0.05+0.5)]
   127  
   128  	if len(set) <= 1 {
   129  		return ts[0]
   130  	}
   131  
   132  	var t time.Duration
   133  	var i int
   134  	for _, n := range set {
   135  		t += n
   136  		i++
   137  	}
   138  
   139  	return time.Duration(int(t) / i)
   140  }
   141  
   142  func (ts TimeDurations) min() time.Duration {
   143  	return ts[0]
   144  }
   145  
   146  func (ts TimeDurations) max() time.Duration {
   147  	return ts[ts.Len()-1]
   148  }
   149  
   150  func (ts TimeDurations) srange() time.Duration {
   151  	return ts.max() - ts.min()
   152  }