// Copyright (c) 2015-2021 MinIO, Inc. // // This file is part of MinIO Object Storage stack // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . package cmd import ( "context" "math" "os" "sync" "github.com/minio/madmin-go" "github.com/minio/minio/internal/disk" ) // round returns value rounding to specified decimal places. func round(f float64, n int) float64 { if n <= 0 { return math.Round(f) } p := math.Pow10(n) return math.Round(f*p) / p } func getDrivePerfInfo(ctx context.Context, parallel bool) []madmin.DrivePerfInfo { pools := globalEndpoints info := []madmin.DrivePerfInfo{} var wg sync.WaitGroup for _, pool := range pools { for _, endpoint := range pool.Endpoints { if !endpoint.IsLocal { continue } if _, err := os.Stat(endpoint.Path); err != nil { info = append(info, madmin.DrivePerfInfo{ Path: endpoint.Path, Error: err.Error(), }) continue } getHealthInfo := func(path string) { defer wg.Done() latency, throughput, err := disk.GetHealthInfo( ctx, path, pathJoin(path, minioMetaTmpBucket, mustGetUUID()), ) if err != nil { info = append(info, madmin.DrivePerfInfo{ Path: path, Error: err.Error(), }) } else { info = append(info, madmin.DrivePerfInfo{ Path: path, Latency: madmin.Latency{ Avg: round(latency.Avg, 3), Max: round(latency.Max, 3), Min: round(latency.Min, 3), Percentile50: round(latency.Percentile50, 3), Percentile90: round(latency.Percentile90, 3), Percentile99: round(latency.Percentile99, 3), }, Throughput: madmin.Throughput{ Avg: uint64(round(throughput.Avg, 0)), Max: uint64(round(throughput.Max, 0)), Min: uint64(round(throughput.Min, 0)), Percentile50: uint64(round(throughput.Percentile50, 0)), Percentile90: uint64(round(throughput.Percentile90, 0)), Percentile99: uint64(round(throughput.Percentile99, 0)), }, }) } } wg.Add(1) if parallel { go getHealthInfo(endpoint.Path) } else { getHealthInfo(endpoint.Path) } } } wg.Wait() return info } func getDrivePerfInfos(ctx context.Context, addr string) madmin.DrivePerfInfos { serialPerf := getDrivePerfInfo(ctx, false) parallelPerf := getDrivePerfInfo(ctx, true) return madmin.DrivePerfInfos{ Addr: addr, SerialPerf: serialPerf, ParallelPerf: parallelPerf, } }