-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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`. 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 (it is ~3 times slower). Thus, this workaround is disabled by default. To enable it, user should set the `v2 = true` as an option while creating the tube. As example: ```lua local test_queue = queue.create_tube('test_queue', 'utube', {temporary = true, v2 = true}) ``` Part of #228
- Loading branch information
Showing
4 changed files
with
275 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
#!/usr/bin/env tarantool | ||
|
||
local clock = require('clock') | ||
local os = require('os') | ||
local fiber = require('fiber') | ||
local queue = require('queue') | ||
|
||
-- Set the number of consumers. | ||
local consumers_count = 10 | ||
-- Set the number of tasks processed by one consumer per iteration. | ||
local batch_size = 150000 | ||
|
||
local barrier = fiber.cond() | ||
local wait_count = 0 | ||
|
||
box.cfg() | ||
|
||
local test_queue = queue.create_tube('test_queue', 'utube', | ||
{temporary = true, v2 = true}) | ||
|
||
local function prepare_tasks() | ||
local test_data = 'test data' | ||
|
||
for i = 1, consumers_count do | ||
for _ = 1, batch_size do | ||
test_queue:put(test_data, {utube = tostring(i)}) | ||
end | ||
end | ||
end | ||
|
||
local function prepare_consumers() | ||
local consumers = {} | ||
|
||
-- Make half the utubes busy. | ||
for _ = 1, consumers_count / 2 do | ||
test_queue:take() | ||
end | ||
|
||
for i = 1, consumers_count / 2 do | ||
consumers[i] = fiber.create(function() | ||
wait_count = wait_count + 1 | ||
-- Wait for all consumers to start. | ||
barrier:wait() | ||
|
||
-- Ack the tasks. | ||
for _ = 1, batch_size do | ||
local task = test_queue:take() | ||
test_queue:ack(task[1]) | ||
end | ||
|
||
wait_count = wait_count + 1 | ||
end) | ||
end | ||
|
||
return consumers | ||
end | ||
|
||
local function multi_consumer_bench() | ||
--- Wait for all consumer fibers. | ||
local wait_all = function() | ||
while (wait_count ~= consumers_count / 2) do | ||
fiber.yield() | ||
end | ||
wait_count = 0 | ||
end | ||
|
||
fiber.set_max_slice(100) | ||
|
||
prepare_tasks() | ||
|
||
-- Wait for all consumers to start. | ||
local consumers = prepare_consumers() | ||
wait_all() | ||
|
||
-- Start timing of task confirmation. | ||
local start_ack_time = clock.proc64() | ||
barrier:broadcast() | ||
-- Wait for all tasks to be acked. | ||
wait_all() | ||
-- Complete the timing of task confirmation. | ||
local complete_time = clock.proc64() | ||
|
||
-- Print the result in milliseconds. | ||
print(string.format("Time it takes to confirm the tasks: %i", | ||
tonumber((complete_time - start_ack_time) / 10^6))) | ||
end | ||
|
||
-- Start benchmark. | ||
multi_consumer_bench() | ||
|
||
-- Cleanup. | ||
test_queue:drop() | ||
|
||
os.exit(0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#!/usr/bin/env tarantool | ||
|
||
local clock = require('clock') | ||
local os = require('os') | ||
local fiber = require('fiber') | ||
local queue = require('queue') | ||
|
||
-- Set the number of consumers. | ||
local consumers_count = 30000 | ||
|
||
local barrier = fiber.cond() | ||
local wait_count = 0 | ||
|
||
box.cfg() | ||
|
||
local test_queue = queue.create_tube('test_queue', 'utube', | ||
{temporary = true, v2 = true}) | ||
|
||
local function prepare_tasks() | ||
local test_data = 'test data' | ||
|
||
for i = 1, consumers_count do | ||
test_queue:put(test_data, {utube = tostring(i)}) | ||
end | ||
end | ||
|
||
local function prepare_consumers() | ||
local consumers = {} | ||
|
||
for i = 1, consumers_count do | ||
consumers[i] = fiber.create(function() | ||
wait_count = wait_count + 1 | ||
-- Wait for all consumers to start. | ||
barrier:wait() | ||
|
||
-- Ack the task. | ||
local task = test_queue:take() | ||
test_queue:ack(task[1]) | ||
|
||
wait_count = wait_count + 1 | ||
end) | ||
end | ||
|
||
return consumers | ||
end | ||
|
||
local function multi_consumer_bench() | ||
--- Wait for all consumer fibers. | ||
local wait_all = function() | ||
while (wait_count ~= consumers_count) do | ||
fiber.yield() | ||
end | ||
wait_count = 0 | ||
end | ||
|
||
fiber.set_max_slice(100) | ||
|
||
-- Wait for all consumers to start. | ||
local consumers = prepare_consumers() | ||
wait_all() | ||
|
||
-- Start timing creation of tasks. | ||
local start_put_time = clock.proc64() | ||
prepare_tasks() | ||
-- Start timing of task confirmation. | ||
local start_ack_time = clock.proc64() | ||
barrier:broadcast() | ||
-- Wait for all tasks to be acked. | ||
wait_all() | ||
-- Complete the timing of task confirmation. | ||
local complete_time = clock.proc64() | ||
|
||
-- Print results in milliseconds. | ||
print(string.format("Time it takes to fill the queue: %i", | ||
tonumber((start_ack_time - start_put_time) / 10^6))) | ||
print(string.format("Time it takes to confirm the tasks: %i", | ||
tonumber((complete_time - start_ack_time) / 10^6))) | ||
end | ||
|
||
-- Start benchmark. | ||
multi_consumer_bench() | ||
|
||
-- Cleanup. | ||
test_queue:drop() | ||
|
||
os.exit(0) |