Skip to content

Commit bb6d935

Browse files
authored
perf: speed up xqueue.upgrade() for large spaces (#22)
* perf: speed up xqueue.upgrade() for large spaces * test: fix flaky test
1 parent bcadffd commit bb6d935

File tree

7 files changed

+115
-22
lines changed

7 files changed

+115
-22
lines changed

.env

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
BENCHER_PROJECT=xqueue
2+
BENCHER_ADAPTER=json
3+
BENCHER_TESTBED=localhost
4+
LUABENCH_USE_BMF=true

.github/workflows/benchmark.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Benchmarking code
2+
3+
on:
4+
- push
5+
6+
jobs:
7+
run-unit-benchmarks:
8+
runs-on: ubuntu-latest
9+
strategy:
10+
matrix:
11+
version: ["2.10.6", "2.11.0", "2.11.2"]
12+
steps:
13+
- uses: actions/checkout@v4
14+
- uses: tarantool/setup-tarantool@v3
15+
with:
16+
tarantool-version: '${{matrix.version}}'
17+
- name: install argparse
18+
run: tarantoolctl rocks install argparse
19+
- name: install luabench
20+
run: tarantoolctl rocks --server=https://moonlibs.org install luabench 0.3.0
21+
- name: run benchmarks
22+
env:
23+
LUABENCH_USE_BMF: false
24+
LUABENCH_TIMEOUT: 60
25+
LUABENCH_DURATION: '10s'
26+
run: |
27+
.rocks/bin/luabench

.luabench

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
jit = 'on'
2+
duration = '10s'

benchmarks/001_put_take_bench.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ xqueue.upgrade(box.space.queue, {
4040

4141
local queue = box.space.queue --[[@as xqueue.space]]
4242
lb.before_all(function() queue:truncate() end)
43-
lb.after_all(function() queue:truncate() box.snapshot() end)
43+
lb.after_all(function() box.space.queue:truncate() box.snapshot() end)
4444

4545
local M = {}
4646

benchmarks/002_initial_stat_bench.lua

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
local lb = require 'luabench'
2+
local fiber = require 'fiber'
3+
local fun = require 'fun'
4+
5+
local M = {}
6+
7+
local STATUS = { 'R', 'T', 'W', 'B', 'Z', 'D' }
8+
9+
lb.before_all(function()
10+
box.cfg{ memtx_memory = 2^30 }
11+
12+
box.schema.space.create('q1', {
13+
if_not_exists = true,
14+
format = {
15+
{ name = 'id', type = 'unsigned' },
16+
{ name = 'status', type = 'string' },
17+
},
18+
})
19+
20+
box.space.q1:create_index('primary', { parts = {'id'}, if_not_exists = true })
21+
box.space.q1:create_index('xq', { parts = {'status', 'id'}, if_not_exists = true })
22+
23+
if fiber.extend_slice then
24+
fiber.extend_slice({ err = 3600, warn = 3600 })
25+
end
26+
27+
box.begin()
28+
local tab = {}
29+
for no = 1, 4e6 do
30+
tab[1], tab[2] = no, STATUS[math.random(#STATUS)]
31+
box.space.q1:replace(tab)
32+
end
33+
box.commit()
34+
end)
35+
36+
lb.after_all(function()
37+
box.space.q1:drop()
38+
box.snapshot()
39+
end)
40+
41+
function M.bench_iterate_all(b)
42+
local limit = b.N
43+
local scanned = 0
44+
local stats = {}
45+
for _, t in box.space.q1:pairs({}, { iterator = "ALL" }) do
46+
stats[t.status] = (stats[t.status] or 0ULL) + 1
47+
scanned = scanned + 1
48+
if limit == scanned then break end
49+
end
50+
b.N = scanned
51+
end
52+
53+
function M.bench_count(b)
54+
local total = 0
55+
for _, s in pairs(STATUS) do
56+
total = total + box.space.q1.index.xq:count(s)
57+
if b.N < total then break end
58+
end
59+
b.N = total
60+
end
61+
62+
return M

test/basic_test.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,10 @@ function g.test_delayed_queue()
178178
t.assert_equals(queue:get({taken.id}).status, 'W', 'queue:release(..., {delay=<>}) must put task in W')
179179
t.assert_le(queue:get({task_put_delay_500ms.id}).runat, queue:get({taken.id}).runat, "first task must wakeup earlier")
180180

181-
local taken_delayed = queue:take({ timeout = 0.13 })
181+
local taken_delayed = queue:take({ timeout = 3 })
182182
t.assert(taken_delayed, 'delayed task must be taken after timeout')
183183

184-
local taken_put = queue:take({ timeout = 0.1 })
184+
local taken_put = queue:take({ timeout = 3 })
185185
t.assert(taken_put, 'released task must be taken after timeout')
186186

187187
t.assert_equals(taken_delayed.id, task_put_delay_500ms.id, "firstly delayed task must be taken")

xqueue.lua

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,15 @@ local function _table2tuple ( qformat )
215215
return dostring(fun)
216216
end
217217

218+
local pretty_st = {
219+
R = "Ready",
220+
T = "Taken",
221+
W = "Waiting",
222+
B = "Buried",
223+
Z = "Zombie",
224+
D = "Done",
225+
}
226+
218227
---@class xqueue.space
219228
local methods = {}
220229

@@ -583,19 +592,17 @@ function M.upgrade(space,opts,depth)
583592
tube = stat_tube;
584593
}
585594
if self.fields.tube then
586-
for _, t in space:pairs(nil, { iterator = box.index.ALL }) do
587-
local s = t[self.fields.status]
588-
self._stat.counts[s] = (self._stat.counts[s] or 0LL) + 1
589-
590-
local tube = t[self.fields.tube]
591-
if stat_tube[tube] then
592-
stat_tube[tube].counts[s] = (stat_tube[tube].counts[s] or 0LL) + 1
595+
for status in pairs(pretty_st) do
596+
self._stat.counts[status] = 0LL+self.index:count(status)
597+
end
598+
for tube in pairs(stat_tube) do
599+
for status in pairs(pretty_st) do
600+
stat_tube[tube].counts[status] = 0LL+self.tube_index:count({ tube, status })
593601
end
594602
end
595603
else
596-
for _, t in space:pairs(nil, { iterator = box.index.ALL }) do
597-
local s = t[self.fields.status]
598-
self._stat.counts[s] = (self._stat.counts[s] or 0LL) + 1
604+
for status in pairs(pretty_st) do
605+
self._stat.counts[status] = 0LL+self.index:count(status)
599606
end
600607
end
601608
else
@@ -1748,15 +1755,6 @@ function methods:truncate()
17481755
return ret
17491756
end
17501757

1751-
local pretty_st = {
1752-
R = "Ready",
1753-
T = "Taken",
1754-
W = "Waiting",
1755-
B = "Buried",
1756-
Z = "Zombie",
1757-
D = "Done",
1758-
}
1759-
17601758
local shortmap = { __serialize = 'map' }
17611759

17621760
---@param pretty? boolean

0 commit comments

Comments
 (0)