Skip to content

Commit eb6bee8

Browse files
committed
test: add benchmark tests
Added benchmarks of large Select and Replace. Added a new target in Makefile for running benchmark tests. Added a new space in config.lua for large Select tests. Added a new target in Makefile for measuring performance degradation between current changes and master. Added a new line in gitignore for ignoring artifacts from bench target. Added a new step for running benchmark tests in ci. Added description to the CONTRIBUTING.md for how to run benchmark tests. Closes #122
1 parent 1606275 commit eb6bee8

File tree

6 files changed

+154
-0
lines changed

6 files changed

+154
-0
lines changed

.github/workflows/testing.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,6 @@ jobs:
6363
COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6464
run: |
6565
make coveralls
66+
67+
- name: Check workability of benchmark tests
68+
run: make bench-deps bench DURATION=1x COUNT=1

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
.idea/
44
work_dir*
55
.rocks
6+
bench

CONTRIBUTING.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,42 @@ For example, for running tests in `multi`, `uuid` and `main` packages, call
3838
make test-multi test-uuid test-main
3939
```
4040

41+
Before running benchmark or measuring performance degradation, install benchmark dependencies:
42+
```bash
43+
make bench-deps BENCH_PATH=custom_path
44+
```
45+
46+
Use the variable `BENCH_PATH` to specialize the path of benchmark artifacts.
47+
It is set to `bench` by default.
48+
49+
To run benchmark tests, call:
50+
```bash
51+
make bench DURATION=5s COUNT=7 BENCH_PATH=custom_path TEST_PATH=.
52+
```
53+
54+
Use the variable `DURATION` to set the duration of perf tests. That variable is mapped on
55+
testing [flag](https://pkg.go.dev/cmd/go#hdr-Testing_flags) `-benchtime` for gotest.
56+
It may take the values in seconds (e.g, `5s`) or count of iterations (e.g, `1000x`).
57+
It is set to `3s` by default.
58+
59+
Use the variable `COUNT` to control the count of benchmark runs for each test. It is set to `5` by default.
60+
That variable is mapped on testing flag `-count`.
61+
Use higher values if the benchmark numbers aren't stable.
62+
63+
Use the variable `TEST_PATH` to set the directory of test files.
64+
It is set to `./...` by default, so it runs all the Benchmark tests in project.
65+
66+
Before calculating performance difference between master and the current branch,
67+
prepare benchmark results of master:
68+
```bash
69+
make perf-reference DURATION=5s COUNT=7 BENCH_PATH=custom_path TEST_PATH=.
70+
```
71+
72+
To measure performance degradation after changes in code, run:
73+
```bash
74+
make bench perf-reference perf-diff BENCH_PATH=custom_path
75+
```
76+
4177
## Code review checklist
4278

4379
- Public API contains functions, variables, constants that are needed from

Makefile

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
SHELL := /bin/bash
22
COVERAGE_FILE := coverage.out
3+
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
4+
PROJECT_DIR := $(patsubst %/,%,$(dir $(MAKEFILE_PATH)))
5+
DURATION ?= 3s
6+
COUNT ?= 5
7+
BENCH_PATH ?= ${PROJECT_DIR}/bench
8+
TEST_PATH ?= ${PROJECT_DIR}/...
9+
BENCH_FILE := ${BENCH_PATH}/bench.txt
10+
REFERENCE_FILE := ${BENCH_PATH}/reference.txt
311

412
.PHONY: clean
513
clean:
@@ -55,3 +63,32 @@ coverage:
5563
coveralls: coverage
5664
go get github.com/mattn/goveralls
5765
goveralls -coverprofile=$(COVERAGE_FILE) -service=github
66+
67+
.PHONY: bench-deps
68+
bench-deps:
69+
@echo "Installing benchstat tool"
70+
rm -rf ${BENCH_PATH}
71+
mkdir ${BENCH_PATH}
72+
go clean -testcache
73+
cd ${BENCH_PATH} && git clone https://go.googlesource.com/perf && cd perf && go install ./cmd/benchstat
74+
rm -rf ${BENCH_PATH}/perf
75+
76+
.PHONY: bench
77+
bench:
78+
@echo "Running benchmark tests in the current branch"
79+
go test ${TEST_PATH} -bench=. -run=^Benchmark -benchmem -benchtime=${DURATION} -count=${COUNT} 2>&1 \
80+
| tee ${BENCH_FILE}
81+
benchstat ${BENCH_FILE}
82+
83+
.PHONY: bench-reference
84+
bench-reference:
85+
@echo "Running benchmark tests in master for using results in bench-diff target"
86+
cd ${BENCH_PATH} && git clone https://github.com/tarantool/go-tarantool.git
87+
cd ${BENCH_PATH}/go-tarantool && go test ${BENCH_PATH}/go-tarantool/... -bench=. -run=^Benchmark -benchmem \
88+
-benchtime=${DURATION} -count=${COUNT} 2>&1 | tee ${REFERENCE_FILE}
89+
rm -rf ${BENCH_PATH}/go-tarantool
90+
91+
.PHONY: bench-diff
92+
bench-diff:
93+
@echo "Comparing performance between master and current branch"
94+
benchstat ${REFERENCE_FILE} ${BENCH_FILE}

config.lua

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,31 @@ box.once("init", function()
4040
})
4141
st:truncate()
4242

43+
local s2 = box.schema.space.create('test_perf', {
44+
id = 520,
45+
temporary = true,
46+
if_not_exists = true,
47+
field_count = 3,
48+
format = {
49+
{name = "id", type = "unsigned"},
50+
{name = "name", type = "string"},
51+
{name = "arr1", type = "array"},
52+
},
53+
})
54+
s2:create_index('primary', {type = 'tree', unique = true, parts = {1, 'unsigned'}, if_not_exists = true})
55+
s2:create_index('secondary', {id = 5, type = 'tree', unique = false, parts = {2, 'string'}, if_not_exists = true})
56+
local arr_data = {}
57+
for i = 1,100 do
58+
arr_data[i] = i
59+
end
60+
for i = 1,1000 do
61+
s2:insert{
62+
i,
63+
'test_name',
64+
arr_data,
65+
}
66+
end
67+
4368
--box.schema.user.grant('guest', 'read,write,execute', 'universe')
4469
box.schema.func.create('box.info')
4570
box.schema.func.create('simple_incr')
@@ -49,6 +74,7 @@ box.once("init", function()
4974
box.schema.user.grant('test', 'execute', 'universe')
5075
box.schema.user.grant('test', 'read,write', 'space', 'test')
5176
box.schema.user.grant('test', 'read,write', 'space', 'schematest')
77+
box.schema.user.grant('test', 'read,write', 'space', 'test_perf')
5278
end)
5379

5480
local function func_name()

tarantool_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,57 @@ func BenchmarkClientParallelMassiveUntyped(b *testing.B) {
362362
close(limit)
363363
}
364364

365+
func BenchmarkConnection_Replace(b *testing.B) {
366+
conn, err := Connect(server, opts)
367+
if err != nil {
368+
b.Errorf("No connection available")
369+
return
370+
}
371+
defer conn.Close()
372+
spaceNo = 520
373+
374+
rSpaceNo, _, err := conn.Schema.ResolveSpaceIndex("test_perf", "secondary")
375+
if err != nil {
376+
b.Fatalf("Space is not resolved: %s", err.Error())
377+
}
378+
379+
b.ResetTimer()
380+
b.RunParallel(func(pb *testing.PB) {
381+
for pb.Next() {
382+
_, err := conn.Replace(rSpaceNo, []interface{}{uint(1), "hello", []interface{}{}})
383+
if err != nil {
384+
b.Error(err)
385+
}
386+
}
387+
})
388+
}
389+
390+
func BenchmarkConnection_LargeSelect(b *testing.B) {
391+
conn, err := Connect(server, opts)
392+
if err != nil {
393+
b.Errorf("No connection available")
394+
return
395+
}
396+
defer conn.Close()
397+
398+
schema := conn.Schema
399+
rSpaceNo, rIndexNo, err := schema.ResolveSpaceIndex("test_perf", "secondary")
400+
if err != nil {
401+
b.Fatalf("symbolic space and index params not resolved")
402+
}
403+
404+
offset, limit := uint32(0), uint32(1000)
405+
b.ResetTimer()
406+
b.RunParallel(func(pb *testing.PB) {
407+
for pb.Next() {
408+
_, err := conn.Select(rSpaceNo, rIndexNo, offset, limit, IterEq, []interface{}{"test_name"})
409+
if err != nil {
410+
b.Fatal(err)
411+
}
412+
}
413+
})
414+
}
415+
365416
///////////////////
366417

367418
func TestClient(t *testing.T) {

0 commit comments

Comments
 (0)