mirror of https://github.com/cirruslabs/tart.git
109 lines
2.5 KiB
Go
109 lines
2.5 KiB
Go
package xcode
|
|
|
|
import (
|
|
"fmt"
|
|
executorpkg "github.com/cirruslabs/tart/benchmark/internal/executor"
|
|
"github.com/gosuri/uitable"
|
|
"github.com/spf13/cobra"
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zapio"
|
|
"os"
|
|
"os/exec"
|
|
)
|
|
|
|
var debug bool
|
|
var image string
|
|
var prepare string
|
|
|
|
func NewCommand() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "xcode",
|
|
Short: "run XCode benchmarks",
|
|
RunE: run,
|
|
}
|
|
|
|
cmd.Flags().BoolVar(&debug, "debug", false, "enable debug logging")
|
|
cmd.Flags().StringVar(&image, "image", "ghcr.io/cirruslabs/macos-tahoe-xcode:latest", "image to use for testing")
|
|
cmd.Flags().StringVar(&prepare, "prepare", "", "command to run before running each benchmark")
|
|
|
|
return cmd
|
|
}
|
|
|
|
func run(cmd *cobra.Command, args []string) error {
|
|
config := zap.NewProductionConfig()
|
|
if debug {
|
|
config.Level = zap.NewAtomicLevelAt(zap.DebugLevel)
|
|
}
|
|
logger, err := config.Build()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func() {
|
|
_ = logger.Sync()
|
|
}()
|
|
|
|
table := uitable.New()
|
|
table.AddRow("Name", "Executor", "Time")
|
|
|
|
for _, benchmark := range benchmarks {
|
|
for _, executorInitializer := range executorpkg.DefaultInitializers(cmd.Context(), image, logger) {
|
|
if prepare != "" {
|
|
shell := "/bin/sh"
|
|
|
|
if shellFromEnv, ok := os.LookupEnv("SHELL"); ok {
|
|
shell = shellFromEnv
|
|
}
|
|
|
|
logger.Sugar().Infof("running prepare command %q using shell %q",
|
|
prepare, shell)
|
|
|
|
cmd := exec.CommandContext(cmd.Context(), shell, "-c", prepare)
|
|
|
|
loggerWriter := &zapio.Writer{Log: logger, Level: zap.DebugLevel}
|
|
|
|
cmd.Stdout = loggerWriter
|
|
cmd.Stderr = loggerWriter
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to run prepare command %q: %v", prepare, err)
|
|
}
|
|
}
|
|
|
|
logger.Sugar().Infof("initializing executor %s", executorInitializer.Name)
|
|
|
|
executor, err := executorInitializer.Fn()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
logger.Sugar().Infof("running benchmark %q on %s executor", benchmark.Name,
|
|
executorInitializer.Name)
|
|
|
|
stdout, err := executor.Run(cmd.Context(), benchmark.Command)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
output, err := ParseOutput(string(stdout))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
duration := output.Ended.Sub(output.Started)
|
|
|
|
logger.Sugar().Infof("Xcode benchmark duration: %s", duration)
|
|
|
|
table.AddRow(benchmark.Name, executorInitializer.Name, duration)
|
|
|
|
if err := executor.Close(); err != nil {
|
|
return fmt.Errorf("failed to close executor %s: %w",
|
|
executorInitializer.Name, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
fmt.Println(table.String())
|
|
|
|
return nil
|
|
}
|