| // Copyright 2020 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // benchfilter reads Go benchmark results from input files, filters |
| // them, and writes filtered benchmark results to stdout. If no inputs |
| // are provided, it reads from stdin. |
| // |
| // The filter language is described at |
| // https://pkg.go.dev/golang.org/x/perf/cmd/benchstat#Filtering |
| package main |
| |
| import ( |
| "flag" |
| "fmt" |
| "log" |
| "os" |
| |
| "golang.org/x/perf/benchfmt" |
| "golang.org/x/perf/benchproc" |
| ) |
| |
| func usage() { |
| fmt.Fprintf(flag.CommandLine.Output(), `Usage: benchfilter query [inputs...] |
| |
| benchfilter reads Go benchmark results from input files, filters them, |
| and writes filtered benchmark results to stdout. If no inputs are |
| provided, it reads from stdin. |
| |
| The filter language is described at |
| https://pkg.go.dev/golang.org/x/perf/cmd/benchstat#hdr-Filtering |
| `) |
| flag.PrintDefaults() |
| } |
| |
| func main() { |
| log.SetPrefix("") |
| log.SetFlags(0) |
| |
| flag.Usage = usage |
| flag.Parse() |
| if flag.NArg() < 1 { |
| usage() |
| os.Exit(2) |
| } |
| |
| // TODO: Consider adding filtering on values, like "@ns/op>=100". |
| |
| filter, err := benchproc.NewFilter(flag.Arg(0)) |
| if err != nil { |
| log.Fatal(err) |
| } |
| |
| writer := benchfmt.NewWriter(os.Stdout) |
| files := benchfmt.Files{Paths: flag.Args()[1:], AllowStdin: true, AllowLabels: true} |
| for files.Scan() { |
| rec := files.Result() |
| switch rec := rec.(type) { |
| case *benchfmt.SyntaxError: |
| // Non-fatal result parse error. Warn |
| // but keep going. |
| fmt.Fprintln(os.Stderr, rec) |
| continue |
| case *benchfmt.Result: |
| if ok, err := filter.Apply(rec); !ok { |
| if err != nil { |
| // Print the reason we rejected this result. |
| fmt.Fprintln(os.Stderr, err) |
| } |
| continue |
| } |
| } |
| |
| err = writer.Write(rec) |
| if err != nil { |
| log.Fatal("writing output: ", err) |
| } |
| } |
| if err := files.Err(); err != nil { |
| log.Fatal(err) |
| } |
| } |