From 3133fea3e72b71d5fa5584a18b5de10354c86902 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys <hanwen@google.com> Date: Thu, 5 Sep 2019 19:53:32 +0200 Subject: [PATCH] contrib/benchmark-createchange: program to test BatchRefUpdate speed Useful for benchmarking reftable. Change-Id: Ic5081410c199764dd6cef4a99d69548e1eed40e7 --- contrib/benchmark-createchange.go | 103 ++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 contrib/benchmark-createchange.go diff --git a/contrib/benchmark-createchange.go b/contrib/benchmark-createchange.go new file mode 100644 index 0000000000..dc320d6ae1 --- /dev/null +++ b/contrib/benchmark-createchange.go @@ -0,0 +1,103 @@ +// Copyright (C) 2019 Google LLC +// +// 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. + +// Program to benchmark Gerrit. Creates pending changes in a loop, +// which tests performance of BatchRefUpdate and Lucene indexing +package main + +import ( + "bytes" + "encoding/base64" + "flag" + "fmt" + "io" + "log" + "net/http" + "net/url" + "os" + "sort" + "time" +) + +func main() { + user := flag.String("user", "admin", "username for basic auth") + pw := flag.String("password", "secret", "HTTP password for basic auth") + project := flag.String("project", "", "project to create changes in") + gerritURL := flag.String("url", "http://localhost:8080/", "URL to gerrit instance") + numChanges := flag.Int("n", 100, "number of changes to create") + flag.Parse() + if *gerritURL == "" { + log.Fatal("provide --url") + } + if *project == "" { + log.Fatal("provide --project") + } + + u, err := url.Parse(*gerritURL) + if err != nil { + log.Fatal(err) + } + + basicAuth := fmt.Sprintf("%s:%s", *user, *pw) + authHeader := base64.StdEncoding.EncodeToString([]byte(basicAuth)) + + client := &http.Client{} + + var dts []time.Duration + startAll := time.Now() + var lastSec int + for i := 0; i < *numChanges; i++ { + body := fmt.Sprintf(`{ + "project" : "%s", + "subject" : "change %d", + "branch" : "master", + "status" : "NEW" + }`, *project, i) + start := time.Now() + + thisSec := int(start.Sub(startAll) / time.Second) + if thisSec != lastSec { + log.Printf("change %d", i) + } + lastSec = thisSec + + u.Path = "/a/changes/" + req, err := http.NewRequest("POST", u.String(), bytes.NewBufferString(body)) + if err != nil { + log.Fatal(err) + } + req.Header.Add("Authorization", "Basic "+authHeader) + req.Header.Add("Content-Type", "application/json; charset=UTF-8") + resp, err := client.Do(req) + if err != nil { + log.Fatal(err) + } + dt := time.Now().Sub(start) + dts = append(dts, dt) + + if resp.StatusCode/100 == 2 { + continue + } + log.Println("code", resp.StatusCode) + io.Copy(os.Stdout, resp.Body) + } + + sort.Slice(dts, func(i, j int) bool { return dts[i] < dts[j] }) + + var total time.Duration + for _, dt := range dts { + total += dt + } + log.Printf("min %v max %v median %v avg %v", dts[0], dts[len(dts)-1], dts[len(dts)/2], total/time.Duration(len(dts))) +}