gitaly-bench.go (139 lines of code) (raw):

package main import ( "flag" "fmt" "io/ioutil" "log" "os" "strings" "github.com/pkg/profile" "gitlab.com/gitlab-org/gitaly-bench/benchmarks" "gitlab.com/gitlab-org/gitaly-bench/operations" "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb" gitalyauth "gitlab.com/gitlab-org/gitaly/auth" "gitlab.com/gitlab-org/gitaly/client" "google.golang.org/grpc" ) var ( hostFlag = flag.String("host", "tcp://127.0.0.1:9999", "The server address in the format of host:port") storage = flag.String("storage", "default", "The storage to test") gitRepoPath = flag.String("repo", "", "Relative path of git repo within storage") iterations = flag.Int("iterations", 10, "Number of iterations to perform on each thread") parallel = flag.Int("concurrency", 10, "Number of concurrent threads to test the benchmark on") profileFlag = flag.String("profile", "", "Profiling mode: `block` / `cpu` / `mem` / `mutex` ") authFlag = flag.String("auth", "", "Authentication token") authFileFlag = flag.String("auth-file", "", "Path to a text file containing the authentication token") ) func newConnection() (*grpc.ClientConn, error) { connOpts := make([]grpc.DialOption, len(client.DefaultDialOpts)) copy(connOpts, client.DefaultDialOpts) token := "" if *authFileFlag != "" { contents, err := ioutil.ReadFile(*authFileFlag) if err != nil { log.Fatalf("unable to read auth-file: %v", err) } token = string(contents) token = strings.TrimRight(token, "\n\r") } else if *authFlag != "" { token = *authFlag } if token != "" { connOpts = append(connOpts, grpc.WithPerRPCCredentials(gitalyauth.RPCCredentialsV2(token))) } conn, err := client.Dial(*hostFlag, connOpts) if err != nil { return nil, err } return conn, nil } func getProfileOpt(name string) func(p *profile.Profile) { switch *profileFlag { case "block": return profile.BlockProfile case "cpu": return profile.CPUProfile case "mem": return profile.MemProfile case "mutex": return profile.MutexProfile default: return nil } } func main() { commands := map[string]*struct { flagSet *flag.FlagSet builder func(repository *gitalypb.Repository, conn *grpc.ClientConn) operations.BenchmarkOperation }{ "gc": {flagSet: operations.GCFlagSet, builder: operations.NewGC}, "repack-full": {flagSet: operations.GCFlagSet, builder: operations.NewRepackFull}, "find-all-branch-names": {flagSet: nil, builder: operations.NewFindAllBranchNames}, "find-all-branches": {flagSet: nil, builder: operations.NewFindAllBranches}, "commit-diff": {flagSet: operations.CommitDiffFlagSet, builder: operations.NewCommitDiff}, "ref-exists": {flagSet: operations.RefExistsFlagSet, builder: operations.NewRefExists}, "info-refs": {flagSet: nil, builder: operations.NewInfoRefs}, "has-local-branches": {flagSet: nil, builder: operations.NewHasLocalBranches}, "find-commit": {flagSet: operations.FindCommitFlagSet, builder: operations.NewFindCommit}, } flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage of gitaly-bench [options] command:\n\n") fmt.Fprintf(os.Stderr, "Options:\n") flag.PrintDefaults() fmt.Fprintf(os.Stderr, "\n`command` being one of:\n") for k := range commands { fmt.Fprintf(os.Stderr, "\t%v\n", k) } fmt.Fprintf(os.Stderr, "Use gitaly-bench command --help for command options\n") } flag.Parse() if *gitRepoPath == "" { flag.Usage() os.Exit(1) } // Verify that a subcommand has been provided if len(flag.Args()) < 1 { flag.Usage() os.Exit(1) } if *profileFlag != "" { profileOpt := getProfileOpt(*profileFlag) if profileOpt == nil { flag.Usage() os.Exit(1) } defer profile.Start(profileOpt, profile.ProfilePath(".")).Stop() } benchmarkName := flag.Arg(0) command := commands[benchmarkName] if command == nil { flag.Usage() os.Exit(1) } if command.flagSet != nil { err := command.flagSet.Parse(flag.Args()[1:]) if err != nil || len(command.flagSet.Args()) > 0 { if len(command.flagSet.Args()) > 0 { fmt.Println("Unknown argument", strings.Join(command.flagSet.Args(), " ")) } command.flagSet.Usage() os.Exit(1) } } else { if len(flag.Args()) > 1 { fmt.Println("Unknown argument", strings.Join(flag.Args()[1:], " ")) flag.Usage() os.Exit(1) } } conn, err := newConnection() if err != nil { panic(err) } defer conn.Close() repository := &gitalypb.Repository{ StorageName: *storage, RelativePath: *gitRepoPath, } operation := command.builder(repository, conn) benchmarks.RunBenchmark(benchmarkName, *parallel, *iterations, operation) }