diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 00000000..bf7515da --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,43 @@ +name: Benchmark + +on: + push: + branches: [main] + pull_request: + branches: [main] + +permissions: + contents: write + deployments: write + +jobs: + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache: true + - uses: actions/setup-node@v4 + with: + node-version-file: web/package.json + cache: "npm" + cache-dependency-path: web/package-lock.json + - run: make web-install gen-client-ts web-build + - run: make test-env-start + - run: make install-deps gen-clean gen-client-go + - run: make bench + - name: Store benchmark result + uses: benchmark-action/github-action-benchmark@v1 + with: + name: Gravity Benchmark + tool: 'go' + output-file-path: test-output + github-token: ${{ secrets.GITHUB_TOKEN }} + auto-push: true + # Show alert with commit comment on detecting possible performance regression + alert-threshold: '200%' + comment-on-alert: true + fail-on-alert: true diff --git a/Makefile b/Makefile index 8741851f..4507cb7c 100644 --- a/Makefile +++ b/Makefile @@ -169,7 +169,7 @@ test: internal/resources/macoui internal/resources/blocky internal/resources/tft export ETCD_ENDPOINT="localhost:2385" export DEBUG="true" export LISTEN_ONLY="true" - go run -v ${PWD} cli etcdctl del --prefix / + export CI="true" go test \ -p 1 \ -coverprofile=coverage.txt \ @@ -179,3 +179,16 @@ test: internal/resources/macoui internal/resources/blocky internal/resources/tft $(shell go list ./... | grep -v ./api) \ 2>&1 | tee test-output go tool cover -html coverage.txt -o coverage.html + +bench: internal/resources/macoui internal/resources/blocky internal/resources/tftp + export BOOTSTRAP_ROLES="dns;dhcp;api;discovery;backup;debug;tsdb;tftp" + export ETCD_ENDPOINT="localhost:2385" + export DEBUG="true" + export LISTEN_ONLY="true" + export CI="true" + go test \ + -benchmem \ + -run=^$$ \ + -bench=^Benchmark \ + $(shell go list ./... | grep -v ./api) \ + 2>&1 | tee test-output diff --git a/pkg/roles/dns/handler_memory_test.go b/pkg/roles/dns/handler_memory_test.go index 511c8ddd..a0f8ddcf 100644 --- a/pkg/roles/dns/handler_memory_test.go +++ b/pkg/roles/dns/handler_memory_test.go @@ -66,6 +66,61 @@ func TestRoleDNS_Memory(t *testing.T) { assert.Equal(t, net.ParseIP("10.1.2.3").String(), ans.(*d.A).A.String()) } +func BenchmarkRoleDNS_Memory(b *testing.B) { + defer tests.Setup(nil)() + rootInst := instance.New() + ctx := tests.Context() + inst := rootInst.ForRole("dns", ctx) + tests.PanicIfError(inst.KV().Put( + ctx, + inst.KV().Key( + types.KeyRole, + types.KeyZones, + ".", + ).String(), + tests.MustJSON(dns.Zone{ + HandlerConfigs: []map[string]interface{}{ + { + "type": "memory", + }, + }, + }), + )) + tests.PanicIfError(inst.KV().Put( + ctx, + inst.KV().Key( + types.KeyRole, + types.KeyZones, + ".", + "foo", + types.DNSRecordTypeA, + "0", + ).String(), + tests.MustJSON(dns.Record{ + Data: "10.1.2.3", + }), + )) + + role := dns.New(inst) + _ = role.Start(ctx, RoleConfig()) + defer role.Stop() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + fw := NewNullDNSWriter() + role.Handler(fw, &d.Msg{ + Question: []d.Question{ + { + Name: "foo.", + Qtype: d.TypeA, + Qclass: d.ClassINET, + }, + }, + }) + _ = fw.Msg() + } +} + func TestRoleDNS_Memory_Wildcard(t *testing.T) { defer tests.Setup(t)() rootInst := instance.New() diff --git a/pkg/tests/utils.go b/pkg/tests/utils.go index 64728117..9029fb01 100644 --- a/pkg/tests/utils.go +++ b/pkg/tests/utils.go @@ -85,7 +85,9 @@ func ResetEtcd(t *testing.T) { "/", clientv3.WithPrefix(), ) - assert.NoError(t, err) + if t != nil { + assert.NoError(t, err) + } } func Setup(t *testing.T) func() {