google.golang.org/grpc@v1.62.1/benchmark/benchresult/main.go (about) 1 /* 2 * 3 * Copyright 2017 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 /* 20 To format the benchmark result: 21 22 go run benchmark/benchresult/main.go resultfile 23 24 To see the performance change based on a old result: 25 26 go run benchmark/benchresult/main.go resultfile_old resultfile 27 28 It will print the comparison result of intersection benchmarks between two files. 29 */ 30 package main 31 32 import ( 33 "encoding/gob" 34 "fmt" 35 "log" 36 "os" 37 "strings" 38 "time" 39 40 "google.golang.org/grpc/benchmark/stats" 41 ) 42 43 func createMap(fileName string) map[string]stats.BenchResults { 44 f, err := os.Open(fileName) 45 if err != nil { 46 log.Fatalf("Read file %s error: %s\n", fileName, err) 47 } 48 defer f.Close() 49 var data []stats.BenchResults 50 decoder := gob.NewDecoder(f) 51 if err = decoder.Decode(&data); err != nil { 52 log.Fatalf("Decode file %s error: %s\n", fileName, err) 53 } 54 m := make(map[string]stats.BenchResults) 55 for _, d := range data { 56 m[d.RunMode+"-"+d.Features.String()] = d 57 } 58 return m 59 } 60 61 func intChange(title string, val1, val2 uint64) string { 62 return fmt.Sprintf("%20s %12d %12d %8.2f%%\n", title, val1, val2, float64(int64(val2)-int64(val1))*100/float64(val1)) 63 } 64 65 func floatChange(title string, val1, val2 float64) string { 66 return fmt.Sprintf("%20s %12.2f %12.2f %8.2f%%\n", title, val1, val2, float64(int64(val2)-int64(val1))*100/float64(val1)) 67 } 68 func timeChange(title string, val1, val2 time.Duration) string { 69 return fmt.Sprintf("%20s %12s %12s %8.2f%%\n", title, val1.String(), 70 val2.String(), float64(val2-val1)*100/float64(val1)) 71 } 72 73 func strDiff(title, val1, val2 string) string { 74 return fmt.Sprintf("%20s %12s %12s\n", title, val1, val2) 75 } 76 77 func compareTwoMap(m1, m2 map[string]stats.BenchResults) { 78 for k2, v2 := range m2 { 79 if v1, ok := m1[k2]; ok { 80 changes := k2 + "\n" 81 changes += fmt.Sprintf("%20s %12s %12s %8s\n", "Title", "Before", "After", "Percentage") 82 changes += intChange("TotalOps", v1.Data.TotalOps, v2.Data.TotalOps) 83 changes += intChange("SendOps", v1.Data.SendOps, v2.Data.SendOps) 84 changes += intChange("RecvOps", v1.Data.RecvOps, v2.Data.RecvOps) 85 changes += floatChange("Bytes/op", v1.Data.AllocedBytes, v2.Data.AllocedBytes) 86 changes += floatChange("Allocs/op", v1.Data.Allocs, v2.Data.Allocs) 87 changes += floatChange("ReqT/op", v1.Data.ReqT, v2.Data.ReqT) 88 changes += floatChange("RespT/op", v1.Data.RespT, v2.Data.RespT) 89 changes += timeChange("50th-Lat", v1.Data.Fiftieth, v2.Data.Fiftieth) 90 changes += timeChange("90th-Lat", v1.Data.Ninetieth, v2.Data.Ninetieth) 91 changes += timeChange("99th-Lat", v1.Data.NinetyNinth, v2.Data.NinetyNinth) 92 changes += timeChange("Avg-Lat", v1.Data.Average, v2.Data.Average) 93 changes += strDiff("GoVersion", v1.GoVersion, v2.GoVersion) 94 changes += strDiff("GrpcVersion", v1.GrpcVersion, v2.GrpcVersion) 95 fmt.Printf("%s\n", changes) 96 } 97 } 98 } 99 100 func compareBenchmark(file1, file2 string) { 101 compareTwoMap(createMap(file1), createMap(file2)) 102 } 103 104 func printHeader() { 105 fmt.Printf("%-80s%12s%12s%12s%18s%18s%18s%18s%12s%12s%12s%12s\n", 106 "Name", "TotalOps", "SendOps", "RecvOps", "Bytes/op (B)", "Allocs/op (#)", 107 "RequestT", "ResponseT", "L-50", "L-90", "L-99", "L-Avg") 108 } 109 110 func printline(benchName string, d stats.RunData) { 111 fmt.Printf("%-80s%12d%12d%12d%18.2f%18.2f%18.2f%18.2f%12v%12v%12v%12v\n", 112 benchName, d.TotalOps, d.SendOps, d.RecvOps, d.AllocedBytes, d.Allocs, 113 d.ReqT, d.RespT, d.Fiftieth, d.Ninetieth, d.NinetyNinth, d.Average) 114 } 115 116 func formatBenchmark(fileName string) { 117 f, err := os.Open(fileName) 118 if err != nil { 119 log.Fatalf("Read file %s error: %s\n", fileName, err) 120 } 121 defer f.Close() 122 var results []stats.BenchResults 123 decoder := gob.NewDecoder(f) 124 if err = decoder.Decode(&results); err != nil { 125 log.Fatalf("Decode file %s error: %s\n", fileName, err) 126 } 127 if len(results) == 0 { 128 log.Fatalf("No benchmark results in file %s\n", fileName) 129 } 130 131 fmt.Println("\nShared features:\n" + strings.Repeat("-", 20)) 132 fmt.Print(results[0].Features.SharedFeatures(results[0].SharedFeatures)) 133 fmt.Println(strings.Repeat("-", 35)) 134 135 wantFeatures := results[0].SharedFeatures 136 for i := 0; i < len(results[0].SharedFeatures); i++ { 137 wantFeatures[i] = !wantFeatures[i] 138 } 139 140 printHeader() 141 for _, r := range results { 142 printline(r.RunMode+r.Features.PrintableName(wantFeatures), r.Data) 143 } 144 } 145 146 func main() { 147 if len(os.Args) == 2 { 148 formatBenchmark(os.Args[1]) 149 } else { 150 compareBenchmark(os.Args[1], os.Args[2]) 151 } 152 }