0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2024-12-16 21:56:37 -05:00

ci/cd: add continuous benchmark action

Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com>
This commit is contained in:
Ramkumar Chinchani 2022-01-13 22:06:35 +00:00 committed by Ramkumar Chinchani
parent 72da8303c5
commit 6a2529f08f
4 changed files with 90 additions and 7 deletions

40
.github/workflows/benchmark.yaml vendored Normal file
View file

@ -0,0 +1,40 @@
name: "Minimal Continuous Benchmark"
on:
push:
branches:
- main
pull_request:
# The branches below must be a subset of the branches above
branches: [main]
jobs:
benchmark:
name: Performance regression check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: 1.17.x
# Run benchmark with `go test -bench` and stores the output to a file
- name: Run benchmark
run: make BENCH_OUTPUT=ci-cd run-bench
# Download previous benchmark result from cache (if exists)
- name: Download previous benchmark data
uses: actions/cache@v1
with:
path: ./cache
key: ${{ runner.os }}-benchmark
# Run `github-action-benchmark` action
- name: Store benchmark result
uses: benchmark-action/github-action-benchmark@v1
with:
# What benchmark tool the output.txt came from
tool: 'customBiggerIsBetter'
# Where the output from the benchmark tool is stored
output-file-path: ci-cd.json
# Where the previous data file is stored
external-data-json-path: ./cache/benchmark-data.json
# Workflow will fail when an alert happens
fail-on-alert: true
# Upload the updated cache file for the next job by actions/cache

View file

@ -12,6 +12,7 @@ GOLINTER := $(TOOLSDIR)/bin/golangci-lint
NOTATION := $(TOOLSDIR)/bin/notation
OS ?= linux
ARCH ?= amd64
BENCH_OUTPUT ?= stdout
.PHONY: all
all: swagger binary binary-minimal binary-debug binary-arch binary-arch-minimal cli cli-arch bench bench-arch exporter-minimal verify-config test test-clean check
@ -64,6 +65,13 @@ test: check-skopeo $(NOTATION)
go test -tags extended,containers_image_openpgp -v -trimpath -race -timeout 15m -cover -coverpkg ./... -coverprofile=coverage-extended.txt -covermode=atomic ./...
go test -tags minimal,containers_image_openpgp -v -trimpath -race -cover -coverpkg ./... -coverprofile=coverage-minimal.txt -covermode=atomic ./...
.PHONY: run-bench
run-bench: binary bench
bin/zot serve examples/config-minimal.json &
sleep 5
bin/zb -c 10 -n 100 -o $(BENCH_OUTPUT) http://localhost:8080
killall zot
.PHONY: test-clean
test-clean:
$(shell sudo rm -rf /etc/containers/certs.d/127.0.0.1:8089/)

View file

@ -13,7 +13,7 @@ import (
func NewPerfRootCmd() *cobra.Command {
showVersion := false
var auth, workdir, repo, output string
var auth, workdir, repo, outFmt string
var concurrency, requests int
@ -45,7 +45,7 @@ func NewPerfRootCmd() *cobra.Command {
requests = concurrency * (requests / concurrency)
Perf(workdir, url, auth, repo, concurrency, requests)
Perf(workdir, url, auth, repo, concurrency, requests, outFmt)
},
}
@ -59,8 +59,8 @@ func NewPerfRootCmd() *cobra.Command {
"Number of multiple requests to make at a time")
rootCmd.Flags().IntVarP(&requests, "requests", "n", 1,
"Number of requests to perform")
rootCmd.Flags().StringVarP(&output, "output-format", "o", "",
"Output format of test results [default: stdout]")
rootCmd.Flags().StringVarP(&outFmt, "output-format", "o", "",
"Output format of test results: stdout (default), json, ci-cd")
// "version"
rootCmd.Flags().BoolVarP(&showVersion, "version", "v", false, "show the version and exit")

View file

@ -4,6 +4,7 @@ import (
"crypto/rand"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
@ -33,6 +34,7 @@ const (
smallBlob = 1 * MiB
mediumBlob = 10 * MiB
largeBlob = 100 * MiB
cicdFmt = "ci-cd"
)
// helper routines
@ -198,7 +200,17 @@ func updateStats(summary *statsSummary, record statsRecord) {
summary.latencies = append(summary.latencies, record.latency)
}
func printStats(requests int, summary *statsSummary) {
type cicdTestSummary struct {
Name string `json:"name"`
Unit string `json:"unit"`
Value interface{} `json:"value"`
Range string `json:"range,omitempty"`
}
//nolint:gochecknoglobals // used only in this test
var cicdSummary = []cicdTestSummary{}
func printStats(requests int, summary *statsSummary, outFmt string) {
log.Printf("============\n")
log.Printf("Test name:\t%s", summary.name)
log.Printf("Time taken for tests:\t%v", summary.total)
@ -219,6 +231,18 @@ func printStats(requests int, summary *statsSummary) {
log.Printf("%s:\t%v", "p90", summary.latencies[requests*9/10])
log.Printf("%s:\t%v", "p99", summary.latencies[requests*99/100])
log.Printf("\n")
// ci/cd
if outFmt == cicdFmt {
cicdSummary = append(cicdSummary,
cicdTestSummary{
Name: summary.name,
Unit: "requests per sec",
Value: summary.rps,
Range: "3",
},
)
}
}
// test suites/funcs.
@ -644,7 +668,7 @@ var testSuite = []testConfig{ // nolint:gochecknoglobals // used only in this te
},
}
func Perf(workdir, url, auth, repo string, concurrency int, requests int) {
func Perf(workdir, url, auth, repo string, concurrency int, requests int, outFmt string) {
// logging
log.SetFlags(0)
log.SetOutput(tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.TabIndent))
@ -691,6 +715,17 @@ func Perf(workdir, url, auth, repo string, concurrency int, requests int) {
sort.Sort(Durations(summary.latencies))
printStats(requests, &summary)
printStats(requests, &summary, outFmt)
}
if outFmt == cicdFmt {
jsonOut, err := json.Marshal(cicdSummary)
if err != nil {
log.Fatal(err) //nolint:gocritic // file closed on exit
}
if err := ioutil.WriteFile(fmt.Sprintf("%s.json", outFmt), jsonOut, defaultFilePerms); err != nil {
log.Fatal(err)
}
}
}