1// Copyright (c) 2015-2021 MinIO, Inc.
2//
3// This file is part of MinIO Object Storage stack
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Affero General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13// GNU Affero General Public License for more details.
14//
15// You should have received a copy of the GNU Affero General Public License
16// along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18package net
19
20import (
21	"github.com/minio/madmin-go"
22	"github.com/montanaflynn/stats"
23)
24
25// ComputePerfStats takes arrays of Latency & Throughput to compute Statistics
26func ComputePerfStats(latencies, throughputs []float64) (madmin.NetLatency, madmin.NetThroughput, error) {
27	var avgLatency float64
28	var percentile50Latency float64
29	var percentile90Latency float64
30	var percentile99Latency float64
31	var minLatency float64
32	var maxLatency float64
33
34	var avgThroughput float64
35	var percentile50Throughput float64
36	var percentile90Throughput float64
37	var percentile99Throughput float64
38	var minThroughput float64
39	var maxThroughput float64
40	var err error
41
42	if avgLatency, err = stats.Mean(latencies); err != nil {
43		return madmin.NetLatency{}, madmin.NetThroughput{}, err
44	}
45	if percentile50Latency, err = stats.Percentile(latencies, 50); err != nil {
46		return madmin.NetLatency{}, madmin.NetThroughput{}, err
47	}
48	if percentile90Latency, err = stats.Percentile(latencies, 90); err != nil {
49		return madmin.NetLatency{}, madmin.NetThroughput{}, err
50	}
51	if percentile99Latency, err = stats.Percentile(latencies, 99); err != nil {
52		return madmin.NetLatency{}, madmin.NetThroughput{}, err
53	}
54	if maxLatency, err = stats.Max(latencies); err != nil {
55		return madmin.NetLatency{}, madmin.NetThroughput{}, err
56	}
57	if minLatency, err = stats.Min(latencies); err != nil {
58		return madmin.NetLatency{}, madmin.NetThroughput{}, err
59	}
60	l := madmin.NetLatency{
61		Avg:          avgLatency,
62		Percentile50: percentile50Latency,
63		Percentile90: percentile90Latency,
64		Percentile99: percentile99Latency,
65		Min:          minLatency,
66		Max:          maxLatency,
67	}
68
69	if avgThroughput, err = stats.Mean(throughputs); err != nil {
70		return madmin.NetLatency{}, madmin.NetThroughput{}, err
71	}
72	if percentile50Throughput, err = stats.Percentile(throughputs, 50); err != nil {
73		return madmin.NetLatency{}, madmin.NetThroughput{}, err
74	}
75	if percentile90Throughput, err = stats.Percentile(throughputs, 90); err != nil {
76		return madmin.NetLatency{}, madmin.NetThroughput{}, err
77	}
78	if percentile99Throughput, err = stats.Percentile(throughputs, 99); err != nil {
79		return madmin.NetLatency{}, madmin.NetThroughput{}, err
80	}
81	if maxThroughput, err = stats.Max(throughputs); err != nil {
82		return madmin.NetLatency{}, madmin.NetThroughput{}, err
83	}
84	if minThroughput, err = stats.Min(throughputs); err != nil {
85		return madmin.NetLatency{}, madmin.NetThroughput{}, err
86	}
87	t := madmin.NetThroughput{
88		Avg:          avgThroughput,
89		Percentile50: percentile50Throughput,
90		Percentile90: percentile90Throughput,
91		Percentile99: percentile99Throughput,
92		Min:          minThroughput,
93		Max:          maxThroughput,
94	}
95
96	return l, t, nil
97}
98