148 lines
4.9 KiB
Go
148 lines
4.9 KiB
Go
// Copyright 2020 The gVisor Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Binary parser parses Benchmark data from golang benchmarks,
|
|
// puts it into a Schema for BigQuery, and sends it to BigQuery.
|
|
// parser will also initialize a table with the Benchmarks BigQuery schema.
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
|
|
"gvisor.dev/gvisor/runsc/flag"
|
|
bq "gvisor.dev/gvisor/tools/bigquery"
|
|
"gvisor.dev/gvisor/tools/parsers"
|
|
)
|
|
|
|
const (
|
|
initString = "init"
|
|
initDescription = "initializes a new table with benchmarks schema"
|
|
parseString = "parse"
|
|
parseDescription = "parses given benchmarks file and sends it to BigQuery table."
|
|
)
|
|
|
|
var (
|
|
// The init command will create a new dataset/table in the given project and initialize
|
|
// the table with the schema in //tools/bigquery/bigquery.go. If the table/dataset exists
|
|
// or has been initialized, init has no effect and successfully returns.
|
|
initCmd = flag.NewFlagSet(initString, flag.ContinueOnError)
|
|
initProject = initCmd.String("project", "", "GCP project to send benchmarks.")
|
|
initDataset = initCmd.String("dataset", "", "dataset to send benchmarks data.")
|
|
initTable = initCmd.String("table", "", "table to send benchmarks data.")
|
|
|
|
// The parse command parses benchmark data in `file` and sends it to the
|
|
// requested table.
|
|
parseCmd = flag.NewFlagSet(parseString, flag.ContinueOnError)
|
|
file = parseCmd.String("file", "", "file to parse for benchmarks")
|
|
name = parseCmd.String("suite_name", "", "name of the benchmark suite")
|
|
parseProject = parseCmd.String("project", "", "GCP project to send benchmarks.")
|
|
parseDataset = parseCmd.String("dataset", "", "dataset to send benchmarks data.")
|
|
parseTable = parseCmd.String("table", "", "table to send benchmarks data.")
|
|
official = parseCmd.Bool("official", false, "mark input data as official.")
|
|
runtime = parseCmd.String("runtime", "", "runtime used to run the benchmark")
|
|
debug = parseCmd.Bool("debug", false, "print debug logs")
|
|
)
|
|
|
|
// initBenchmarks initializes a dataset/table in a BigQuery project.
|
|
func initBenchmarks(ctx context.Context) error {
|
|
return bq.InitBigQuery(ctx, *initProject, *initDataset, *initTable, nil)
|
|
}
|
|
|
|
// parseBenchmarks parses the given file into the BigQuery schema,
|
|
// adds some custom data for the commit, and sends the data to BigQuery.
|
|
func parseBenchmarks(ctx context.Context) error {
|
|
debugLog("Reading file: %s", *file)
|
|
data, err := ioutil.ReadFile(*file)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read file %s: %v", *file, err)
|
|
}
|
|
debugLog("Parsing output: %s", string(data))
|
|
suite, err := parsers.ParseOutput(string(data), *name, *official)
|
|
if err != nil {
|
|
return fmt.Errorf("failed parse data: %v", err)
|
|
}
|
|
debugLog("Parsed benchmarks: %d", len(suite.Benchmarks))
|
|
if len(suite.Benchmarks) < 1 {
|
|
fmt.Fprintf(os.Stderr, "Failed to find benchmarks for file: %s", *file)
|
|
return nil
|
|
}
|
|
|
|
extraConditions := []*bq.Condition{
|
|
{
|
|
Name: "runtime",
|
|
Value: *runtime,
|
|
},
|
|
{
|
|
Name: "version",
|
|
Value: version,
|
|
},
|
|
}
|
|
|
|
suite.Official = *official
|
|
suite.Conditions = append(suite.Conditions, extraConditions...)
|
|
debugLog("Sending benchmarks")
|
|
return bq.SendBenchmarks(ctx, suite, *parseProject, *parseDataset, *parseTable, nil)
|
|
}
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
switch {
|
|
// the "init" command
|
|
case len(os.Args) >= 2 && os.Args[1] == initString:
|
|
if err := initCmd.Parse(os.Args[2:]); err != nil {
|
|
log.Fatalf("Failed parse flags: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
if err := initBenchmarks(ctx); err != nil {
|
|
failure := "failed to initialize project: %s dataset: %s table: %s: %v\n"
|
|
log.Fatalf(failure, *parseProject, *parseDataset, *parseTable, err)
|
|
os.Exit(1)
|
|
}
|
|
// the "parse" command.
|
|
case len(os.Args) >= 2 && os.Args[1] == parseString:
|
|
if err := parseCmd.Parse(os.Args[2:]); err != nil {
|
|
log.Fatalf("Failed parse flags: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
if err := parseBenchmarks(ctx); err != nil {
|
|
log.Fatalf("Failed parse benchmarks: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
default:
|
|
printUsage()
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// printUsage prints the top level usage string.
|
|
func printUsage() {
|
|
usage := `Usage: parser <command> <flags> ...
|
|
|
|
Available commands:
|
|
%s %s
|
|
%s %s
|
|
`
|
|
log.Printf(usage, initCmd.Name(), initDescription, parseCmd.Name(), parseDescription)
|
|
}
|
|
|
|
func debugLog(msg string, args ...interface{}) {
|
|
if *debug {
|
|
log.Printf(msg, args...)
|
|
}
|
|
}
|