Skip to content

Commit 06b96ce

Browse files
Run performance test for metrics
Before this patch, performance tests ran together with unit and integration with `--coverage` flag. Coverage analysis cropped the result of performance tests to 10-15 times. For metrics integration it resulted in timeout errors and drop of performance which is not reproduces with coverage disabled. Moreover, before this patch log capture was disabled and performance tests did not displayed any results after run. After this patch, `make -C build coverage` will run lightweight version of performance test. `make -C build performance` will run real performance tests. This path also adds new cases to performance test to compare module performance with or without statistics, statistic wrappers and compare different metrics drivers. Closes #233, follows up #224
1 parent a1d4238 commit 06b96ce

File tree

4 files changed

+189
-64
lines changed

4 files changed

+189
-64
lines changed

.github/workflows/test_on_push.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ jobs:
1616
tarantool-version: ["1.10.6", "1.10", "2.2", "2.3", "2.4", "2.5", "2.6", "2.7", "2.8"]
1717
metrics-version: [""]
1818
remove-merger: [false]
19+
perf-test: [false]
1920
include:
21+
- tarantool-version: "1.10"
22+
metrics-version: "0.12.0"
23+
perf-test: true
2024
- tarantool-version: "2.7"
2125
remove-merger: true
2226
- tarantool-version: "2.8"
@@ -26,6 +30,7 @@ jobs:
2630
- tarantool-version: "2.8"
2731
coveralls: true
2832
metrics-version: "0.12.0"
33+
perf-test: true
2934
fail-fast: false
3035
runs-on: [ubuntu-latest]
3136
steps:
@@ -72,6 +77,10 @@ jobs:
7277
- name: Run tests and code coverage analysis
7378
run: make -C build coverage
7479

80+
- name: Run performance tests
81+
run: make -C build performance
82+
if: ${{ matrix.perf-test }}
83+
7584
- name: Send code coverage to coveralls.io
7685
run: make -C build coveralls
7786
if: ${{ matrix.coveralls }}

CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ add_custom_target(luatest
3636
COMMENT "Run regression tests"
3737
)
3838

39+
set(PERFORMANCE_TESTS_SUBDIR "test/performance")
40+
41+
add_custom_target(performance
42+
COMMAND PERF_MODE_ON=true ${LUATEST} -v -c ${PERFORMANCE_TESTS_SUBDIR}
43+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
44+
COMMENT "Run performance tests"
45+
)
46+
3947
add_custom_target(coverage
4048
COMMAND ${LUACOV} ${PROJECT_SOURCE_DIR} && grep -A999 '^Summary' ${CODE_COVERAGE_REPORT}
4149
DEPENDS ${CODE_COVERAGE_STATS}

crud/stats/metrics_registry.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ local metric_name = {
2828

2929
local LATENCY_QUANTILE = 0.99
3030

31+
-- Increasing tolerance threshold affects performance.
3132
local DEFAULT_QUANTILES = {
3233
[LATENCY_QUANTILE] = 1e-3,
3334
}

test/performance/select_perf_test.lua

Lines changed: 171 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ local g = t.group('perf')
99

1010
local helpers = require('test.helper')
1111

12-
g.before_all = function()
12+
g.before_all(function(g)
1313
g.cluster = helpers.Cluster:new({
1414
datadir = fio.tempdir(),
1515
server_command = helpers.entrypoint('srv_select'),
@@ -53,21 +53,32 @@ g.before_all = function()
5353
},
5454
})
5555
g.cluster:start()
56-
end
5756

58-
g.after_all = function()
57+
g.router = g.cluster:server('router').net_box
58+
59+
helpers.prepare_simple_functions(g.router)
60+
g.router:eval(" crud = require('crud') ")
61+
62+
-- Run real perf tests only with flag, otherwise run short version
63+
-- to test compatibility as part of unit/integration test run.
64+
g.perf_mode_on = os.getenv('PERF_MODE_ON')
65+
end)
66+
67+
g.before_each(function(g)
68+
helpers.truncate_space_on_cluster(g.cluster, 'customers')
69+
end)
70+
71+
g.after_all(function(g)
5972
g.cluster:stop()
6073
fio.rmtree(g.cluster.datadir)
61-
end
62-
63-
g.before_each(function() end)
74+
end)
6475

65-
local function insert_customers(conn, id, count, timeout, report)
76+
local function insert_customers(conn, id, count, timeout, report, call_func)
6677
local customer = {id, box.NULL, 'David', 'Smith', 33, 'Los Angeles'}
6778
local start = fiber.clock()
6879

6980
while (fiber.clock() - start) < timeout do
70-
local ok, res, err = pcall(conn.call, conn, [[package.loaded.crud.insert]], {'customers', customer})
81+
local ok, res, err = pcall(conn.call, conn, call_func, {'customers', customer})
7182
if not ok then
7283
log.error('Insert error: %s', res)
7384
table.insert(report.errors, res)
@@ -82,11 +93,123 @@ local function insert_customers(conn, id, count, timeout, report)
8293
end
8394
end
8495

85-
local function select_customers(conn, id, timeout, report)
96+
local insert_cases = {
97+
without_stats_wrapper = {
98+
prepare = function(g)
99+
g.router:eval("plain_insert = require('crud.insert').tuple")
100+
end,
101+
call = "plain_insert",
102+
},
103+
with_stats_disabled = {
104+
prepare = function(g)
105+
g.cluster:server('router').net_box:call("package.loaded.crud.disable_stats")
106+
end,
107+
call = "package.loaded.crud.insert",
108+
},
109+
with_local_stats = {
110+
prepare = function(g)
111+
g.cluster:server('router').net_box:call("package.loaded.crud.enable_stats", {{ driver = 'local' }})
112+
end,
113+
call = "package.loaded.crud.insert",
114+
},
115+
with_metrics_stats = {
116+
prepare = function(g)
117+
local router = g.cluster:server('router').net_box
118+
local is_metrics_supported = router:eval([[
119+
return require('crud.stats.metrics_registry').is_supported()
120+
]])
121+
t.skip_if(is_metrics_supported == false, 'Metrics registry is unsupported')
122+
router:call("package.loaded.crud.enable_stats", {{ driver = 'metrics' }})
123+
end,
124+
call = "package.loaded.crud.insert",
125+
},
126+
}
127+
128+
for name, case in pairs(insert_cases) do
129+
local test_name = ('test_insert_%s'):format(name)
130+
131+
if case.prepare ~= nil then
132+
g.before_test(test_name, case.prepare)
133+
end
134+
135+
g[test_name] = function(g)
136+
local timeout, fiber_count, connection_count
137+
if g.perf_mode_on then
138+
timeout = 30
139+
fiber_count = 600
140+
connection_count = 10
141+
else
142+
timeout = 2
143+
fiber_count = 10
144+
connection_count = 2
145+
end
146+
147+
local connections = {}
148+
149+
local server = g.cluster.main_server
150+
for _ = 1, connection_count do
151+
local c = net_box:connect(server.net_box_uri, server.net_box_credentials)
152+
assert(c)
153+
table.insert(connections, c)
154+
end
155+
156+
local fibers = {}
157+
local report = {errors = {}, count = 0}
158+
for id = 1, fiber_count do
159+
local conn_id = id % connection_count + 1
160+
local conn = connections[conn_id]
161+
local f = fiber.new(insert_customers, conn, id, fiber_count, timeout, report, case.call)
162+
f:set_joinable(true)
163+
table.insert(fibers, f)
164+
end
165+
166+
for i = 1, fiber_count do
167+
fibers[i]:join()
168+
end
169+
170+
log.error('\n%s: requests %d, rps %d, errors %d',
171+
test_name, report.count, report.count / timeout, #report.errors)
172+
end
173+
end
174+
175+
176+
local select_cases = {
177+
without_stats_wrapper = {
178+
prepare = function(g)
179+
g.router:eval("plain_select = require('crud.select').call")
180+
end,
181+
call = "plain_select",
182+
},
183+
with_stats_disabled = {
184+
prepare = function(g)
185+
g.router:call("package.loaded.crud.disable_stats")
186+
end,
187+
call = "package.loaded.crud.select",
188+
},
189+
with_local_stats = {
190+
prepare = function(g)
191+
g.router:call("package.loaded.crud.enable_stats", {{ driver = 'local' }})
192+
end,
193+
call = "package.loaded.crud.select",
194+
},
195+
with_metrics_stats = {
196+
prepare = function(g)
197+
local router = g.cluster:server('router').net_box
198+
local is_metrics_supported = router:eval([[
199+
return require('crud.stats.metrics_registry').is_supported()
200+
]])
201+
t.skip_if(is_metrics_supported == false, 'Metrics registry is unsupported')
202+
router:call("package.loaded.crud.enable_stats", {{ driver = 'metrics' }})
203+
end,
204+
call = "package.loaded.crud.select",
205+
},
206+
}
207+
208+
local function select_customers(conn, id, timeout, report, call_func)
86209
local start = fiber.clock()
87210
local ok, err = pcall(function()
88211
while (fiber.clock() - start) < timeout do
89-
local _, err = conn:call([[package.loaded.crud.select]], {'customers', {{'>', 'id', id}}, {first = 10}})
212+
local _, err = conn:call(call_func, {'customers', {{'>', 'id', id}}, {first = 10}})
90213
if err ~= nil then
91214
errors.wrap(err)
92215
log.error(err)
@@ -102,66 +225,50 @@ local function select_customers(conn, id, timeout, report)
102225
end
103226
end
104227

105-
g.test_insert = function()
106-
local timeout = 30
107-
local fiber_count = 600
108-
local connection_count = 10
109-
local connections = {}
110-
111-
local server = g.cluster.main_server
112-
server.net_box:eval([[require('crud')]])
113-
for _ = 1, connection_count do
114-
local c = net_box:connect(server.net_box_uri, server.net_box_credentials)
115-
assert(c)
116-
table.insert(connections, c)
117-
end
228+
for name, case in pairs(select_cases) do
229+
local test_name = ('test_select_%s'):format(name)
118230

119-
local fibers = {}
120-
local report = {errors = {}, count = 0}
121-
for id = 1, fiber_count do
122-
local conn_id = id % connection_count + 1
123-
local conn = connections[conn_id]
124-
local f = fiber.new(insert_customers, conn, id, fiber_count, timeout, report)
125-
f:set_joinable(true)
126-
table.insert(fibers, f)
231+
if case.prepare ~= nil then
232+
g.before_test(test_name, case.prepare)
127233
end
128234

129-
for i = 1, fiber_count do
130-
fibers[i]:join()
131-
end
235+
g[test_name] = function(g)
236+
local timeout, fiber_count, connection_count
237+
if g.perf_mode_on then
238+
timeout = 30
239+
fiber_count = 200
240+
connection_count = 10
241+
else
242+
timeout = 2
243+
fiber_count = 5
244+
connection_count = 2
245+
end
132246

133-
log.error('\nINSERT: requests %d, rps %d, errors %d',
134-
report.count, report.count / timeout, #report.errors)
135-
end
247+
local connections = {}
136248

137-
g.test_select = function()
138-
local timeout = 30
139-
local fiber_count = 200
140-
local connection_count = 10
141-
local connections = {}
142-
143-
local server = g.cluster.main_server
144-
server.net_box:eval([[require('crud')]])
145-
for _ = 1, connection_count do
146-
local c = net_box:connect(server.net_box_uri, server.net_box_credentials)
147-
assert(c)
148-
table.insert(connections, c)
149-
end
249+
local server = g.cluster.main_server
150250

151-
local fibers = {}
152-
local report = {errors = {}, count = 0}
153-
for id = 1, fiber_count do
154-
local conn_id = id % connection_count + 1
155-
local conn = connections[conn_id]
156-
local f = fiber.new(select_customers, conn, id, timeout, report)
157-
f:set_joinable(true)
158-
table.insert(fibers, f)
159-
end
251+
for _ = 1, connection_count do
252+
local c = net_box:connect(server.net_box_uri, server.net_box_credentials)
253+
assert(c)
254+
table.insert(connections, c)
255+
end
160256

161-
for i = 1, fiber_count do
162-
fibers[i]:join()
163-
end
257+
local fibers = {}
258+
local report = {errors = {}, count = 0}
259+
for id = 1, fiber_count do
260+
local conn_id = id % connection_count + 1
261+
local conn = connections[conn_id]
262+
local f = fiber.new(select_customers, conn, id, timeout, report, case.call)
263+
f:set_joinable(true)
264+
table.insert(fibers, f)
265+
end
266+
267+
for i = 1, fiber_count do
268+
fibers[i]:join()
269+
end
164270

165-
log.error('\nSELECT: requests %d, rps %d, errors %d',
166-
report.count, report.count / timeout, #report.errors)
271+
log.error('\n%s: requests %d, rps %d, errors %d',
272+
test_name, report.count, report.count / timeout, #report.errors)
273+
end
167274
end

0 commit comments

Comments
 (0)