Tarantool development patches archive
 help / color / mirror / Atom feed
From: Ilya Kosarev via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: v.shpilevoy@tarantool.org, alyapunov@tarantool.org
Cc: tarantool-patches@dev.tarantool.org
Subject: [Tarantool-patches] [PATCH 1/4] tuple: introduce unit perf test based on gbench
Date: Tue, 19 Jan 2021 02:50:30 +0300	[thread overview]
Message-ID: <e1af2ea02cbc3d79425d82a98f495634c74a4a35.1611013688.git.i.kosarev@tarantool.org> (raw)
In-Reply-To: <cover.1611013688.git.i.kosarev@tarantool.org>
In-Reply-To: <cover.1611013688.git.i.kosarev@tarantool.org>

To verify that tuple actions performance is fine after notable
struct tuple reassembling the perf test is introduced. It tests
creation, deletion, field & data access actions for tuple.
By default, unit perf tests based on gbench are being assembled in case
the google benchmark submodule is being found. Otherwise they are being
silently ignored. If needed, unit perf tests assembling can be enforced
or disabled using -DWITH_UNIT_PERF_TESTS=ON or
-DWITH_UNIT_PERF_TESTS=OFF.

Part of #5385
---
 .gitignore          |   2 +
 CMakeLists.txt      |   1 +
 perf/CMakeLists.txt |  34 ++++++++
 perf/tuple.cc       | 185 ++++++++++++++++++++++++++++++++++++++++++++
 src/box/alter.cc    |   2 +-
 5 files changed, 223 insertions(+), 1 deletion(-)
 create mode 100644 perf/CMakeLists.txt
 create mode 100644 perf/tuple.cc

diff --git a/.gitignore b/.gitignore
index 70784d2b3..4a6ec0e2d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,7 @@ doc/*/Makefile
 extra/Makefile
 extra/*/Makefile
 extra/luarocks/hardcoded.lua
+perf/Makefile
 test/Makefile
 test/*/Makefile
 Doxyfile.API
@@ -88,6 +89,7 @@ src/box/lua/*.lua.c
 src/tarantool
 src/module.h
 tarantool-*.tar.gz
+perf/*.perftest
 test/lib/
 test/unit/*.test
 test/unit/fiob
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4fbd19558..17b0aee00 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -550,6 +550,7 @@ include (cmake/rpm.cmake)
 add_subdirectory(src)
 add_subdirectory(extra)
 add_subdirectory(test)
+add_subdirectory(perf)
 add_subdirectory(doc)
 
 option(WITH_NOTIFY_SOCKET "Enable notifications on NOTIFY_SOCKET" ON)
diff --git a/perf/CMakeLists.txt b/perf/CMakeLists.txt
new file mode 100644
index 000000000..5b7038e05
--- /dev/null
+++ b/perf/CMakeLists.txt
@@ -0,0 +1,34 @@
+set(CMAKE_CXX_STANDARD 11)
+
+set(PERF_TESTS_OPTION ON)
+
+if (NOT DEFINED WITH_UNIT_PERF_TESTS)
+    set(PERF_TESTS_OPTION OFF)
+endif()
+
+if (PERF_TESTS_OPTION AND NOT WITH_UNIT_PERF_TESTS)
+    return()
+endif()
+
+find_package(benchmark QUIET)
+if (NOT ${benchmark_FOUND})
+    if (PERF_TESTS_OPTION AND WITH_UNIT_PERF_TESTS)
+        message(FATAL_ERROR "Google Benchmark submodule not found")
+    else()
+        message(AUTHOR_WARNING "Google Benchmark submodule not found")
+    endif()
+    return()
+endif()
+
+file(GLOB all_sources *.c *.cc)
+
+if(NOT TARGET_OS_OPENBSD)
+    set(LIB_DL "dl")
+endif()
+
+include_directories(${MSGPUCK_INCLUDE_DIRS})
+include_directories(${PROJECT_SOURCE_DIR}/src/box)
+include_directories(${CMAKE_SOURCE_DIR}/third_party)
+
+add_executable(tuple.perftest tuple.cc)
+target_link_libraries(tuple.perftest core box tuple benchmark::benchmark)
diff --git a/perf/tuple.cc b/perf/tuple.cc
new file mode 100644
index 000000000..4d50a49b6
--- /dev/null
+++ b/perf/tuple.cc
@@ -0,0 +1,185 @@
+#include "memory.h"
+#include "fiber.h"
+#include "tuple.h"
+
+#include <benchmark/benchmark.h>
+
+#include <vector>
+
+const size_t amount = 1000, index_count = 4;
+char **start;
+char **end;
+std::vector<struct tuple *> tuples;
+std::vector<struct tuple *> big_tuples;
+std::vector<struct tuple *> tiny_tuples;
+
+static void
+create_tuple(benchmark::State& state)
+{
+	size_t i = 0;
+	for (auto _ : state) {
+		struct tuple *tuple = tuple_new(box_tuple_format_default(),
+						start[i % amount],
+						end[i % amount]);
+		tuple_ref(tuple);
+		tuple_unref(tuple);
+		i++;
+	}
+}
+BENCHMARK(create_tuple);
+
+static inline int
+access_fields(struct tuple *tuple)
+{
+	int sum = 0;
+	sum += tuple->refs;
+	sum += tuple->format_id;
+	sum += tuple->bsize;
+	sum += tuple->data_offset;
+	sum += tuple->is_dirty;
+	return sum;
+}
+
+static void
+access_tuple_fields(benchmark::State& state)
+{
+	size_t i = 0;
+	int64_t sum = 0;
+	for (auto _ : state) {
+		struct tuple *tuple = tuples[i++ % tuples.size()];
+		sum += access_fields(tuple);
+	}
+	assert(sum > 0);
+}
+BENCHMARK(access_tuple_fields);
+
+static void
+access_tiny_tuple_fields(benchmark::State& state)
+{
+	size_t i = 0;
+	int64_t sum = 0;
+	for (auto _ : state) {
+		struct tuple *tuple = tiny_tuples[i++ % tiny_tuples.size()];
+		sum += access_fields(tuple);
+	}
+	assert(sum > 0);
+}
+BENCHMARK(access_tiny_tuple_fields);
+
+static void
+access_big_tuple_fields(benchmark::State& state)
+{
+	size_t i = 0;
+	int64_t sum = 0;
+	for (auto _ : state) {
+		struct tuple *tuple = big_tuples[i++ % big_tuples.size()];
+		sum += access_fields(tuple);
+	}
+	assert(sum > 0);
+}
+BENCHMARK(access_big_tuple_fields);
+
+static inline int
+access_data(struct tuple *tuple)
+{
+	uint32_t out;
+	int sum = 0;
+	for (size_t j = 0; j <= index_count; j++)
+		sum += tuple_field_u32(tuple, j, &out);
+	return sum;
+}
+
+static void
+access_tuple_data(benchmark::State& state)
+{
+	size_t i = 0;
+	int64_t sum = 0;
+	for (auto _ : state) {
+		struct tuple *tuple = tuples[i++ % tuples.size()];
+		access_data(tuple);
+	}
+	assert(sum == 0);
+}
+BENCHMARK(access_tuple_data);
+
+static void
+access_tiny_tuple_data(benchmark::State& state)
+{
+	size_t i = 0;
+	int64_t sum = 0;
+	for (auto _ : state) {
+		struct tuple *tuple = tiny_tuples[i++ % tiny_tuples.size()];
+		access_data(tuple);
+	}
+	assert(sum == 0);
+}
+BENCHMARK(access_tiny_tuple_data);
+
+static void
+access_big_tuple_data(benchmark::State& state)
+{
+	size_t i = 0;
+	int64_t sum = 0;
+	for (auto _ : state) {
+		struct tuple *tuple = big_tuples[i++ % big_tuples.size()];
+		access_data(tuple);
+	}
+	assert(sum == 0);
+}
+BENCHMARK(access_big_tuple_data);
+
+int main(int argc, char **argv)
+{
+	memory_init();
+	fiber_init(fiber_c_invoke);
+	tuple_init(NULL);
+
+	char *alloc = (char *)malloc(amount * 5 + amount * (amount - 1) * 2);
+	start = (char **)calloc(amount, sizeof(char *));
+	end = (char **)calloc(amount, sizeof(char *));
+	uint32_t data_size = index_count;
+	start[0] = alloc;
+	for (size_t i = 0; i < amount; i++) {
+		char *cur = start[i];
+		cur = mp_encode_array(cur, ++data_size);
+		for (size_t j = 0; j < data_size; j++)
+			cur = mp_encode_uint(cur, j);
+		end[i] = cur;
+		if (i + 1 < amount)
+			start[i + 1] = cur;
+	}
+
+	uint32_t fieldno0[] = {0};
+	uint32_t fieldno1[] = {1};
+	uint32_t fieldno2[] = {2, 3};
+	uint32_t type1[] = {FIELD_TYPE_UNSIGNED};
+	uint32_t type2[] = {FIELD_TYPE_UNSIGNED, FIELD_TYPE_UNSIGNED};
+	box_key_def_t *key_defs[] = {
+		box_key_def_new(fieldno0, type1, 1),
+		box_key_def_new(fieldno1, type1, 1),
+		box_key_def_new(fieldno2, type2, 2)};
+	box_tuple_format_t *format = box_tuple_format_new(key_defs, 3);
+	for (size_t i = 0; i < amount; i++) {
+		struct tuple *tuple = tuple_new(format, start[i], end[i]);
+		tuple_ref(tuple);
+		if (tuple->bsize <= UINT8_MAX)
+			tiny_tuples.push_back(tuple);
+		else
+			big_tuples.push_back(tuple);
+		tuples.push_back(tuple);
+	}
+
+	::benchmark::Initialize(&argc, argv);
+	if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
+	::benchmark::RunSpecifiedBenchmarks();
+
+	free(alloc);
+	free(start);
+	free(end);
+	for (auto tuple: tuples)
+		tuple_unref(tuple);
+
+	tuple_free();
+	fiber_free();
+	memory_free();
+}
\ No newline at end of file
diff --git a/src/box/alter.cc b/src/box/alter.cc
index 075b79d33..8c65e7552 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -4538,7 +4538,7 @@ on_drop_sequence_data_rollback(struct trigger *trigger, void * /* event */)
 	uint32_t id;
 	if (tuple_field_u32(tuple, BOX_SEQUENCE_DATA_FIELD_ID, &id) != 0)
 		return -1;
-	int64_t val;
+	int64_t val = 0;
 	if (tuple_field_i64(tuple, BOX_SEQUENCE_DATA_FIELD_VALUE, &val) != 0)
 		return -1;
 	struct sequence *seq = sequence_by_id(id);
-- 
2.17.1


  reply	other threads:[~2021-01-18 23:51 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-18 23:50 [Tarantool-patches] [PATCH 0/4] Introduce tiny tuples with perf test Ilya Kosarev via Tarantool-patches
2021-01-18 23:50 ` Ilya Kosarev via Tarantool-patches [this message]
2021-01-18 23:50 ` [Tarantool-patches] [PATCH 2/4] tuple: use getters and setters Ilya Kosarev via Tarantool-patches
2021-01-18 23:50 ` [Tarantool-patches] [PATCH 3/4] core: introduce tiny tuples Ilya Kosarev via Tarantool-patches
2021-01-18 23:50 ` [Tarantool-patches] [PATCH 4/4] box: introduce 1 byte field map offsets Ilya Kosarev via Tarantool-patches

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e1af2ea02cbc3d79425d82a98f495634c74a4a35.1611013688.git.i.kosarev@tarantool.org \
    --to=tarantool-patches@dev.tarantool.org \
    --cc=alyapunov@tarantool.org \
    --cc=i.kosarev@tarantool.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH 1/4] tuple: introduce unit perf test based on gbench' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox