3 * Copyright 2017 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 To format the benchmark result:
21 go run benchmark/benchresult/main.go resultfile
23 To see the performance change based on a old result:
24 go run benchmark/benchresult/main.go resultfile_old resultfile
25 It will print the comparison result of intersection benchmarks between two files.
39 "google.golang.org/grpc/benchmark/stats"
42 func createMap(fileName string, m map[string]stats.BenchResults) {
43 f, err := os.Open(fileName)
45 log.Fatalf("Read file %s error: %s\n", fileName, err)
48 var data []stats.BenchResults
49 decoder := gob.NewDecoder(f)
50 if err = decoder.Decode(&data); err != nil {
51 log.Fatalf("Decode file %s error: %s\n", fileName, err)
53 for _, d := range data {
54 m[d.RunMode+"-"+d.Features.String()] = d
58 func intChange(title string, val1, val2 int64) string {
59 return fmt.Sprintf("%10s %12s %12s %8.2f%%\n", title, strconv.FormatInt(val1, 10),
60 strconv.FormatInt(val2, 10), float64(val2-val1)*100/float64(val1))
63 func timeChange(title int, val1, val2 time.Duration) string {
64 return fmt.Sprintf("%10s %12s %12s %8.2f%%\n", strconv.Itoa(title)+" latency", val1.String(),
65 val2.String(), float64(val2-val1)*100/float64(val1))
68 func compareTwoMap(m1, m2 map[string]stats.BenchResults) {
69 for k2, v2 := range m2 {
70 if v1, ok := m1[k2]; ok {
72 changes += fmt.Sprintf("%10s %12s %12s %8s\n", "Title", "Before", "After", "Percentage")
73 changes += intChange("Bytes/op", v1.AllocedBytesPerOp, v2.AllocedBytesPerOp)
74 changes += intChange("Allocs/op", v1.AllocsPerOp, v2.AllocsPerOp)
75 changes += timeChange(v1.Latency[1].Percent, v1.Latency[1].Value, v2.Latency[1].Value)
76 changes += timeChange(v1.Latency[2].Percent, v1.Latency[2].Value, v2.Latency[2].Value)
77 fmt.Printf("%s\n", changes)
82 func compareBenchmark(file1, file2 string) {
83 var BenchValueFile1 map[string]stats.BenchResults
84 var BenchValueFile2 map[string]stats.BenchResults
85 BenchValueFile1 = make(map[string]stats.BenchResults)
86 BenchValueFile2 = make(map[string]stats.BenchResults)
88 createMap(file1, BenchValueFile1)
89 createMap(file2, BenchValueFile2)
91 compareTwoMap(BenchValueFile1, BenchValueFile2)
94 func printline(benchName, ltc50, ltc90, allocByte, allocsOp interface{}) {
95 fmt.Printf("%-80v%12v%12v%12v%12v\n", benchName, ltc50, ltc90, allocByte, allocsOp)
98 func formatBenchmark(fileName string) {
99 f, err := os.Open(fileName)
101 log.Fatalf("Read file %s error: %s\n", fileName, err)
104 var data []stats.BenchResults
105 decoder := gob.NewDecoder(f)
106 if err = decoder.Decode(&data); err != nil {
107 log.Fatalf("Decode file %s error: %s\n", fileName, err)
110 log.Fatalf("No data in file %s\n", fileName)
112 printPos := data[0].SharedPosion
113 fmt.Println("\nShared features:\n" + strings.Repeat("-", 20))
114 fmt.Print(stats.PartialPrintString(printPos, data[0].Features, true))
115 fmt.Println(strings.Repeat("-", 35))
116 for i := 0; i < len(data[0].SharedPosion); i++ {
117 printPos[i] = !printPos[i]
119 printline("Name", "latency-50", "latency-90", "Alloc (B)", "Alloc (#)")
120 for _, d := range data {
121 name := d.RunMode + stats.PartialPrintString(printPos, d.Features, false)
122 printline(name, d.Latency[1].Value.String(), d.Latency[2].Value.String(),
123 d.AllocedBytesPerOp, d.AllocsPerOp)
128 if len(os.Args) == 2 {
129 formatBenchmark(os.Args[1])
131 compareBenchmark(os.Args[1], os.Args[2])