149 lines
3.7 KiB
Go
149 lines
3.7 KiB
Go
// Copyright 2022 The Dawn 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.
|
|
|
|
package time
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"math"
|
|
"sort"
|
|
"time"
|
|
|
|
"dawn.googlesource.com/dawn/tools/src/cmd/cts/common"
|
|
"dawn.googlesource.com/dawn/tools/src/cts/result"
|
|
"dawn.googlesource.com/dawn/tools/src/subcmd"
|
|
"go.chromium.org/luci/auth/client/authcli"
|
|
)
|
|
|
|
func init() {
|
|
common.Register(&cmd{})
|
|
}
|
|
|
|
type cmd struct {
|
|
flags struct {
|
|
source common.ResultSource
|
|
auth authcli.Flags
|
|
tags string
|
|
topN int
|
|
histogram bool
|
|
}
|
|
}
|
|
|
|
func (cmd) Name() string {
|
|
return "time"
|
|
}
|
|
|
|
func (cmd) Desc() string {
|
|
return "displays timing information for tests"
|
|
}
|
|
|
|
func (c *cmd) RegisterFlags(ctx context.Context, cfg common.Config) ([]string, error) {
|
|
c.flags.source.RegisterFlags(cfg)
|
|
c.flags.auth.Register(flag.CommandLine, common.DefaultAuthOptions())
|
|
flag.IntVar(&c.flags.topN, "top", 0, "print the top N slowest tests")
|
|
flag.BoolVar(&c.flags.histogram, "histogram", false, "print a histogram of test timings")
|
|
flag.StringVar(&c.flags.tags, "tags", "", "comma-separated list of tags to filter results")
|
|
return nil, nil
|
|
}
|
|
|
|
func (c *cmd) Run(ctx context.Context, cfg common.Config) error {
|
|
// Validate command line arguments
|
|
auth, err := c.flags.auth.Options()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to obtain authentication options: %w", err)
|
|
}
|
|
|
|
// Obtain the results
|
|
results, err := c.flags.source.GetResults(ctx, cfg, auth)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(results) == 0 {
|
|
return fmt.Errorf("no results found")
|
|
}
|
|
|
|
// If tags were provided, filter the results to those that contain these tags
|
|
if c.flags.tags != "" {
|
|
results = results.FilterByTags(result.StringToTags(c.flags.tags))
|
|
if len(results) == 0 {
|
|
return fmt.Errorf("no results after filtering by tags")
|
|
}
|
|
}
|
|
|
|
// Sort the results with longest duration first
|
|
sort.Slice(results, func(i, j int) bool {
|
|
return results[i].Duration > results[j].Duration
|
|
})
|
|
|
|
didSomething := false
|
|
|
|
// Did the user request --top N ?
|
|
if c.flags.topN > 0 {
|
|
didSomething = true
|
|
topN := results
|
|
if c.flags.topN < len(results) {
|
|
topN = topN[:c.flags.topN]
|
|
}
|
|
for i, r := range topN {
|
|
fmt.Printf("%3.1d: %v\n", i, r)
|
|
}
|
|
}
|
|
|
|
// Did the user request --histogram ?
|
|
if c.flags.histogram {
|
|
maxTime := results[0].Duration
|
|
|
|
const (
|
|
numBins = 25
|
|
pow = 2.0
|
|
)
|
|
|
|
binToDuration := func(i int) time.Duration {
|
|
frac := math.Pow(float64(i)/float64(numBins), pow)
|
|
return time.Duration(float64(maxTime) * frac)
|
|
}
|
|
durationToBin := func(d time.Duration) int {
|
|
frac := math.Pow(float64(d)/float64(maxTime), 1.0/pow)
|
|
idx := int(frac * numBins)
|
|
if idx >= numBins-1 {
|
|
return numBins - 1
|
|
}
|
|
return idx
|
|
}
|
|
|
|
didSomething = true
|
|
bins := make([]int, numBins)
|
|
for _, r := range results {
|
|
idx := durationToBin(r.Duration)
|
|
bins[idx] = bins[idx] + 1
|
|
}
|
|
for i, bin := range bins {
|
|
fmt.Printf("[%.8v, %.8v]: %v\n", binToDuration(i), binToDuration(i+1), bin)
|
|
}
|
|
}
|
|
|
|
// If the user didn't request anything, show a helpful message
|
|
if !didSomething {
|
|
fmt.Fprintln(flag.CommandLine.Output(), "no action flags specified for", c.Name())
|
|
fmt.Fprintln(flag.CommandLine.Output())
|
|
flag.Usage()
|
|
return subcmd.ErrInvalidCLA
|
|
}
|
|
|
|
return nil
|
|
}
|