/* * * Copyright 2017 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ /* To format the benchmark result: go run benchmark/benchresult/main.go resultfile To see the performance change based on a old result: go run benchmark/benchresult/main.go resultfile_old resultfile It will print the comparison result of intersection benchmarks between two files. */ package main import ( "encoding/gob" "fmt" "log" "os" "strings" "time" "google.golang.org/grpc/benchmark/stats" ) func createMap(fileName string) map[string]stats.BenchResults { f, err := os.Open(fileName) if err != nil { log.Fatalf("Read file %s error: %s\n", fileName, err) } defer f.Close() var data []stats.BenchResults decoder := gob.NewDecoder(f) if err = decoder.Decode(&data); err != nil { log.Fatalf("Decode file %s error: %s\n", fileName, err) } m := make(map[string]stats.BenchResults) for _, d := range data { m[d.RunMode+"-"+d.Features.String()] = d } return m } func intChange(title string, val1, val2 uint64) string { return fmt.Sprintf("%20s %12d %12d %8.2f%%\n", title, val1, val2, float64(int64(val2)-int64(val1))*100/float64(val1)) } func floatChange(title string, val1, val2 float64) string { return fmt.Sprintf("%20s %12.2f %12.2f %8.2f%%\n", title, val1, val2, float64(int64(val2)-int64(val1))*100/float64(val1)) } func timeChange(title string, val1, val2 time.Duration) string { return fmt.Sprintf("%20s %12s %12s %8.2f%%\n", title, val1.String(), val2.String(), float64(val2-val1)*100/float64(val1)) } func strDiff(title, val1, val2 string) string { return fmt.Sprintf("%20s %12s %12s\n", title, val1, val2) } func compareTwoMap(m1, m2 map[string]stats.BenchResults) { for k2, v2 := range m2 { if v1, ok := m1[k2]; ok { changes := k2 + "\n" changes += fmt.Sprintf("%20s %12s %12s %8s\n", "Title", "Before", "After", "Percentage") changes += intChange("TotalOps", v1.Data.TotalOps, v2.Data.TotalOps) changes += intChange("SendOps", v1.Data.SendOps, v2.Data.SendOps) changes += intChange("RecvOps", v1.Data.RecvOps, v2.Data.RecvOps) changes += floatChange("Bytes/op", v1.Data.AllocedBytes, v2.Data.AllocedBytes) changes += floatChange("Allocs/op", v1.Data.Allocs, v2.Data.Allocs) changes += floatChange("ReqT/op", v1.Data.ReqT, v2.Data.ReqT) changes += floatChange("RespT/op", v1.Data.RespT, v2.Data.RespT) changes += timeChange("50th-Lat", v1.Data.Fiftieth, v2.Data.Fiftieth) changes += timeChange("90th-Lat", v1.Data.Ninetieth, v2.Data.Ninetieth) changes += timeChange("99th-Lat", v1.Data.NinetyNinth, v2.Data.NinetyNinth) changes += timeChange("Avg-Lat", v1.Data.Average, v2.Data.Average) changes += strDiff("GoVersion", v1.GoVersion, v2.GoVersion) changes += strDiff("GrpcVersion", v1.GrpcVersion, v2.GrpcVersion) fmt.Printf("%s\n", changes) } } } func compareBenchmark(file1, file2 string) { compareTwoMap(createMap(file1), createMap(file2)) } func printHeader() { fmt.Printf("%-80s%12s%12s%12s%18s%18s%18s%18s%12s%12s%12s%12s\n", "Name", "TotalOps", "SendOps", "RecvOps", "Bytes/op (B)", "Allocs/op (#)", "RequestT", "ResponseT", "L-50", "L-90", "L-99", "L-Avg") } func printline(benchName string, d stats.RunData) { fmt.Printf("%-80s%12d%12d%12d%18.2f%18.2f%18.2f%18.2f%12v%12v%12v%12v\n", benchName, d.TotalOps, d.SendOps, d.RecvOps, d.AllocedBytes, d.Allocs, d.ReqT, d.RespT, d.Fiftieth, d.Ninetieth, d.NinetyNinth, d.Average) } func formatBenchmark(fileName string) { f, err := os.Open(fileName) if err != nil { log.Fatalf("Read file %s error: %s\n", fileName, err) } defer f.Close() var results []stats.BenchResults decoder := gob.NewDecoder(f) if err = decoder.Decode(&results); err != nil { log.Fatalf("Decode file %s error: %s\n", fileName, err) } if len(results) == 0 { log.Fatalf("No benchmark results in file %s\n", fileName) } fmt.Println("\nShared features:\n" + strings.Repeat("-", 20)) fmt.Print(results[0].Features.SharedFeatures(results[0].SharedFeatures)) fmt.Println(strings.Repeat("-", 35)) wantFeatures := results[0].SharedFeatures for i := 0; i < len(results[0].SharedFeatures); i++ { wantFeatures[i] = !wantFeatures[i] } printHeader() for _, r := range results { printline(r.RunMode+r.Features.PrintableName(wantFeatures), r.Data) } } func main() { if len(os.Args) == 2 { formatBenchmark(os.Args[1]) } else { compareBenchmark(os.Args[1], os.Args[2]) } }