1
18
19
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 }
153
View as plain text