From 2385e76ed542b8330f648fc64263a3579a5baffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Ma=C5=82ek?= Date: Sun, 11 Jun 2023 14:13:19 +0200 Subject: [PATCH] initial commit --- .github/workflows/main.yaml | 52 +++++++++++++++++++++++++ .github/workflows/prs.yaml | 78 +++++++++++++++++++++++++++++++++++++ Makefile | 9 +++++ README.md | 7 ++++ fib.go | 30 ++++++++++++-- fib_test.go | 10 ++++- go.sum | 0 7 files changed, 181 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/main.yaml create mode 100644 .github/workflows/prs.yaml create mode 100644 Makefile create mode 100644 README.md create mode 100644 go.sum diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml new file mode 100644 index 0000000..025b845 --- /dev/null +++ b/.github/workflows/main.yaml @@ -0,0 +1,52 @@ +name: Main +on: + push: + branches: + - main + +permissions: + contents: read + +jobs: + go-bench: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v3.5.2 + + - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + with: + go-version-file: './go.mod' + cache-dependency-path: './go.sum' + check-latest: true + + - name: Run benchmark + run: | + set -o pipefail + make bench | tee bench_output.txt + + - name: Get JSON for benchmark + uses: benchmark-action/github-action-benchmark@70405016b032d44f409e4b1b451c40215cbe2393 # v1.18.0 + with: + # What benchmark tool the output.txt came from + tool: 'go' + # Where the output from the benchmark tool is stored + output-file-path: bench_output.txt + # Updates the file content instead of generating a Git commit in GitHub Pages branch + external-data-json-path: ./cache/benchmark-data.json + # Workflow will fail when an alert happens + fail-on-alert: true + github-token: ${{ secrets.GITHUB_TOKEN }} + comment-on-alert: true + + - name: Get CPU information + uses: kenchan0130/actions-system-info@master + id: system-info + + - name: Save benchmark JSON + uses: actions/cache/save@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + with: + path: ./cache/benchmark-data.json + # Save with commit hash to avoid "cache already exists" + # Save with OS & CPU info to prevent comparing against results from different CPUs + key: ${{ github.sha }}-${{ runner.os }}-${{ steps.system-info.outputs.cpu-model }}-go-benchmark \ No newline at end of file diff --git a/.github/workflows/prs.yaml b/.github/workflows/prs.yaml new file mode 100644 index 0000000..f4f1072 --- /dev/null +++ b/.github/workflows/prs.yaml @@ -0,0 +1,78 @@ +name: Pull Request +on: + pull_request: + branches: + - main + +permissions: + contents: read + +jobs: + go-bench: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v3.5.2 + with: + fetch-depth: 0 + + - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + with: + go-version-file: './go.mod' + cache-dependency-path: './go.sum' + check-latest: true + + - name: Run benchmark on PR + run: | + set -o pipefail + make bench | tee ${{ github.sha }}_bench_output.txt + + - name: Get CPU information + uses: kenchan0130/actions-system-info@master + id: system-info + + - name: Get Main branch SHA + id: get-main-branch-sha + run: | + SHA=$(git rev-parse origin/main) + echo "sha=$SHA" >> $GITHUB_OUTPUT + + - name: Download benchmark from Main + uses: actions/cache/restore@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + id: cache + with: + path: ./cache/benchmark-data.json + key: ${{ steps.get-main-branch-sha.outputs.sha }}-${{ runner.os }}-${{ steps.system-info.outputs.cpu-model }}-go-benchmark + + - name: Compare benchmarks with Main + uses: benchmark-action/github-action-benchmark@v1 + if: steps.cache.outputs.cache-hit == 'true' + with: + alert-threshold: "200%" + # What benchmark tool the output.txt came from + tool: 'go' + # Where the output from the benchmark tool is stored + output-file-path: ${{ github.sha }}_bench_output.txt + # Where the benchmarks in master are (to compare) + external-data-json-path: ./cache/benchmark-data.json + # Do not save the data + save-data-file: false + # Workflow will fail when an alert happens + fail-on-alert: true + github-token: ${{ secrets.GITHUB_TOKEN }} + # Enable Job Summary for PRs + summary-always: true + + - name: Run benchmarks but don't compare to Main branch + uses: benchmark-action/github-action-benchmark@v1 + if: steps.cache.outputs.cache-hit != 'true' + with: + # What benchmark tool the output.txt came from + tool: 'go' + # Where the output from the benchmark tool is stored + output-file-path: ${{ github.sha }}_bench_output.txt + # Write benchmarks to this file, do not publish to GitHub Pages + save-data-file: false + external-data-json-path: ./cache/benchmark-data.json + # Enable Job Summary for PRs + summary-always: true \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..70f5fc7 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +.DEFAULT_GOAL := help + +.PHONY: help +help: + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +.PHONY: bench +bench: ## Run benchmark test. See https://pkg.go.dev/cmd/go#hdr-Testing_flags + go test ./... -bench . -benchtime 5s -timeout 0 -run=XXX -cpu 1 -benchmem \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8d7115e --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +## Running benchmarks reliably with GitHub action + +This repo shows you can: + +1. run benchmarks for your Go code in the `main` branch and in PRs +2. compare PR benchmarks against `main` benchmarks +3. if no `main` benchmarks are available, just publish benchmarks in the summary of the PR \ No newline at end of file diff --git a/fib.go b/fib.go index 21a3676..80d04a7 100644 --- a/fib.go +++ b/fib.go @@ -1,8 +1,32 @@ package fib -func Fib(u uint) uint { - if u <= 1 { +import ( + "math/rand" + "sync" + "time" +) + +var _m sync.Map + +// Fib returns nth Fibonnaci sequence number. +func Fib(n uint) uint { + if n <= 1 { return 1 } - return Fib(u-2) + Fib(u-1) + + n2, ok := _m.Load(n - 2) + if !ok { + n2 = Fib(n - 2) + _m.Store(n-2, n2) + } + n1, ok := _m.Load(n - 1) + if !ok { + n1 = Fib(n - 1) + _m.Store(n-1, n1) + } + + dur := 500*time.Microsecond + time.Duration(rand.Intn(500))*time.Microsecond + time.Sleep(dur) + + return n2.(uint) + n1.(uint) } diff --git a/fib_test.go b/fib_test.go index 87bd05c..0cede38 100644 --- a/fib_test.go +++ b/fib_test.go @@ -6,12 +6,18 @@ import ( func BenchmarkFib10(b *testing.B) { for i := 0; i < b.N; i++ { - _ = Fib(10) + _ = Fib(1) } } func BenchmarkFib20(b *testing.B) { for i := 0; i < b.N; i++ { - _ = Fib(20) + _ = Fib(1) + } +} + +func BenchmarkFib25(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = Fib(1) } } diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e69de29