Skip to content

Commit

Permalink
txm: add perf test for mvcc read trackers
Browse files Browse the repository at this point in the history
This patch adds ffi-based performance test for mvcc used to compare
effectiveness of further optimizations.

Needed for #6209
  • Loading branch information
Egor Elchinov committed Sep 27, 2021
1 parent b424f44 commit 090124a
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 0 deletions.
4 changes: 4 additions & 0 deletions perf/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ include_directories(${CMAKE_SOURCE_DIR}/third_party)

add_executable(tuple.perftest tuple.cc)
target_link_libraries(tuple.perftest core box tuple benchmark::benchmark)

add_library(tx_man SHARED tx_man.cc)
target_link_libraries(tx_man ${MSGPUCK_LIBRARIES})
set_target_properties(tx_man PROPERTIES PREFIX "" OUTPUT_NAME "tx_man")
162 changes: 162 additions & 0 deletions perf/tx_man.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#include "tx_man.h"

#include <vector>
#include <chrono>
#include <cstdint>
#include <cstdio>
#include <benchmark/benchmark.h>

constexpr size_t TXM_BENCH_STMT_CNT = 10;
constexpr size_t TXM_BENCH_LOOP_CNT = 100000;

class TxmBenchMsgPack;
using TxmBenchMsgPackSeq = std::vector<TxmBenchMsgPack>;

class TxmBenchMsgPack {
public:
static constexpr uint32_t TXM_BENCH_MAX_TUPLE_DATA_SIZE = 256;
TxmBenchMsgPack() = default;

TxmBenchMsgPack(uint64_t key, const char *value, uint32_t len = 0)
{
char *begin = data_, *end = begin;
end = mp_encode_array(end, 2);
end = mp_encode_uint(end, key);
len = std::min(len == 0 ? (uint32_t) strlen(value) : len,
TXM_BENCH_MAX_TUPLE_DATA_SIZE -
(uint32_t)(end - begin));
end = mp_encode_str(end, value, len);
size_ = end - begin;
}

const char *
begin() const
{
return data_;
}

const char *
end() const
{
return data_ + size_;
}

static int
gen_rand_mp(TxmBenchMsgPack *mp, uint64_t key, uint32_t max_val_len,
uint32_t val_alph_size)
{
char val_buf[TXM_BENCH_MAX_TUPLE_DATA_SIZE];
max_val_len = std::min(max_val_len,
TXM_BENCH_MAX_TUPLE_DATA_SIZE);
val_alph_size = std::min(val_alph_size,
1 + (uint32_t)('z' - 'a'));

uint32_t val_len = 1 + rand() % max_val_len;
char *val_end = val_buf + val_len;
for (char *symb = val_buf; symb < val_end; ++symb)
*symb = 'a' + rand() % val_alph_size;

*mp = TxmBenchMsgPack(key, val_buf, val_len);

return 0;
}

static int
gen_rand_mp_seq(TxmBenchMsgPackSeq *data, uint64_t max_key,
uint32_t max_val_len, uint32_t val_alph_size)
{
TxmBenchMsgPackSeq mp_seq;
for (auto &mp : *data) {
gen_rand_mp(&mp, rand() % max_key, max_val_len,
val_alph_size);
}

return 0;
}

private:
uint32_t size_ = 0;
char data_[TXM_BENCH_MAX_TUPLE_DATA_SIZE];
};

/**
* Insert tuples from into space with id = @a space_id;
*/
int
txm_bench_fill_space(uint32_t space_id, const TxmBenchMsgPack *data, size_t cnt)
{
const TxmBenchMsgPack *mp_end = data + cnt;
for (const TxmBenchMsgPack *mp = data; mp != mp_end; ++mp) {
box_insert(space_id, mp->begin(), mp->end(), NULL);
}

return 0;
}

/**
* Run non-yieldind transaction on space with id = @a space_id.
*/
int
txm_bench_run_txn_no_yield(const char *name, uint32_t space_id,
const TxmBenchMsgPack *data, size_t cnt)
{
// The implementation must be consistent with the fiber_start() call
auto fiber_f = [](va_list args) {
const TxmBenchMsgPack *data
= va_arg(args, const TxmBenchMsgPack *);
size_t cnt = va_arg(args, size_t);
int space_id = va_arg(args, uint32_t);
if (box_txn_begin() != 0)
return -1;

const TxmBenchMsgPack *mp_end = data + cnt;
for (const TxmBenchMsgPack *mp = data; mp != mp_end; ++mp) {
box_replace(space_id, mp->begin(), mp->end(), NULL);
}
// Must commit successfully as no yields occur.
if (box_txn_commit() != 0)
return -1;

return 0;
};

struct fiber *f = fiber_new(name, fiber_f);
if (f == NULL)
return -1;

fiber_set_joinable(f, true);
fiber_start(f, data, cnt, space_id);
return fiber_join(f);
}

int
txm_bench_init(unsigned seed)
{
srand(seed);
return 0;
}

double
txm_bench_run(unsigned space_id)
{
uint64_t cnt = 0;
TxmBenchMsgPackSeq data(TXM_BENCH_STMT_CNT * TXM_BENCH_LOOP_CNT);
TxmBenchMsgPack::gen_rand_mp_seq(&data, UINT64_MAX, 3, 3);
txm_bench_fill_space(space_id, data.data(), data.size());

fprintf(stderr, "[START BENCH]\n");
TxmBenchMsgPack::gen_rand_mp_seq(&data, TXM_BENCH_STMT_CNT, 3, 3);
auto start_ts = std::chrono::steady_clock::now();
for (size_t i = 0; i < TXM_BENCH_LOOP_CNT; ++i) {
if (txm_bench_run_txn_no_yield(
"tx", space_id, data.data() + i * TXM_BENCH_STMT_CNT,
TXM_BENCH_STMT_CNT) != 0)
abort();
}
auto end_ts = std::chrono::steady_clock::now();
double delta = std::chrono::duration<double>(end_ts - start_ts).count();
fprintf(stderr, "[STOP BENCH]\n");
fprintf(stderr, "delta = %lg\n", delta);

return delta;
}
13 changes: 13 additions & 0 deletions perf/tx_man.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef TX_MAN_H_INCLUDED
#define TX_MAN_H_INCLUDED

#include <module.h>
#include <msgpuck.h>

API_EXPORT int
txm_bench_init(unsigned seed);

API_EXPORT double
txm_bench_run(unsigned space_id);

#endif // TX_MAN_H_INCLUDED
25 changes: 25 additions & 0 deletions perf/tx_man.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
local ffi = require('ffi')

ffi.cdef([[
int txm_bench_init(unsigned);
double txm_bench_run(unsigned);
]])
local tx_man_bench = ffi.load(package.searchpath('perf/tx_man', './?.so'))


local run = function(space_id)
box.cfg{
memtx_use_mvcc_engine = true,
}
space_id = space_id + box.schema.SYSTEM_ID_MAX

local space_name = 'space_1'
local space = box.schema.create_space(space_name,{ engine = 'memtx', id = space_id })
space:create_index('pk', { type = 'TREE', parts = {1, 'unsigned'} })
space:create_index('sk', { type = 'HASH', parts = {2, 'string'} })

tx_man_bench.txm_bench_init(0xdeadbeef)
tx_man_bench.txm_bench_run(space_id)
end

run(1)

0 comments on commit 090124a

Please sign in to comment.