blob: 05e1b5db0d7fe9689ccbdcd7964e3d9e8f5c1e69 [file] [log] [blame]
David Benjamin54b04fd2023-01-29 11:56:25 -05001// Copyright (c) 2020 Google Inc.
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
David Benjaminece1f862023-04-24 16:14:08 -040015//go:build ignore
16
David Benjamin1d8ef2c2020-04-16 18:36:31 -040017// compare_benchmarks takes the JSON-formatted output of bssl speed and
18// compares it against a baseline output.
19package main
20
21import (
22 "encoding/json"
23 "flag"
24 "fmt"
David Benjamin1d8ef2c2020-04-16 18:36:31 -040025 "os"
26)
27
28var baselineFile = flag.String("baseline", "", "the path to the JSON file containing the base results")
29
30type Result struct {
31 Description string `json:"description"`
32 NumCalls int `json:"numCalls"`
33 Microseconds int `json:"microseconds"`
34 BytesPerCall int `json:"bytesPerCall"`
35}
36
37func (r *Result) Speed() (float64, string) {
38 callsPerSecond := float64(r.NumCalls) / float64(r.Microseconds) * 1000000
39 if r.BytesPerCall == 0 {
40 return callsPerSecond, "ops/sec"
41 }
42 return callsPerSecond * float64(r.BytesPerCall) / 1000000, "MB/sec"
43}
44
45func printResult(result Result, baseline *Result) error {
46 if baseline != nil {
47 if result.Description != baseline.Description {
48 return fmt.Errorf("result did not match baseline: %q vs %q", result.Description, baseline.Description)
49 }
50
51 if result.BytesPerCall != baseline.BytesPerCall {
52 return fmt.Errorf("result %q bytes per call did not match baseline: %d vs %d", result.Description, result.BytesPerCall, baseline.BytesPerCall)
53 }
54 }
55
56 newSpeed, unit := result.Speed()
57 fmt.Printf("Did %d %s operations in %dus (%.1f %s)", result.NumCalls, result.Description, result.Microseconds, newSpeed, unit)
58 if baseline != nil {
59 oldSpeed, _ := baseline.Speed()
60 fmt.Printf(" [%+.1f%%]", (newSpeed-oldSpeed)/oldSpeed*100)
61 }
62 fmt.Printf("\n")
63 return nil
64}
65
66func readResults(path string) ([]Result, error) {
David Benjamin5511fa82022-11-12 15:52:28 +000067 data, err := os.ReadFile(path)
David Benjamin1d8ef2c2020-04-16 18:36:31 -040068 if err != nil {
69 return nil, err
70 }
71 var ret []Result
72 if err := json.Unmarshal(data, &ret); err != nil {
73 return nil, err
74 }
75 return ret, nil
76}
77
78func main() {
79 flag.Parse()
80
81 baseline, err := readResults(*baselineFile)
82 if err != nil {
83 fmt.Fprintf(os.Stderr, "Error reading %q: %s\n", *baselineFile, err)
84 os.Exit(1)
85 }
86
87 fmt.Println(*baselineFile)
88 for _, result := range baseline {
89 if err := printResult(result, nil); err != nil {
90 fmt.Fprintf(os.Stderr, "Error in %q: %s\n", *baselineFile, err)
91 os.Exit(1)
92 }
93 }
94
95 for _, arg := range flag.Args() {
96 results, err := readResults(arg)
97 if err != nil {
98 fmt.Fprintf(os.Stderr, "Error reading %q: %s\n", arg, err)
99 os.Exit(1)
100 }
101
102 if len(results) != len(baseline) {
103 fmt.Fprintf(os.Stderr, "Result files %q and %q have different lengths\n", arg, *baselineFile)
104 os.Exit(1)
105 }
106
107 fmt.Printf("\n%s\n", arg)
108 for i, result := range results {
109 if err := printResult(result, &baseline[i]); err != nil {
110 fmt.Fprintf(os.Stderr, "Error in %q: %s\n", arg, err)
111 os.Exit(1)
112 }
113 }
114 }
115}