blob: cc020cdad64947e8cc79bbfb62a1dd5133c2b9e4 [file] [log] [blame]
Austin Engcc2516a2023-10-17 20:57:54 +00001// Copyright 2022 The Dawn & Tint Authors
Ben Clayton2f60bbd2022-11-21 19:14:32 +00002//
Austin Engcc2516a2023-10-17 20:57:54 +00003// Redistribution and use in source and binary forms, with or without
4// modification, are permitted provided that the following conditions are met:
Ben Clayton2f60bbd2022-11-21 19:14:32 +00005//
Austin Engcc2516a2023-10-17 20:57:54 +00006// 1. Redistributions of source code must retain the above copyright notice, this
7// list of conditions and the following disclaimer.
Ben Clayton2f60bbd2022-11-21 19:14:32 +00008//
Austin Engcc2516a2023-10-17 20:57:54 +00009// 2. Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12//
13// 3. Neither the name of the copyright holder nor the names of its
14// contributors may be used to endorse or promote products derived from
15// this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Ben Clayton2f60bbd2022-11-21 19:14:32 +000027
28// tint-bench repeatedly emits a WGSL file from a template, then times how long
29// it takes to execute the tint executable with that WGSL file.
30package main
31
32import (
33 "flag"
34 "fmt"
Ben Clayton2f60bbd2022-11-21 19:14:32 +000035 "os"
36 "os/exec"
37 "path/filepath"
38 "sort"
39 "time"
40
41 "dawn.googlesource.com/dawn/tools/src/fileutils"
42 "dawn.googlesource.com/dawn/tools/src/template"
43)
44
45func main() {
46 if err := run(); err != nil {
47 fmt.Println(err)
48 os.Exit(1)
49 }
50}
51
52// [from .. to]
53type Range struct {
54 from int
55 to int
56}
57
58func run() error {
59 alphaRange := Range{}
60
61 iterations := 0
62 tmplPath := ""
63 flag.StringVar(&tmplPath, "tmpl", "tint-bench.tmpl", `the WGSL template to benchmark.
64Searches in order: absolute, relative to CWD, then relative to `+fileutils.ThisDir())
65 flag.IntVar(&alphaRange.from, "alpha-from", 0, "the start value for 'Alpha'")
66 flag.IntVar(&alphaRange.to, "alpha-to", 10, "the end value for 'Alpha'")
67 flag.IntVar(&iterations, "iterations", 10, "number of times to benchmark tint")
68 flag.Usage = func() {
69 fmt.Println("tint-bench repeatedly emits a WGSL file from a template, then times how long")
70 fmt.Println("it takes to execute the tint executable with that WGSL file.")
71 fmt.Println("")
72 fmt.Println("usage:")
73 fmt.Println(" tint-bench <bench-flags> [tint-exe] <tint-flags>")
74 fmt.Println("")
75 fmt.Println("bench-flags:")
76 flag.PrintDefaults()
77 os.Exit(1)
78 }
79
80 flag.Parse()
81
82 if tmplPath == "" {
83 return fmt.Errorf("missing template path")
84 }
85
Ben Clayton70a26132023-08-12 09:24:21 +000086 tmpl, err := template.FromFile(tmplPath)
Ben Clayton2f60bbd2022-11-21 19:14:32 +000087 if err != nil {
88 if !filepath.IsAbs(tmplPath) {
89 // Try relative to this .go file
90 tmplPath = filepath.Join(fileutils.ThisDir(), tmplPath)
Ben Clayton70a26132023-08-12 09:24:21 +000091 tmpl, err = template.FromFile(tmplPath)
Ben Clayton2f60bbd2022-11-21 19:14:32 +000092 }
93 }
94 if err != nil {
95 return fmt.Errorf("failed to load template: %v", err)
96 }
97
98 args := flag.Args()
99 if len(args) < 1 {
100 flag.Usage()
101 }
102 tintExe := args[0]
103
104 fmt.Println(" alpha | Time (μs)")
105 fmt.Println("-------+-----------------")
106
107 for alpha := alphaRange.from; alpha < alphaRange.to; alpha++ {
108 alpha := alpha
109 funcs := template.Functions{
110 "Alpha": func() int { return alpha },
111 }
Ben Clayton70a26132023-08-12 09:24:21 +0000112 wgslPath, err := writeWGSLFile(tmpl, funcs)
Ben Clayton2f60bbd2022-11-21 19:14:32 +0000113 if err != nil {
114 return err
115 }
116
117 tintArgs := []string{wgslPath}
118 tintArgs = append(tintArgs, args[1:]...)
119
120 durations := []time.Duration{}
121 for i := 0; i < iterations; i++ {
122 tint := exec.Command(tintExe, tintArgs...)
123 start := time.Now()
124 if out, err := tint.CombinedOutput(); err != nil {
125 return fmt.Errorf("tint failed with error: %w\n%v\n\nwith: Alpha=%v", err, string(out), alpha)
126 }
127 duration := time.Since(start)
128 durations = append(durations, duration)
129 }
130 sort.Slice(durations, func(i, j int) bool { return durations[i] < durations[j] })
131
132 median := durations[len(durations)/2]
133 fmt.Printf("%6.v | %v\n", alpha, median.Microseconds())
134 }
135 return nil
136}
137
Ben Clayton70a26132023-08-12 09:24:21 +0000138func writeWGSLFile(tmpl *template.Template, funcs template.Functions) (string, error) {
Ben Clayton2f60bbd2022-11-21 19:14:32 +0000139 const path = "tint-bench.wgsl"
140 wgslFile, err := os.Create(path)
141 if err != nil {
142 return "", fmt.Errorf("failed to create benchmark WGSL test file: %w", err)
143 }
144 defer wgslFile.Close()
Ben Clayton70a26132023-08-12 09:24:21 +0000145 if err := tmpl.Run(wgslFile, nil, funcs); err != nil {
Ben Clayton2f60bbd2022-11-21 19:14:32 +0000146 return "", fmt.Errorf("template error:\n%w", err)
147 }
148 return path, nil
149}