-
Notifications
You must be signed in to change notification settings - Fork 0
Introduce merkle tree implementation #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 30 commits
13f3d36
04f6899
e0f8466
a07da52
d6a218e
8d9fccb
464930d
573b68d
9f4801f
8fcebe1
cae439d
12faebd
9152495
414d0ee
e84efef
57ec932
3bb2b01
25d9fde
d0b7209
be8872e
a81f3a5
2ecaae8
70e7404
6ea5975
93f9f48
5d4431f
09a475a
0b48db3
3a2c38e
f011d21
0db15ee
3a402e4
de5ab3c
c3669e2
8573df7
5d749ab
a5b58e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| CompileFlags: | ||
| Add: [-D__cpp_concepts=202002L] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,21 +6,36 @@ | |
|
|
||
| cmake_minimum_required(VERSION 3.25) | ||
|
|
||
| option(TESTING "Build and run test suite" ON) | ||
| if (TESTING) | ||
| list(APPEND VCPKG_MANIFEST_FEATURES test) | ||
| endif () | ||
| option(MORUM_BUILD_TESTS "Build tests" ON) | ||
| option(MORUM_BUILD_BENCHMARKS "Build benchmarks" ON) | ||
| option(MORUM_BUILD_TRACY "Enable Tracy profiler" OFF) | ||
|
|
||
| set(CMAKE_CXX_STANDARD 20) | ||
| if (MORUM_BUILD_TESTS) | ||
| list(APPEND VCPKG_MANIFEST_FEATURES "test") | ||
| endif() | ||
| if (MORUM_BUILD_BENCHMARKS) | ||
| list(APPEND VCPKG_MANIFEST_FEATURES "benchmark") | ||
| endif() | ||
| if (MORUM_BUILD_TRACY) | ||
| list(APPEND VCPKG_MANIFEST_FEATURES "tracy") | ||
| endif() | ||
|
|
||
| project(morum | ||
| VERSION 0.1.0 | ||
| LANGUAGES C CXX | ||
| ) | ||
| set(CMAKE_CXX_STANDARD 23) | ||
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
| set(CMAKE_CXX_EXTENSIONS OFF) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't off extensions, please. We are using "statement expressions" in some places. |
||
| set(CMAKE_EXPORT_COMPILE_COMMANDS ON) | ||
| set(CMAKE_POSITION_INDEPENDENT_CODE ON) | ||
| set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API ON) | ||
|
|
||
| project(cpp-jam | ||
| VERSION 0.0.1 | ||
| LANGUAGES CXX | ||
| ) | ||
| add_compile_options(-Wall -Wextra -Werror) | ||
|
|
||
| if ((CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang") | ||
| add_compile_options(-flto=thin) | ||
| endif() | ||
|
|
||
| if(DEFINED CMAKE_TOOLCHAIN_FILE AND CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg") | ||
| if(DEFINED VCPKG_TARGET_TRIPLET AND VCPKG_TARGET_TRIPLET) | ||
|
|
@@ -61,20 +76,28 @@ include(GNUInstallDirs) | |
| message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") | ||
| message(STATUS "Boost_DIR: ${Boost_DIR}") | ||
|
|
||
| find_package(Python3 REQUIRED) | ||
|
|
||
| find_package(PkgConfig REQUIRED) | ||
| pkg_check_modules(libb2 REQUIRED IMPORTED_TARGET GLOBAL libb2) | ||
| option(MORUM_ASAN "Enable address sanitizer" OFF) | ||
| option(MORUM_TSAN "Enable address sanitizer" OFF) | ||
| option(MORUM_UBSAN "Enable address sanitizer" OFF) | ||
| option(MORUM_TRACE "Enable tracing" OFF) | ||
|
|
||
| find_package(Boost CONFIG REQUIRED COMPONENTS algorithm outcome program_options) | ||
| set(Python3_FIND_VIRTUALENV ONLY) | ||
| find_package(Python3 REQUIRED) | ||
| find_package(Boost CONFIG REQUIRED COMPONENTS algorithm program_options outcome) | ||
| find_package(fmt CONFIG REQUIRED) | ||
| find_package(yaml-cpp CONFIG REQUIRED) | ||
| find_package(qdrvm-crates CONFIG REQUIRED) | ||
| find_package(scale CONFIG REQUIRED) | ||
| find_package(soralog CONFIG REQUIRED) | ||
| find_package(Boost.DI CONFIG REQUIRED) | ||
| find_package(qtils CONFIG REQUIRED) | ||
| find_package(prometheus-cpp CONFIG REQUIRED) | ||
| find_package(RocksDB CONFIG REQUIRED) | ||
| find_package(nlohmann_json CONFIG REQUIRED) | ||
| find_package(qdrvm-crates CONFIG REQUIRED) | ||
|
|
||
| find_library(BLAKE2_LIB blake2b) | ||
| add_library(blake2b STATIC IMPORTED) | ||
| set_property(TARGET blake2b PROPERTY IMPORTED_LOCATION ${BLAKE2_LIB}) | ||
|
|
||
| if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") | ||
| add_compile_options(-fmodules-ts) | ||
|
|
@@ -88,14 +111,51 @@ target_include_directories(headers INTERFACE | |
| $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> | ||
| ) | ||
|
|
||
| add_subdirectory(src) | ||
| if (MORUM_ASAN) | ||
| add_compile_options(-fsanitize=address) | ||
| add_link_options(-fsanitize=address) | ||
| endif() | ||
|
|
||
| if (TESTING) | ||
| enable_testing() | ||
| if (MORUM_UBSAN) | ||
| add_compile_options(-fsanitize=undefined -fno-sanitize-recovery=undefined) | ||
| add_link_options(-fsanitize=undefined) | ||
| endif() | ||
|
|
||
| find_package(GTest CONFIG REQUIRED) | ||
| set(GTEST_DEPS GTest::gtest_main) | ||
| if (MORUM_TSAN) | ||
| add_compile_options(-fsanitize=thread) | ||
| add_link_options(-fsanitize=thread) | ||
| endif() | ||
|
|
||
| add_subdirectory(test-vectors) | ||
| add_subdirectory(tests) | ||
| if (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") | ||
| option(QTILS_ASSERT "Enable asserts" OFF) | ||
| else() | ||
| option(QTILS_ASSERT "Enable asserts" ON) | ||
| endif() | ||
|
|
||
| add_subdirectory(src) | ||
|
|
||
| if(MORUM_BUILD_BENCHMARKS) | ||
| find_package(benchmark CONFIG REQUIRED) | ||
| add_subdirectory(benchmark) | ||
| endif() | ||
|
|
||
| if(MORUM_BUILD_TESTS) | ||
| find_package(GTest CONFIG REQUIRED) | ||
| set(GTEST_DEPS GTest::gtest_main) | ||
|
|
||
| enable_testing() | ||
|
|
||
| function (morum_add_test TEST_NAME TEST_SRC) | ||
| add_executable(${TEST_NAME} ${TEST_SRC}) | ||
| target_include_directories(${TEST_NAME} | ||
| PUBLIC | ||
| ${CMAKE_SOURCE_DIR}/include | ||
| ) | ||
| add_compile_definitions(${TEST_NAME} PUBLIC MORUM_TEST_BUILD) | ||
| add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/test_bin") | ||
| set_target_properties(${TEST_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test_bin") | ||
| endfunction() | ||
|
|
||
| add_subdirectory(test-vectors) | ||
| add_subdirectory(test) | ||
| endif () | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
|
|
||
| add_executable(set_get_benchmark merkle_tree/set_get.cpp) | ||
| target_link_libraries(set_get_benchmark benchmark::benchmark merkle_tree) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| #include <cstddef> | ||
| #include <expected> | ||
| #include <filesystem> | ||
| #include <memory> | ||
| #include <optional> | ||
| #include <random> | ||
| #include <ranges> | ||
| #include <string> | ||
| #include <utility> | ||
| #include <vector> | ||
|
|
||
| #include <benchmark/benchmark.h> | ||
| #include <client/TracyScoped.hpp> | ||
| #include <tracy/Tracy.hpp> | ||
|
|
||
| #include <morum/archive_backend.hpp> | ||
| #include <morum/common.hpp> | ||
| #include <morum/db.hpp> | ||
| #include <morum/merkle_tree.hpp> | ||
|
|
||
| constexpr unsigned seed = 42; | ||
| static std::mt19937_64 rand_engine{seed}; | ||
|
|
||
| template <std::ranges::input_range R> | ||
| void fill_random(R &&span) { | ||
| static std::uniform_int_distribution dist; | ||
Harrm marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| for (auto &byte : span) { | ||
| byte = dist(rand_engine); | ||
| } | ||
| } | ||
|
|
||
| morum::Hash32 random_hash() { | ||
| morum::Hash32 hash; | ||
| fill_random(hash); | ||
| return hash; | ||
| } | ||
|
|
||
| qtils::ByteVec random_vector(size_t min_size = 1, size_t max_size = 128) { | ||
| std::uniform_int_distribution<size_t> dist(min_size, max_size); | ||
| size_t size = dist(rand_engine); | ||
|
|
||
| qtils::ByteVec v(size); | ||
| fill_random(v); | ||
| return v; | ||
| } | ||
|
|
||
| std::unique_ptr<morum::ArchiveTrieDb> trie_db; | ||
| morum::Hash32 last_root{}; | ||
|
|
||
| static void BM_SetGet(benchmark::State &state) { | ||
| rand_engine.seed(42); | ||
| constexpr int INSERTION_NUM = 1000; | ||
|
|
||
| for (auto _ : state) { | ||
| ZoneNamedN(loop_zone, "loop", true); | ||
|
|
||
| auto tree = trie_db->load_tree(last_root).value().value(); | ||
|
|
||
| std::vector<std::pair<morum::Hash32, qtils::ByteVec>> insertions; | ||
| for (int i = 0; i < INSERTION_NUM; i++) { | ||
| insertions.emplace_back(random_hash(), random_vector()); | ||
| } | ||
| { | ||
| ZoneNamedN(setter_zone, "set", true); | ||
| for (auto &[k, v] : insertions) { | ||
| tree->set(k, qtils::ByteVec{v}).value(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Возможно тут стоит вставить ассерт на наличие результата
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It will throw an exception and kill the benchmark, which in this place works fine in my opinion. |
||
| } | ||
| } | ||
| { | ||
| ZoneNamedN(getter_zone, "get", true); | ||
|
|
||
| for (auto &[k, v] : insertions) { | ||
| tree->get(k).value(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Возможно тут стоит вставить ассерт на наличие результата
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It will throw an exception and kill the benchmark, which in this place works fine in my opinion. |
||
| } | ||
| } | ||
| { | ||
| ZoneNamedN(calculate_hash_zone, "calculate_hash", true); | ||
| trie_db->get_root_and_store(*tree).value(); | ||
| } | ||
|
|
||
| FrameMark; | ||
| } | ||
| } | ||
|
|
||
| BENCHMARK(BM_SetGet); | ||
|
|
||
| template <typename F> | ||
| struct FinalAction { | ||
Harrm marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ~FinalAction() { | ||
| f(); | ||
| } | ||
|
|
||
| F f; | ||
| }; | ||
|
|
||
| int main(int argc, char **argv) { | ||
| char arg0_default[] = "benchmark"; | ||
| char *args_default = arg0_default; | ||
| if (!argv) { | ||
|
||
| argc = 1; | ||
| argv = &args_default; | ||
| } | ||
|
|
||
| auto db = std::shared_ptr{morum::open_db("./test_db").value()}; | ||
| FinalAction cleanup{[]() { std::filesystem::remove_all("./test_db"); }}; | ||
|
|
||
| trie_db = std::make_unique<morum::ArchiveTrieDb>(db); | ||
|
|
||
| auto tree = trie_db->empty_tree(); | ||
| constexpr int INSERTION_NUM = 5000; | ||
| { | ||
| ZoneNamedN(setter_zone, "initial insertions", true); | ||
|
|
||
| for (int i = 0; i < INSERTION_NUM; i++) { | ||
| tree->set(random_hash(), qtils::ByteVec{random_vector()}).value(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Возможно тут стоит вставить ассерт на наличие результата
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It will throw an exception and kill the benchmark, which in this place works fine in my opinion. |
||
| } | ||
| } | ||
| last_root = trie_db->get_root_and_store(*tree).value(); | ||
| ::benchmark::Initialize(&argc, argv); | ||
| if (::benchmark::ReportUnrecognizedArguments(argc, argv)) { | ||
| return 1; | ||
| } | ||
| ::benchmark::RunSpecifiedBenchmarks(); | ||
| ::benchmark::Shutdown(); | ||
| return 0; | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.