-
-
Save igormunkin/e956396d8fb3348d3ebbad60588af297 to your computer and use it in GitHub Desktop.
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
#!/usr/bin/tarantool | |
-- vim:ts=4 ss=4 sw=4 expandtab | |
-- Usage: tarantool relay-1mops.lua [num_ops] [nodes] | |
-- num_ops should be a number multiple of num_fibers * ops_per_txn | |
-- nodes should be a number from 1 to 31 | |
local clock = require('clock') | |
local fiber = require('fiber') | |
local popen = require('popen') | |
local yaml = require('yaml') | |
-- TUNE OPTIONS HERE | |
-- working dir is cleared/created for every run, set mwd | |
-- during the test a subdir will be created for each replica | |
local mwd = './relay-test.data' | |
-- turn true to test the qsync | |
local test_qsync = false | |
-- number of operations performed by test | |
local num_ops = tonumber(arg[1] or 1e6) | |
-- number of fibers | |
local num_fibers = 50 | |
-- number of operations per transaction | |
local ops_per_txn = 100 | |
-- check the number of operations value | |
local txns, tail = math.modf(num_ops / num_fibers / ops_per_txn) | |
assert(txns > 0 and tail == 0, | |
('Invalid number of iterations: %s'):format(num_ops)) | |
-- number of nodes - master and replicas | |
local nodes, tail = math.modf(tonumber(arg[2] or 0) + 1) | |
assert(nodes > 0 and nodes < 32 and tail == 0, | |
('Invalid number of nodes: %s'):format(nodes)) | |
-- posterior evaluation shows that 256Mb is enough to make | |
-- 4 million replaces | |
local default_memtx_memory = 256 * 1024 * 1024 | |
local memtx_memory = math.max(math.ceil(num_ops / 1e6 * default_memtx_memory), | |
default_memtx_memory) | |
-- END OF TUNABLE OPTIONS | |
print(('making %d operations, %d operations per txn using %d fibers'):format( | |
num_ops, ops_per_txn, num_fibers)) | |
--- transactions per fiber | |
local trans_per_fiber = num_ops/ops_per_txn/num_fibers | |
os.execute(('rm -rf %s'):format(mwd)) | |
os.execute(('mkdir -p %s'):format(mwd)) | |
box.cfg({ | |
listen = 3301, | |
log_level = 0, | |
memtx_memory = memtx_memory, | |
read_only = false, | |
replication = 'replicator:password@localhost:3301', | |
work_dir = mwd, | |
}) | |
if test_qsync then | |
box.cfg({ replication_synchro_quorum = nodes }) | |
end | |
box.schema.user.create('replicator', { password = 'password' }) | |
box.schema.user.grant('replicator', 'replication') | |
-- number of nodes, storage for popen handles | |
local nodes_ph = {} | |
-- run replicas (if needed) | |
if nodes > 1 then | |
print(('starting %d replicas'):format(nodes - 1)) | |
for i = 2, nodes do | |
-- subdir for replica's data | |
local rwd = ('relay-test.replica-%s'):format(i) | |
os.execute(('rm -rf %s'):format(rwd)) | |
os.execute(('mkdir -p %s'):format(rwd)) | |
-- command line for replica to start | |
local cmd = { arg[-1], '-e', ([[ | |
box.cfg({ | |
listen = %d, | |
log_level = 0, | |
memtx_memory = %d, | |
read_only = false, | |
replication = 'replicator:password@localhost:3301', | |
work_dir = '%s', | |
}) | |
]]):format(3300 + i, memtx_memory, rwd) } | |
local res, err = popen.new(cmd, { | |
stdin = 'devnull', | |
stdout = 'devnull', | |
stderr = 'devnull', | |
}) | |
assert(res, ('Error running replica %d: %s'):format(i, err)) | |
nodes_ph[i] = res | |
end | |
-- wait for all replicas to connect | |
while #box.info.replication < nodes do | |
fiber.sleep(0.1) | |
end | |
end | |
local space = box.schema.create_space('test', | |
test_qsync and { is_sync = true } or { }) | |
space:create_index('pk', { type = 'HASH' }) | |
-- each fiber runs the fiber_load that has evenly distributed workload | |
function fiber_load(start, s) | |
for i = 1, trans_per_fiber do | |
box.begin() | |
for j = 1, ops_per_txn do | |
s:replace{ start, start } | |
start = start + 1 | |
end | |
box.commit() | |
end | |
end | |
-- fiber storage to join them | |
local fibers_storage = { } | |
-- start timer | |
local start = { | |
lsn = box.info.replication[1].lsn, | |
proc = clock.proc(), | |
time = clock.time(), | |
} | |
for i = 1, num_fibers do | |
fibers_storage[i] = fiber.create(fiber_load, i*num_ops, space) | |
fibers_storage[i]:wakeup() -- needed for backward compatibility with 1.7 | |
end | |
-- wait for all fibers to finish | |
for i = 1, num_fibers do | |
while fibers_storage[i]:status() ~= 'dead' do | |
fiber.yield() | |
end -- the loop is needed for backward compatibility with 1.7 | |
end | |
local ops_done = box.info.replication[1].lsn | |
-- stop timer for master | |
local stop = { | |
lsn = ops_done - start.lsn, | |
proc = clock.proc() - start.proc, | |
time = clock.time() - start.time, | |
} | |
assert(num_ops == stop.lsn, | |
('Missing data: %d/%d inserted'):format(stop.lsn, num_ops)) | |
print(('master done in time: %f, cpu: %f\nmaster speed: %d ops/sec'):format( | |
stop.time, stop.proc, math.floor(stop.lsn / stop.time))) | |
-- wait for all replicas and kill them | |
if nodes > 1 then | |
local done = false | |
repeat | |
for i = 2, nodes do | |
local r_vclock = box.info.replication[i].downstream.vclock | |
if r_vclock and r_vclock[1] < ops_done then | |
done = false | |
break | |
end | |
done = true | |
end | |
if not done then | |
fiber.sleep(0.001) | |
end | |
until done | |
-- stop timer for replicas | |
stop = { | |
lsn = box.info.replication[nodes].downstream.vclock[1] - start.lsn, | |
time = clock.time() - start.time, | |
proc = clock.proc() - start.proc, | |
} | |
print(('replicas done in time: %f, cpu: %f\nreplicas speed: %f ops/sec'):format( | |
stop.time, stop.proc, math.floor(stop.lsn / stop.time))) | |
for _, replica in pairs(nodes_ph) do | |
replica:kill() | |
replica:wait() | |
end | |
end | |
os.exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Some stats for wall clock timings and operations per second (Apple M1 vs Intel(R) Core(TM) i5-1038NG7 CPU @ 2.00GHz).
1000000 replaces
5000000 replaces
10000000 replaces
15000000 replaces
20000000 replaces