blob: a1c8bb5a7495d708b1655fcc2495ee9871305f46 [file] [log] [blame]
// 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)
}
}