Skip to content

Commit b610b65

Browse files
committed
utube: fix slow take on busy utubes
If some of the utube for tasks at the top of the queue were busy most of the time, `take` would slow down for every other task. This problem is fixed by creating a new space `space_ready_buffer`. It contains first task with `READY` status from each utube. This solution shows great results for the stated problem, with the cost of slowing the `put` method. Thus, this workaround is disabled by default. To enable it, user should set the `storage_mode = queue.driver.utube.STORAGE_MODE_READY_BUFFER` as an option while creating the tube. As example: ```lua local test_queue = queue.create_tube('test_queue', 'utube', {temporary = true, storage_mode = queue.driver.utube.STORAGE_MODE_READY_BUFFER}) ``` Part of #228
1 parent aa7c092 commit b610b65

File tree

7 files changed

+630
-125
lines changed

7 files changed

+630
-125
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77

88
## [Unreleased]
99

10+
### Added
11+
- `storage_mode` option for creating a `utube` tube (#228). It enables the
12+
workaround for slow takes while working with busy tubes.
13+
1014
### Fixed
1115

1216
- Stuck in `INIT` state if an instance failed to enter the `running` mode
1317
in time (#226). This fix works only for Tarantool versions >= 2.10.0.
18+
- Slow takes on busy `utube` tubes (#228). The workaround could be enabled by
19+
passing the `storage_mode = "ready_buffer"` option while creating
20+
the tube.
1421

1522
## [1.3.3] - 2023-09-13
1623

README.md

+36
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,49 @@ The main idea of this queue backend is the same as in a `fifo` queue:
165165
the tasks are executed in FIFO order.
166166
However, tasks may be grouped into sub-queues.
167167

168+
It is advised not to use `utube` methods inside transactions with
169+
`read-confirmed` isolation level. It can lead to errors when trying to make
170+
parallel tube methods calls with mvcc enabled.
171+
168172
The following options can be specified when creating a `utube` queue:
169173
* `temporary` - boolean - if true, the contents of the queue do not persist
170174
on disk
171175
* `if_not_exists` - boolean - if true, no error will be returned if the tube
172176
already exists
173177
* `on_task_change` - function name - a callback to be executed on every
174178
operation
179+
* `storage_mode` - string - one of
180+
* `queue.driver.utube.STORAGE_MODE_DEFAULT` ("default") - default
181+
implementation of `utube`
182+
* `queue.driver.utube.STORAGE_MODE_READY_BUFFER`
183+
("ready_buffer") - allows processing `take` requests faster, but
184+
by the cost of `put` operations speed. Right now this option is supported
185+
only for `memtx` engine.
186+
WARNING: this is an experimental storage mode.
187+
188+
Here is a benchmark comparison of these two modes:
189+
* Benchmark for simple `put` and `take` methods. 30k utubes are created
190+
with a single task each. Task creation time is calculated. After that
191+
30k consumers are calling `take` + `ack`, each in the separate fiber.
192+
Time to ack all tasks is calculated. The results are as follows:
193+
194+
| | put (30k) | take+ack |
195+
|---------|-----------|----------|
196+
| default | 180ms | 1.6s |
197+
| ready | 270ms | 1.7s |
198+
* Benchmark for the busy utubes. 10 tubes are created.
199+
Each contains 1000 tasks. After that, 10 consumers are created (each works
200+
on his tube only, one tube — one consumer). Each consumer will
201+
`take`, then `yield` and then `ack` every task from their utube
202+
(1000 tasks each).
203+
After that, we can also run this benchmark with 10k tasks on each utube,
204+
100k tasks and 150k tasks. But all that with 10 utubes and 10 consumers.
205+
The results are as follows:
206+
207+
| | 1k | 10k | 50k | 150k |
208+
|---------|-------|------|------|-------|
209+
| default | 53s | 1.5h | 100h | 1000h |
210+
| ready | 450ms | 4.7s | 26s | 72s |
175211

176212
The following options can be specified when putting a task in a `utube`
177213
queue:

queue/abstract.lua

+6-3
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,12 @@ function tube.drop(self)
295295
error("There are taken tasks in the tube")
296296
end
297297

298-
local space_name = tube[3]
299-
300-
box.space[space_name]:drop()
298+
if self.raw.drop ~= nil then
299+
self.raw:drop()
300+
else
301+
local space_name = tube[3]
302+
box.space[space_name]:drop()
303+
end
301304
box.space._queue:delete{tube_name}
302305
-- drop queue
303306
queue.tube[tube_name] = nil

0 commit comments

Comments
 (0)