// 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))) }