blob: 4daaf969f4f2e5255637678eddcb55847d7b41b8 [file] [log] [blame]
// Copyright (C) 2016 The Android Open Source Project
// 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
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
var (
flagTimeout time.Duration
flagBenchmarkName string
flagBenchmarkComment string
flagSampleLimit int
flagSampleOrder string
flagMaxWidth int
flagMaxHeight int
flagBenchmarkType string
flagSeed int64
flagRuns int
flagEnableCpuProfile bool
flagEnableHeapProfile bool
flagBundleGapis bool
flagBundleTraces bool
flagTextualOutput string
flagPerfzOutput string
func init() {
verb := &app.Verb{
Name: "run",
ShortHelp: "Runs a single benchmark and adds the results to the passed perfz file",
Run: runVerb,
ShortUsage: "<perfz> <trace>",
verb.Flags.DurationVar(&flagTimeout, "timeout", -1, "stop after this time interval")
verb.Flags.StringVar(&flagBenchmarkName, "name", "default", "benchmark name")
verb.Flags.StringVar(&flagBenchmarkComment, "comment", "", "benchmark comment")
verb.Flags.IntVar(&flagSampleLimit, "samples", 50, "how many samples to grab (if applicable)")
verb.Flags.StringVar(&flagSampleOrder, "order", "random", "order in which to process samples (if applicable)")
verb.Flags.IntVar(&flagMaxWidth, "max_width", 1280, "maximum frame width to get")
verb.Flags.IntVar(&flagMaxHeight, "max_height", 720, "maximum frame height to get")
verb.Flags.StringVar(&flagBenchmarkType, "what", "state", "what to test [state|frames|startup]")
verb.Flags.Int64Var(&flagSeed, "seed", 1, "seed to pass to the random number generator")
verb.Flags.IntVar(&flagRuns, "runs", 1, "how many times to repeat the whole process")
verb.Flags.BoolVar(&flagEnableCpuProfile, "cpu", false, "profile GAPIS CPU usage")
verb.Flags.BoolVar(&flagEnableHeapProfile, "heap", false, "profile GAPIS heap usage")
verb.Flags.BoolVar(&flagBundleGapis, "bg", false, "bundle GAPIS")
verb.Flags.BoolVar(&flagBundleTraces, "bt", false, "bundle traces")
verb.Flags.StringVar(&flagTextualOutput, "json", "-", "output results in JSON format")
verb.Flags.StringVar(&flagPerfzOutput, "o", "", "output .perfz file, same as input if empty")
func fileLink(bench *Benchmark, filename string, nameTemplate string, bundle bool) (*Link, error) {
dataEntry := &DataEntry{
DataSource: FileDataSource(filename),
Bundle: bundle,
Source: filename,
link, err := bench.Root().NewLink(dataEntry)
if err != nil {
return nil, err
dataEntry.Name = strings.Replace(nameTemplate, "{{id}}", link.Key, -1)
return link, nil
func newGapisLink(bench *Benchmark, bundle bool) (*Link, error) {
return fileLink(bench, gapis.GapisPath.System(), "gapis/{{id}}", bundle)
func initializeBenchmarkInputFromFlags(flags flag.FlagSet, traceFile string, bench *Benchmark) error {
args := &bench.Input
args.Name = flagBenchmarkName
args.MaxSamples = flagSampleLimit
trace, err := fileLink(bench, traceFile, "traces/{{id}}.gfxtrace", flagBundleTraces)
if err != nil {
return err
args.Trace = trace
g, err := newGapisLink(bench, flagBundleGapis)
if err != nil {
return err
args.Gapis = g
args.MaxFrameHeight = flagMaxHeight
args.MaxFrameWidth = flagMaxWidth
args.Seed = flagSeed
args.BenchmarkType = flagBenchmarkType
args.SampleOrder = flagSampleOrder
args.Runs = flagRuns
args.Timeout = flagTimeout
args.EnableHeapProfile = flagEnableHeapProfile
args.EnableCpuProfile = flagEnableCpuProfile
args.Comment = flagBenchmarkComment
return err
func runVerb(ctx log.Context, flags flag.FlagSet) error {
if flags.NArg() != 2 {
app.Usage(ctx, "Two arguments expected, got %d", flags.NArg())
return nil
perfzFile := flags.Arg(0)
perfz, err := LoadPerfz(ctx, perfzFile, flagVerifyHashes)
if err != nil {
ctx.Info().Logf("Could not load .perfz file, starting new one.")
perfz = NewPerfz()
traceFile := flags.Arg(1)
bench := perfz.NewBenchmarkWithName(flagBenchmarkName)
if err := initializeBenchmarkInputFromFlags(flags, traceFile, bench); err != nil {
return err
if err := fullRun(ctx, bench); err != nil {
return ctx.WrapError(err, "fullRun")
if err := writeAllFn(flagTextualOutput, func(w io.Writer) error {
_, err := w.Write([]byte(perfz.String()))
return err
}); err != nil {
return ctx.WrapError(err, "writeAll")
if flagPerfzOutput == "" {
flagPerfzOutput = perfzFile
err = perfz.WriteTo(ctx, flagPerfzOutput)
if err != nil {
return ctx.WrapError(err, "perfz.WriteTo")
return nil