├── .clang-format ├── .github └── workflows │ ├── cicada_build.yml │ ├── ermia_build.yml │ ├── mocc_build.yml │ ├── si_build.yml │ ├── silo_build.yml │ ├── ss2pl_build.yml │ ├── tictoc_build.yml │ └── tpcc_silo_build_and_ctest.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── build_tools ├── bootstrap.sh ├── bootstrap_apt.sh ├── bootstrap_googletest.sh ├── bootstrap_mimalloc.sh ├── bootstrap_tbb.sh └── ubuntu.deps ├── cc_format ├── Makefile ├── README.md ├── include │ ├── atomic_tool.hh │ ├── common.hh │ ├── log.hh │ ├── result.hh │ ├── silo_op_element.hh │ ├── transaction.hh │ ├── tuple.hh │ └── util.hh ├── result.cc ├── sv_format.cc ├── transaction.cc └── util.cc ├── cicada ├── CMakeLists.txt ├── README.md ├── cicada.cc ├── include │ ├── cicada_op_element.hh │ ├── common.hh │ ├── lock.hh │ ├── result.hh │ ├── time_stamp.hh │ ├── transaction.hh │ ├── tuple.hh │ ├── util.hh │ └── version.hh ├── result.cc ├── script │ ├── test_cache_ana.sh │ ├── test_t1k.sh │ ├── test_t1m.sh │ ├── test_t200.sh │ ├── test_wal.sh │ ├── test_wal4pair.sh │ ├── tst200-1k-1m.sh │ ├── ycsb-xgci.sh │ ├── ycsb-xope.sh │ ├── ycsb-xrratio.sh │ ├── ycsb-xrs.sh │ ├── ycsb-xskew.sh │ ├── ycsb-xth.sh │ ├── ycsb-xval.sh │ ├── ycsbA-xgcidbsize-cache.sh │ ├── ycsbA-xrs-cache.sh │ ├── ycsbA.sh │ ├── ycsbB.sh │ └── ycsbC.sh ├── testzip.cc ├── transaction.cc └── util.cc ├── cmake ├── CompileOptions.cmake ├── Findgflags.cmake └── Findglog.cmake ├── common ├── Makefile ├── result.cc └── util.cc ├── ermia ├── CMakeLists.txt ├── README.md ├── ermia.cc ├── garbage_collection.cc ├── include │ ├── common.hh │ ├── ermia_op_element.hh │ ├── garbage_collection.hh │ ├── lock.hh │ ├── result.hh │ ├── transaction.hh │ ├── transaction_status.hh │ ├── transaction_table.hh │ ├── tuple.hh │ ├── util.hh │ └── version.hh ├── result.cc ├── script │ ├── test_cache_ana.sh │ ├── test_t1k.sh │ ├── test_t1m.sh │ ├── test_t200.sh │ ├── tst200-1k-1m.sh │ ├── ycsb-xope.sh │ ├── ycsb-xrratio.sh │ ├── ycsb-xrs.sh │ ├── ycsb-xskew.sh │ ├── ycsb-xth.sh │ ├── ycsb-xval.sh │ ├── ycsbA-xgcidbsize-cache.sh │ ├── ycsbA-xgcidbsize.sh │ ├── ycsbA-xrs-cache.sh │ ├── ycsbA.sh │ ├── ycsbB.sh │ └── ycsbC.sh ├── transaction.cc └── util.cc ├── include ├── Makefile ├── atomic_wrapper.hh ├── backoff.hh ├── cache_line_size.hh ├── check.hh ├── compiler.hh ├── config.hh ├── cpu.hh ├── debug.hh ├── delay.hh ├── fence.hh ├── fileio.hh ├── inline.hh ├── int64byte.hh ├── logger.h ├── masstree_wrapper.hh ├── op_element.hh ├── procedure.hh ├── random.hh ├── result.hh ├── rwlock.hh ├── string.hh ├── tsc.hh ├── util.hh └── zipf.hh ├── instruction ├── Makefile ├── README.md ├── cache-test.cc ├── fetch_add.cc ├── include │ └── common.hh ├── masstree_simple_test │ ├── GNUmakefile │ ├── script │ │ ├── test.sh │ │ └── xrs.sh │ ├── unit-mt.cc │ └── unit-mt2.cc ├── mcslock_with_timeout.c ├── membench.cc ├── pow_test.cc ├── rdtscBench.cc ├── script │ ├── fetch_add.sh │ └── membench.sh ├── test_fetch_add.sh ├── test_xoroshiro.sh ├── xoroshiro.cc └── zipf_dist_test.cc ├── mocc ├── CMakeLists.txt ├── README.md ├── include │ ├── atomic_tool.hh │ ├── common.hh │ ├── lock.hh │ ├── mocc_op_element.hh │ ├── result.hh │ ├── transaction.hh │ ├── tuple.hh │ └── util.hh ├── lock.cc ├── mocc.cc ├── pseudo_mql.txt ├── result.cc ├── script │ ├── test_cache_ana.sh │ ├── test_t1k.sh │ ├── test_t1m.sh │ ├── test_t200.sh │ ├── tst200-1k-1m.sh │ ├── ycsb-xope.sh │ ├── ycsb-xrratio.sh │ ├── ycsb-xrs.sh │ ├── ycsb-xskew.sh │ ├── ycsb-xth.sh │ ├── ycsb-xval.sh │ ├── ycsbA-xrs-cache.sh │ ├── ycsbA.sh │ ├── ycsbB.sh │ └── ycsbC.sh ├── transaction.cc └── util.cc ├── occ ├── Makefile ├── README.md ├── include │ ├── atomic_tool.hh │ ├── common.hh │ ├── log.hh │ ├── occ_op_element.hh │ ├── result.hh │ ├── transaction.hh │ ├── tuple.hh │ └── util.hh ├── occ.cc ├── result.cc ├── transaction.cc └── util.cc ├── si ├── CMakeLists.txt ├── README.md ├── garbage_collection.cc ├── include │ ├── common.hh │ ├── garbage_collection.hh │ ├── result.hh │ ├── si_op_element.hh │ ├── transaction.hh │ ├── transaction_table.hh │ ├── tuple.hh │ ├── util.hh │ └── version.hh ├── result.cc ├── script │ ├── tst200-1k-1m.sh │ ├── ycsb-xope.sh │ ├── ycsb-xrratio.sh │ ├── ycsb-xrs.sh │ ├── ycsb-xskew.sh │ ├── ycsb-xth.sh │ ├── ycsb-xval.sh │ ├── ycsbA-xrs-cache.sh │ ├── ycsbA.sh │ ├── ycsbB.sh │ └── ycsbC.sh ├── si.cc ├── transaction.cc └── util.cc ├── silo ├── CMakeLists.txt ├── README.md ├── include │ ├── atomic_tool.hh │ ├── common.hh │ ├── log.hh │ ├── result.hh │ ├── silo_op_element.hh │ ├── transaction.hh │ ├── tuple.hh │ └── util.hh ├── replayTest.cc ├── result.cc ├── script │ ├── test_cache_ana.sh │ ├── test_t1k.sh │ ├── test_t1m.sh │ ├── test_t200.sh │ ├── tst200-1k-1m.sh │ ├── ycsb-xgci.sh │ ├── ycsb-xope.sh │ ├── ycsb-xrratio.sh │ ├── ycsb-xrs.sh │ ├── ycsb-xskew.sh │ ├── ycsb-xslprp.sh │ ├── ycsb-xth.sh │ ├── ycsb-xval.sh │ ├── ycsbA-xrs-cache.sh │ ├── ycsbA.sh │ ├── ycsbB.sh │ └── ycsbC.sh ├── silo.cc ├── transaction.cc └── util.cc ├── ss2pl ├── CMakeLists.txt ├── README.md ├── include │ ├── common.hh │ ├── result.hh │ ├── ss2pl_op_element.hh │ ├── transaction.hh │ ├── tuple.hh │ └── util.hh ├── result.cc ├── script │ ├── test_cache_ana.sh │ ├── test_t1k.sh │ ├── test_t1m.sh │ ├── test_t200.sh │ ├── tst200-1k-1m.sh │ ├── ycsb-xope.sh │ ├── ycsb-xrratio.sh │ ├── ycsb-xrs.sh │ ├── ycsb-xskew.sh │ ├── ycsb-xth.sh │ ├── ycsb-xval.sh │ ├── ycsbA-xrs-cache.sh │ ├── ycsbA.sh │ ├── ycsbB.sh │ └── ycsbC.sh ├── ss2pl.cc ├── test │ ├── CMakeLists.txt │ └── make_db_test.cpp ├── transaction.cc └── util.cc ├── tictoc ├── CMakeLists.txt ├── README.md ├── include │ ├── common.hh │ ├── result.hh │ ├── tictoc_op_element.hh │ ├── transaction.hh │ ├── tuple.hh │ └── util.hh ├── result.cc ├── script │ ├── test_cache_ana.sh │ ├── test_t1k.sh │ ├── test_t1m.sh │ ├── test_t200.sh │ ├── tst200-1k-1m.sh │ ├── ycsb-xope.sh │ ├── ycsb-xrratio.sh │ ├── ycsb-xrs.sh │ ├── ycsb-xskew.sh │ ├── ycsb-xslprp.sh │ ├── ycsb-xth.sh │ ├── ycsb-xval.sh │ ├── ycsbA-xrs-cache.sh │ ├── ycsbA.sh │ ├── ycsbB.sh │ └── ycsbC.sh ├── tictoc.cc ├── transaction.cc └── util.cc └── tpcc_silo ├── CMakeLists.txt ├── README.md ├── build_script.sh ├── epoch.cpp ├── garbage_collection.cpp ├── include ├── aligned_allocator.h ├── atomic_tool.hh ├── atomic_wrapper.h ├── clock.h ├── common.hh ├── compiler.h ├── cpu.h ├── epoch.h ├── error.h ├── fence.h ├── fileio.h ├── garbage_collection.h ├── heap_object.hpp ├── inline.h ├── log.h ├── memory.h ├── record.h ├── result.hh ├── scheme.h ├── scheme_global.h ├── session_info.h ├── session_info_table.h ├── tid.h ├── tsc.h ├── tuple.h └── util.hh ├── index └── masstree_beta │ ├── include │ └── masstree_beta_wrapper.h │ └── masstree_beta_wrapper.cpp ├── interface ├── interface.h ├── interface_delete.cpp ├── interface_helper.cpp ├── interface_helper.h ├── interface_scan.cpp ├── interface_search.cpp ├── interface_termination.cpp └── interface_update_insert.cpp ├── log.cpp ├── result.cpp ├── scheme.cpp ├── session_info.cpp ├── session_info_table.cpp ├── silo.cpp ├── test ├── CMakeLists.txt ├── aligned_allocator_test.cpp ├── scheme_global_test.cpp ├── tpcc_initializer_test.cpp ├── tpcc_tables_test.cpp ├── tpcc_util_test.cpp └── unit_test.cpp ├── tid.cpp ├── tpcc ├── neworder.cpp ├── payment.cpp ├── tpcc_initializer.hpp ├── tpcc_query.cpp ├── tpcc_query.hpp ├── tpcc_tables.hpp ├── tpcc_txn.hpp └── tpcc_util.hpp └── util.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | # Generated from CLion C/C++ Code Style settings 2 | BasedOnStyle: LLVM 3 | AccessModifierOffset: -4 4 | AlignAfterOpenBracket: Align 5 | AlignConsecutiveAssignments: false 6 | AlignOperands: true 7 | AllowAllArgumentsOnNextLine: false 8 | AllowAllConstructorInitializersOnNextLine: false 9 | AllowAllParametersOfDeclarationOnNextLine: false 10 | AllowShortBlocksOnASingleLine: Always 11 | AllowShortCaseLabelsOnASingleLine: false 12 | AllowShortFunctionsOnASingleLine: All 13 | AllowShortIfStatementsOnASingleLine: Always 14 | AllowShortLambdasOnASingleLine: All 15 | AllowShortLoopsOnASingleLine: true 16 | AlwaysBreakAfterReturnType: None 17 | AlwaysBreakTemplateDeclarations: Yes 18 | BreakBeforeBraces: Custom 19 | BraceWrapping: 20 | AfterCaseLabel: false 21 | AfterClass: false 22 | AfterControlStatement: Never 23 | AfterEnum: false 24 | AfterFunction: false 25 | AfterNamespace: false 26 | AfterUnion: false 27 | BeforeCatch: false 28 | BeforeElse: false 29 | IndentBraces: false 30 | SplitEmptyFunction: false 31 | SplitEmptyRecord: true 32 | BreakBeforeBinaryOperators: None 33 | BreakBeforeTernaryOperators: true 34 | BreakConstructorInitializers: BeforeColon 35 | BreakInheritanceList: BeforeColon 36 | ColumnLimit: 80 37 | CompactNamespaces: false 38 | ContinuationIndentWidth: 8 39 | IndentCaseLabels: true 40 | IndentPPDirectives: None 41 | IndentWidth: 4 42 | KeepEmptyLinesAtTheStartOfBlocks: true 43 | MaxEmptyLinesToKeep: 2 44 | NamespaceIndentation: None 45 | ObjCSpaceAfterProperty: false 46 | ObjCSpaceBeforeProtocolList: true 47 | PointerAlignment: Left 48 | ReflowComments: false 49 | SpaceAfterCStyleCast: true 50 | SpaceAfterLogicalNot: false 51 | SpaceAfterTemplateKeyword: false 52 | SpaceBeforeAssignmentOperators: true 53 | SpaceBeforeCpp11BracedList: false 54 | SpaceBeforeCtorInitializerColon: true 55 | SpaceBeforeInheritanceColon: true 56 | SpaceBeforeParens: ControlStatements 57 | SpaceBeforeRangeBasedForLoopColon: true 58 | SpaceInEmptyParentheses: false 59 | SpacesBeforeTrailingComments: 1 60 | SpacesInAngles: false 61 | SpacesInCStyleCastParentheses: false 62 | SpacesInContainerLiterals: false 63 | SpacesInParentheses: false 64 | SpacesInSquareBrackets: false 65 | TabWidth: 4 66 | UseTab: Never 67 | -------------------------------------------------------------------------------- /.github/workflows/cicada_build.yml: -------------------------------------------------------------------------------- 1 | name: cicada_build 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/workflows/cicada_build.yml' 7 | - 'cicada/**' 8 | - 'common/**' 9 | - 'include/**' 10 | - 'third_party/**' 11 | pull_request: 12 | paths: 13 | - '.github/workflows/cicada_build.yml' 14 | - 'cicada/**' 15 | - 'common/**' 16 | - 'include/**' 17 | 18 | jobs: 19 | Build: 20 | runs-on: ubuntu-latest 21 | timeout-minutes: 10 22 | 23 | steps: 24 | - id: Begin 25 | name: Begin 26 | run: | 27 | echo "Begin ${GITHUB_WORKFLOW}/${GITHUB_JOB}" 28 | 29 | - id: Checkout 30 | name: Checkout 31 | uses: actions/checkout@v2 32 | 33 | - id: Install_apt 34 | name: Install_apt 35 | run: | 36 | sudo apt update -y 37 | sudo apt-get install -y $(cat build_tools/ubuntu.deps) 38 | 39 | - id: Submodule_init_recursive 40 | name: Submodule_init_recursive 41 | run: | 42 | git submodule update --init --recursive 43 | 44 | - id: Build_third_party_masstree 45 | name: Build_third_party_masstree 46 | run: | 47 | ./build_tools/bootstrap.sh 48 | 49 | - id: Build_third_party_mimalloc 50 | name: Build_third_party_mimalloc 51 | run: | 52 | ./build_tools/bootstrap_mimalloc.sh 53 | 54 | - id: Build_third_party_googletest 55 | name: Build_third_party_googletest 56 | run: | 57 | ./build_tools/bootstrap_googletest.sh 58 | 59 | - id: Build_cicada 60 | name: Build_cicada 61 | run: | 62 | cd cicada 63 | mkdir build 64 | cd build 65 | cmake -DCMAKE_BUILD_TYPE=Debug .. 66 | cmake --build . --target all --clean-first -- -j 67 | -------------------------------------------------------------------------------- /.github/workflows/ermia_build.yml: -------------------------------------------------------------------------------- 1 | name: ermia_build 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/workflows/ermia_build.yml' 7 | - 'common/**' 8 | - 'ermia/**' 9 | - 'third_party/**' 10 | pull_request: 11 | paths: 12 | - '.github/workflows/ermia_build.yml' 13 | - 'common/**' 14 | - 'ermia/**' 15 | 16 | jobs: 17 | Build: 18 | runs-on: ubuntu-latest 19 | timeout-minutes: 10 20 | 21 | steps: 22 | - id: Begin 23 | name: Begin 24 | run: | 25 | echo "Begin ${GITHUB_WORKFLOW}/${GITHUB_JOB}" 26 | 27 | - id: Checkout 28 | name: Checkout 29 | uses: actions/checkout@v2 30 | 31 | - id: Install_apt 32 | name: Install_apt 33 | run: | 34 | sudo apt update -y 35 | sudo apt-get install -y $(cat build_tools/ubuntu.deps) 36 | 37 | - id: Submodule_init_recursive 38 | name: Submodule_init_recursive 39 | run: | 40 | git submodule update --init --recursive 41 | 42 | - id: Build_third_party_masstree 43 | name: Build_third_party_masstree 44 | run: | 45 | ./build_tools/bootstrap.sh 46 | 47 | - id: Build_third_party_mimalloc 48 | name: Build_third_party_mimalloc 49 | run: | 50 | ./build_tools/bootstrap_mimalloc.sh 51 | 52 | - id: Build_third_party_googletest 53 | name: Build_third_party_googletest 54 | run: | 55 | ./build_tools/bootstrap_googletest.sh 56 | 57 | - id: Build_ermia 58 | name: Build_ermia 59 | run: | 60 | cd ermia 61 | mkdir -p build 62 | cd build 63 | cmake -DCMAKE_BUILD_TYPE=Debug .. 64 | make -j 65 | -------------------------------------------------------------------------------- /.github/workflows/mocc_build.yml: -------------------------------------------------------------------------------- 1 | name: mocc_build 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/workflows/mocc_build.yml' 7 | - 'common/**' 8 | - 'mocc/**' 9 | - 'third_party/**' 10 | pull_request: 11 | - '.github/workflows/mocc_build.yml' 12 | - 'common/**' 13 | - 'mocc/**' 14 | 15 | jobs: 16 | Build: 17 | runs-on: ubuntu-latest 18 | timeout-minutes: 10 19 | 20 | steps: 21 | - id: Begin 22 | name: Begin 23 | run: | 24 | echo "Begin ${GITHUB_WORKFLOW}/${GITHUB_JOB}" 25 | 26 | - id: Checkout 27 | name: Checkout 28 | uses: actions/checkout@v2 29 | 30 | - id: Install_apt 31 | name: Install_apt 32 | run: | 33 | sudo apt update -y 34 | sudo apt-get install -y $(cat build_tools/ubuntu.deps) 35 | 36 | - id: Submodule_init_recursive 37 | name: Submodule_init_recursive 38 | run: | 39 | git submodule update --init --recursive 40 | 41 | - id: Build_third_party_masstree 42 | name: Build_third_party_masstree 43 | run: | 44 | ./build_tools/bootstrap.sh 45 | 46 | - id: Build_third_party_mimalloc 47 | name: Build_third_party_mimalloc 48 | run: | 49 | ./build_tools/bootstrap_mimalloc.sh 50 | 51 | - id: Build_third_party_googletest 52 | name: Build_third_party_googletest 53 | run: | 54 | ./build_tools/bootstrap_googletest.sh 55 | 56 | - id: Build_mocc 57 | name: Build_mocc 58 | run: | 59 | cd mocc 60 | mkdir -p build 61 | cd build 62 | cmake -DCMAKE_BUILD_TYPE=Debug .. 63 | make -j 64 | -------------------------------------------------------------------------------- /.github/workflows/si_build.yml: -------------------------------------------------------------------------------- 1 | name: si_build 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/workflows/si_build.yml' 7 | - 'common/**' 8 | - 'si/**' 9 | - 'third_party/**' 10 | pull_request: 11 | paths: 12 | - '.github/workflows/si_build.yml' 13 | - 'common/**' 14 | - 'si/**' 15 | 16 | jobs: 17 | Build: 18 | runs-on: ubuntu-latest 19 | timeout-minutes: 10 20 | 21 | steps: 22 | - id: Begin 23 | name: Begin 24 | run: | 25 | echo "Begin ${GITHUB_WORKFLOW}/${GITHUB_JOB}" 26 | 27 | - id: Checkout 28 | name: Checkout 29 | uses: actions/checkout@v2 30 | 31 | - id: Install_apt 32 | name: Install_apt 33 | run: | 34 | sudo apt update -y 35 | sudo apt-get install -y $(cat build_tools/ubuntu.deps) 36 | 37 | - id: Submodule_init_recursive 38 | name: Submodule_init_recursive 39 | run: | 40 | git submodule update --init --recursive 41 | 42 | - id: Build_third_party_masstree 43 | name: Build_third_party_masstree 44 | run: | 45 | ./build_tools/bootstrap.sh 46 | 47 | - id: Build_third_party_mimalloc 48 | name: Build_third_party_mimalloc 49 | run: | 50 | ./build_tools/bootstrap_mimalloc.sh 51 | 52 | - id: Build_third_party_googletest 53 | name: Build_third_party_googletest 54 | run: | 55 | ./build_tools/bootstrap_googletest.sh 56 | 57 | - id: Build_si 58 | name: Build_si 59 | run: | 60 | cd si 61 | mkdir -p build 62 | cd build 63 | cmake -DCMAKE_BUILD_TYPE=Debug .. 64 | make -j 65 | -------------------------------------------------------------------------------- /.github/workflows/silo_build.yml: -------------------------------------------------------------------------------- 1 | name: silo_build 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/workflows/silo_build.yml' 7 | - 'common/**' 8 | - 'silo/**' 9 | - 'third_party/**' 10 | pull_request: 11 | paths: 12 | - '.github/workflows/silo_build.yml' 13 | - 'common/**' 14 | - 'silo/**' 15 | 16 | jobs: 17 | Build: 18 | runs-on: ubuntu-latest 19 | timeout-minutes: 10 20 | 21 | steps: 22 | - id: Begin 23 | name: Begin 24 | run: | 25 | echo "Begin ${GITHUB_WORKFLOW}/${GITHUB_JOB}" 26 | 27 | - id: Checkout 28 | name: Checkout 29 | uses: actions/checkout@v2 30 | 31 | - id: Install_apt 32 | name: Install_apt 33 | run: | 34 | sudo apt update -y 35 | sudo apt-get install -y $(cat build_tools/ubuntu.deps) 36 | 37 | - id: Submodule_init_recursive 38 | name: Submodule_init_recursive 39 | run: | 40 | git submodule update --init --recursive 41 | 42 | - id: Build_third_party_masstree 43 | name: Build_third_party_masstree 44 | run: | 45 | ./build_tools/bootstrap.sh 46 | 47 | - id: Build_third_party_mimalloc 48 | name: Build_third_party_mimalloc 49 | run: | 50 | ./build_tools/bootstrap_mimalloc.sh 51 | 52 | - id: Build_third_party_googletest 53 | name: Build_third_party_googletest 54 | run: | 55 | ./build_tools/bootstrap_googletest.sh 56 | 57 | - id: Build_silo 58 | name: Build_silo 59 | run: | 60 | cd silo 61 | mkdir -p build 62 | cd build 63 | cmake -DCMAKE_BUILD_TYPE=Debug .. 64 | make -j 65 | -------------------------------------------------------------------------------- /.github/workflows/ss2pl_build.yml: -------------------------------------------------------------------------------- 1 | name: ss2pl_build 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/workflows/ss2pl_build.yml' 7 | - 'common/**' 8 | - 'ss2pl/**' 9 | - 'third_party/**' 10 | pull_request: 11 | paths: 12 | - '.github/workflows/ss2pl_build.yml' 13 | - 'common/**' 14 | - 'ss2pl/**' 15 | 16 | jobs: 17 | Build: 18 | runs-on: ubuntu-latest 19 | timeout-minutes: 10 20 | 21 | steps: 22 | - id: Begin 23 | name: Begin 24 | run: | 25 | echo "Begin ${GITHUB_WORKFLOW}/${GITHUB_JOB}" 26 | 27 | - id: Checkout 28 | name: Checkout 29 | uses: actions/checkout@v2 30 | 31 | - id: Install_apt 32 | name: Install_apt 33 | run: | 34 | sudo apt update -y 35 | sudo apt-get install -y $(cat build_tools/ubuntu.deps) 36 | 37 | - id: Submodule_init_recursive 38 | name: Submodule_init_recursive 39 | run: | 40 | git submodule update --init --recursive 41 | 42 | - id: Build_third_party_masstree 43 | name: Build_third_party_masstree 44 | run: | 45 | ./build_tools/bootstrap.sh 46 | 47 | - id: Build_third_party_mimalloc 48 | name: Build_third_party_mimalloc 49 | run: | 50 | ./build_tools/bootstrap_mimalloc.sh 51 | 52 | - id: Build_third_party_googletest 53 | name: Build_third_party_googletest 54 | run: | 55 | ./build_tools/bootstrap_googletest.sh 56 | 57 | - id: Build_ss2pl 58 | name: Build_ss2pl 59 | run: | 60 | cd ss2pl 61 | mkdir -p build 62 | cd build 63 | cmake -DCMAKE_BUILD_TYPE=Debug .. 64 | make -j 65 | 66 | - id: Test_ss2pl 67 | name: Test_ss2pl 68 | run: | 69 | cd ss2pl/build 70 | ctest --verbose --timeout 20 -j 100 -------------------------------------------------------------------------------- /.github/workflows/tictoc_build.yml: -------------------------------------------------------------------------------- 1 | name: tictoc_build 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/workflows/tictoc_build.yml' 7 | - 'common/**' 8 | - 'tictoc/**' 9 | - 'third_party/**' 10 | pull_request: 11 | paths: 12 | - '.github/workflows/tictoc_build.yml' 13 | - 'common/**' 14 | - 'tictoc/**' 15 | 16 | jobs: 17 | Build: 18 | runs-on: ubuntu-latest 19 | timeout-minutes: 10 20 | 21 | steps: 22 | - id: Begin 23 | name: Begin 24 | run: | 25 | echo "Begin ${GITHUB_WORKFLOW}/${GITHUB_JOB}" 26 | 27 | - id: Checkout 28 | name: Checkout 29 | uses: actions/checkout@v2 30 | 31 | - id: Install_apt 32 | name: Install_apt 33 | run: | 34 | sudo apt update -y 35 | sudo apt-get install -y $(cat build_tools/ubuntu.deps) 36 | 37 | - id: Submodule_init_recursive 38 | name: Submodule_init_recursive 39 | run: | 40 | git submodule update --init --recursive 41 | 42 | - id: Build_third_party_masstree 43 | name: Build_third_party_masstree 44 | run: | 45 | ./build_tools/bootstrap.sh 46 | 47 | - id: Build_third_party_mimalloc 48 | name: Build_third_party_mimalloc 49 | run: | 50 | ./build_tools/bootstrap_mimalloc.sh 51 | 52 | - id: Build_third_party_googletest 53 | name: Build_third_party_googletest 54 | run: | 55 | ./build_tools/bootstrap_googletest.sh 56 | 57 | - id: Build_tictoc 58 | name: Build_tictoc 59 | run: | 60 | cd tictoc 61 | mkdir -p build 62 | cd build 63 | cmake -DCMAKE_BUILD_TYPE=Debug .. 64 | make -j 65 | -------------------------------------------------------------------------------- /.github/workflows/tpcc_silo_build_and_ctest.yml: -------------------------------------------------------------------------------- 1 | name: tpcc_silo_build_and_ctest 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/workflows/tpcc_silo_build_and_ctest.yml' 7 | - 'common/**' 8 | - 'index/masstree_beta/masstree_beta_wrapper.cpp' 9 | - 'tpcc_silo/**' 10 | - 'third_party/**' 11 | pull_request: 12 | paths: 13 | - '.github/workflows/tpcc_silo_build_and_ctest.yml' 14 | - 'common/**' 15 | - 'index/masstree_beta/masstree_beta_wrapper.cpp' 16 | - 'tpcc_silo/**' 17 | 18 | jobs: 19 | Build: 20 | runs-on: ubuntu-latest 21 | timeout-minutes: 10 22 | 23 | steps: 24 | - id: Begin 25 | name: Begin 26 | run: | 27 | echo "Begin ${GITHUB_WORKFLOW}/${GITHUB_JOB}" 28 | 29 | - id: Checkout 30 | name: Checkout 31 | uses: actions/checkout@v2 32 | 33 | - id: Install_apt 34 | name: Install_apt 35 | run: | 36 | sudo apt update -y 37 | sudo apt-get install -y $(cat build_tools/ubuntu.deps) 38 | 39 | - id: Submodule_init_recursive 40 | name: Submodule_init_recursive 41 | run: | 42 | git submodule update --init --recursive 43 | 44 | - id: Build_third_party_masstree 45 | name: Build_third_party_masstree 46 | run: | 47 | ./build_tools/bootstrap.sh 48 | 49 | - id: Build_third_party_mimalloc 50 | name: Build_third_party_mimalloc 51 | run: | 52 | ./build_tools/bootstrap_mimalloc.sh 53 | 54 | - id: Build_third_party_googletest 55 | name: Build_third_party_googletest 56 | run: | 57 | ./build_tools/bootstrap_googletest.sh 58 | 59 | - id: Build_tpcc_silo 60 | name: Build_tpcc_silo 61 | run: | 62 | cd tpcc_silo 63 | mkdir -p build 64 | cd build 65 | cmake -DCMAKE_BUILD_TYPE=Debug .. 66 | make -j 67 | 68 | - id: Ctest_tpcc_silo 69 | name: Ctest_tpcc_silo 70 | continue-on-error: false 71 | env: 72 | GTEST_OUTPUT: xml 73 | ASAN_OPTIONS: detect_stack_use_after_return=true 74 | run: | 75 | cd tpcc_silo 76 | cd build 77 | ctest --verbose --timeout 100 -j 100 78 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.dat 2 | *.eps 3 | *.data 4 | *.old 5 | *.s 6 | 7 | 8 | # Created by https://www.gitignore.io/api/vim,c++,macos 9 | 10 | ### C++ ### 11 | # Prerequisites 12 | *.d 13 | 14 | # Compiled Object files 15 | *.slo 16 | *.lo 17 | *.o 18 | *.obj 19 | 20 | # Precompiled Headers 21 | *.gch 22 | *.pch 23 | 24 | # Compiled Dynamic libraries 25 | *.so 26 | *.dylib 27 | *.dll 28 | 29 | # Fortran module files 30 | *.mod 31 | *.smod 32 | 33 | # Compiled Static libraries 34 | *.lai 35 | *.la 36 | *.a 37 | *.lib 38 | 39 | # Executables 40 | *.exe 41 | *.out 42 | *.app 43 | 44 | ### macOS ### 45 | *.DS_Store 46 | .AppleDouble 47 | .LSOverride 48 | 49 | # Icon must end with two \r 50 | Icon 51 | 52 | # Thumbnails 53 | ._* 54 | 55 | # Files that might appear in the root of a volume 56 | .DocumentRevisions-V100 57 | .fseventsd 58 | .Spotlight-V100 59 | .TemporaryItems 60 | .Trashes 61 | .VolumeIcon.icns 62 | .com.apple.timemachine.donotpresent 63 | 64 | # Directories potentially created on remote AFP share 65 | .AppleDB 66 | .AppleDesktop 67 | Network Trash Folder 68 | Temporary Items 69 | .apdisk 70 | 71 | ### Vim ### 72 | # swap 73 | [._]*.s[a-v][a-z] 74 | [._]*.sw[a-p] 75 | [._]s[a-v][a-z] 76 | [._]sw[a-p] 77 | # session 78 | Session.vim 79 | # temporary 80 | .netrwhist 81 | *~ 82 | # auto-generated tag files 83 | tags 84 | 85 | # End of https://www.gitignore.io/api/vim,c++,macos 86 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "third_party/masstree"] 2 | path = third_party/masstree 3 | url = https://github.com/thawk105/masstree-beta.git 4 | [submodule "third_party/googletest"] 5 | path = third_party/googletest 6 | url = https://github.com/google/googletest.git 7 | [submodule "third_party/mimalloc"] 8 | path = third_party/mimalloc 9 | url = https://github.com/microsoft/mimalloc.git 10 | [submodule "third_party/spdlog"] 11 | path = third_party/spdlog 12 | url = https://github.com/gabime/spdlog.git 13 | -------------------------------------------------------------------------------- /build_tools/bootstrap.sh: -------------------------------------------------------------------------------- 1 | # prepare for masstree 2 | cd third_party/masstree 3 | ./bootstrap.sh 4 | ./configure --disable-assertions 5 | make clean 6 | make -j CXXFLAGS='-g -W -Wall -O3 -fPIC' 7 | ar cr libkohler_masstree_json.a json.o string.o straccum.o str.o msgpack.o clp.o kvrandom.o compiler.o memdebug.o kvthread.o misc.o 8 | ranlib libkohler_masstree_json.a 9 | 10 | -------------------------------------------------------------------------------- /build_tools/bootstrap_apt.sh: -------------------------------------------------------------------------------- 1 | sudo apt update -y 2 | sudo apt install -y libgflags-dev cmake cmake-curses-gui libboost-filesystem-dev 3 | -------------------------------------------------------------------------------- /build_tools/bootstrap_googletest.sh: -------------------------------------------------------------------------------- 1 | cd third_party/googletest 2 | mkdir -p build 3 | cd build 4 | cmake .. 5 | make -j 6 | -------------------------------------------------------------------------------- /build_tools/bootstrap_mimalloc.sh: -------------------------------------------------------------------------------- 1 | # prepare for mimalloc 2 | cd third_party/mimalloc 3 | mkdir -p out/release 4 | cd out/release 5 | cmake -DCMAKE_BUILD_TYPE=Release ../.. 6 | make clean all -j 7 | 8 | cd ../ 9 | mkdir debug 10 | cd debug 11 | cmake -DCMAKE_BUILD_TYPE=Debug ../.. 12 | make clean all -j 13 | 14 | cd ../ 15 | mkdir secure 16 | cd secure 17 | cmake -DMI_SECURE=ON ../.. 18 | make clean all -j 19 | 20 | # prepare for tbb 21 | cd ../../../tbb 22 | make clean all -j 23 | 24 | cd ../../ 25 | -------------------------------------------------------------------------------- /build_tools/bootstrap_tbb.sh: -------------------------------------------------------------------------------- 1 | # prepare for tbb 2 | cd third_party/tbb 3 | make -j 4 | cd ../../ 5 | -------------------------------------------------------------------------------- /build_tools/ubuntu.deps: -------------------------------------------------------------------------------- 1 | cmake cmake-curses-gui 2 | libboost-filesystem-dev 3 | libgflags-dev 4 | libgoogle-glog-dev 5 | -------------------------------------------------------------------------------- /cc_format/Makefile: -------------------------------------------------------------------------------- 1 | PROG1 = sv_format.exe 2 | SV_FORMAT_SRCS1 := sv_format.cc transaction.cc util.cc result.cc 3 | 4 | REL := ../common/ 5 | include $(REL)Makefile 6 | SV_FORMAT_ALLSRC = $(SV_FORMAT_SRCS1) $(SRCS2) $(wildcard include/*.hh) 7 | 8 | # start of initialization of some parameters. 9 | ADD_ANALYSIS=1 10 | BACK_OFF=0 11 | KEY_SIZE=8 12 | MASSTREE_USE=1 13 | NO_WAIT_LOCKING_IN_VALIDATION=0 14 | NO_WAIT_OF_TICTOC=1 15 | PARTITION_TABLE=0 16 | PROCEDURE_SORT=0 17 | SLEEP_READ_PHASE=0 # of tics 18 | VAL_SIZE=4 19 | WAL=0 20 | # end of initialization 21 | 22 | CC = g++ 23 | CFLAGS = -c -pipe -g -O3 -std=c++17 -march=native \ 24 | -Wall -Wextra -Wdangling-else -Wchkp -Winvalid-memory-model \ 25 | -D$(shell uname) \ 26 | -D$(shell hostname) \ 27 | -DKEY_SIZE=$(KEY_SIZE) \ 28 | -DVAL_SIZE=$(VAL_SIZE) \ 29 | -DADD_ANALYSIS=$(ADD_ANALYSIS) \ 30 | -DBACK_OFF=$(BACK_OFF) \ 31 | -DMASSTREE_USE=$(MASSTREE_USE) \ 32 | -DNO_WAIT_LOCKING_IN_VALIDATION=$(NO_WAIT_LOCKING_IN_VALIDATION) \ 33 | -DNO_WAIT_OF_TICTOC=$(NO_WAIT_OF_TICTOC) \ 34 | -DPARTITION_TABLE=$(PARTITION_TABLE) \ 35 | -DPROCEDURE_SORT=$(PROCEDURE_SORT) \ 36 | -DSLEEP_READ_PHASE=$(SLEEP_READ_PHASE) \ 37 | -DWAL=$(WAL) \ 38 | 39 | INCLUDE = -I/usr/include \ 40 | -I../third_party/ \ 41 | 42 | LDLIBS = -lpthread -lboost_filesystem -lboost_system -lgflags -lglog 43 | 44 | OBJS1 = $(SV_FORMAT_SRCS1:.cc=.o) 45 | 46 | all: $(PROG1) 47 | 48 | include ../include/MakefileForMasstreeUse 49 | $(PROG1) : $(OBJS1) $(MASSOBJ) 50 | $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) $(INCLUDE) 51 | 52 | .cc.o: 53 | $(CC) $(CFLAGS) -c $< -o $@ 54 | 55 | format: 56 | clang-format -i -verbose -style=Google $(SV_FORMAT_ALLSRC) 57 | 58 | clean: 59 | rm -f *~ *.o *.exe *.stackdump 60 | rm -f ../common/*~ ../common/*.o ../common/*.exe ../common/*.stackdump 61 | rm -rf .deps 62 | -------------------------------------------------------------------------------- /cc_format/README.md: -------------------------------------------------------------------------------- 1 | # Single version concurrency control format 2 | - This is the format for adding single-version concurrency control. 3 | 4 | ## Where to edit 5 | ### Source files 6 | - result.cc 7 | - L12-14 : Declare the variables with appropriate names. 8 | - sv_format.cc
9 | Set an appropriate file name. 10 | - L48-66 : Edit it appropriately when you enable log persistence. 11 | - L106-133 : Define a single transaction workflow. 12 | - util.cc
13 | - L105-117 : Set initial value of record member appropriately. 14 | - leaderWork function : Define the job of a leader thread. 15 | - Makefile
16 | - Edit the file name "sv_format / SV_FORMAT" appropriately. 17 | - L9-37 : Define your preprocessor definition properly to determine the configuration. 18 | - Please remove the libraries and options that cannot be used in the experimental environment. 19 | - transaction.cc
20 | - Define the tbegin/validationPhase/abort/writePhase/read/write function properly. 21 | Delete unnecessary functions and add necessary functions to the transaction workflow. 22 | ### Header files 23 | - include/common.hh
24 | - Define the global variables and workload configuration variables that are necessary for Concurrency Control. 25 | - include/log.hh
26 | - Define the members of LogRecord class as appropriate. Please modify accordingly. 27 | - include/result.hh
28 | - Change the name of the variable appropriately. 29 | - include/silo_op_element.hh
30 | - Change the file name appropriately. 31 | - Change the members of ReadElement/WriteElement appropriately. And make corrections accordingly. 32 | - include/transaction.hh
33 | - Modify the members of TransactionStatus class appropriately as necessary. 34 | - TxnExecutor class is information that should be held by the worker thread. Please add any information necessary for concurrency control to the class members. 35 | - include/tuple.hh
36 | - Declare the metadata to be stored in the record header in the Tuple class. 37 | - attention : To improve the performance, no keys are stored. When a one-dimensional array is used as a DB table, the index position is the key. If you use masstree, the key-value is stored in the leaf node of masstree and the value is a pointer to the record, so there is no need to store the key. 38 | - include/util.hh
39 | - Edit it appropriately in conjunction with util.cc. 40 | -------------------------------------------------------------------------------- /cc_format/include/atomic_tool.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.hh" 4 | 5 | #include "../../include/inline.hh" 6 | 7 | INLINE uint64_t atomicLoadGE(); 8 | 9 | INLINE void atomicAddGE() { 10 | uint64_t expected, desired; 11 | 12 | expected = atomicLoadGE(); 13 | for (;;) { 14 | desired = expected + 1; 15 | if (__atomic_compare_exchange_n(&(GlobalEpoch.obj_), &expected, desired, 16 | false, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) 17 | break; 18 | } 19 | } 20 | 21 | INLINE uint64_t atomicLoadGE() { 22 | uint64_t_64byte result = 23 | __atomic_load_n(&(GlobalEpoch.obj_), __ATOMIC_ACQUIRE); 24 | return result.obj_; 25 | } 26 | 27 | INLINE void atomicStoreThLocalEpoch(unsigned int thid, uint64_t newval) { 28 | __atomic_store_n(&(ThLocalEpoch[thid].obj_), newval, __ATOMIC_RELEASE); 29 | } 30 | -------------------------------------------------------------------------------- /cc_format/include/common.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "tuple.hh" 8 | 9 | #include "../../include/cache_line_size.hh" 10 | #include "../../include/int64byte.hh" 11 | #include "../../include/masstree_wrapper.hh" 12 | 13 | #include "gflags/gflags.h" 14 | #include "glog/logging.h" 15 | 16 | #ifdef GLOBAL_VALUE_DEFINE 17 | #define GLOBAL 18 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte GlobalEpoch(1); 19 | #if MASSTREE_USE 20 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 21 | #endif 22 | #else 23 | #define GLOBAL extern 24 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte GlobalEpoch; 25 | #if MASSTREE_USE 26 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 27 | #endif 28 | #endif 29 | 30 | #ifdef GLOBAL_VALUE_DEFINE 31 | DEFINE_uint64(clocks_per_us, 2100, 32 | "CPU_MHz. Use this info for measuring time."); 33 | DEFINE_uint64(epoch_time, 40, "Epoch interval[msec]."); 34 | DEFINE_uint64(extime, 3, "Execution time[sec]."); 35 | DEFINE_uint64(max_ope, 10, 36 | "Total number of operations per single transaction."); 37 | DEFINE_bool(rmw, false, 38 | "True means read modify write, false means blind write."); 39 | DEFINE_uint64(rratio, 50, "read ratio of single transaction."); 40 | DEFINE_uint64(thread_num, 10, "Total number of worker threads."); 41 | DEFINE_uint64(tuple_num, 1000000, "Total number of records."); 42 | DEFINE_bool(ycsb, true, 43 | "True uses zipf_skew, false uses faster random generator."); 44 | DEFINE_double(zipf_skew, 0, "zipf skew. 0 ~ 0.999..."); 45 | #else 46 | DECLARE_uint64(clocks_per_us); 47 | DECLARE_uint64(epoch_time); 48 | DECLARE_uint64(extime); 49 | DECLARE_uint64(max_ope); 50 | DECLARE_bool(rmw); 51 | DECLARE_uint64(rratio); 52 | DECLARE_uint64(thread_num); 53 | DECLARE_uint64(tuple_num); 54 | DECLARE_bool(ycsb); 55 | DECLARE_double(zipf_skew); 56 | #endif 57 | 58 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte *ThLocalEpoch; 59 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte *CTIDW; 60 | 61 | alignas(CACHE_LINE_SIZE) GLOBAL Tuple *Table; 62 | -------------------------------------------------------------------------------- /cc_format/include/log.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | class LogHeader { 9 | public: 10 | int chkSum_ = 0; 11 | unsigned int logRecNum_ = 0; 12 | const std::size_t len_val_ = VAL_SIZE; 13 | 14 | void init() { 15 | chkSum_ = 0; 16 | logRecNum_ = 0; 17 | } 18 | 19 | void convertChkSumIntoComplementOnTwo() { 20 | chkSum_ ^= 0xffffffff; 21 | ++chkSum_; 22 | } 23 | }; 24 | 25 | class LogRecord { 26 | public: 27 | uint64_t tid_; 28 | unsigned int key_; 29 | char val_[VAL_SIZE]; 30 | 31 | LogRecord() : tid_(0), key_(0) {} 32 | 33 | LogRecord(uint64_t tid, unsigned int key, char *val) : tid_(tid), key_(key) { 34 | memcpy(this->val_, val, VAL_SIZE); 35 | } 36 | 37 | int computeChkSum() { 38 | // compute checksum 39 | int chkSum = 0; 40 | int *itr = (int *)this; 41 | for (unsigned int i = 0; i < sizeof(LogRecord) / sizeof(int); ++i) { 42 | chkSum += (*itr); 43 | ++itr; 44 | } 45 | 46 | return chkSum; 47 | } 48 | }; 49 | 50 | class LogPackage { 51 | public: 52 | LogHeader header_; 53 | std::unique_ptr log_records_; 54 | }; 55 | -------------------------------------------------------------------------------- /cc_format/include/result.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/result.hh" 6 | 7 | extern std::vector SiloResult; 8 | 9 | extern void initResult(); 10 | -------------------------------------------------------------------------------- /cc_format/include/silo_op_element.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../include/op_element.hh" 4 | 5 | template 6 | class ReadElement : public OpElement { 7 | public: 8 | using OpElement::OpElement; 9 | 10 | Tidword tidword_; 11 | char val_[VAL_SIZE]; 12 | 13 | ReadElement(uint64_t key, T* rcdptr, char* val, Tidword tidword) 14 | : OpElement::OpElement(key, rcdptr) { 15 | tidword_.obj_ = tidword.obj_; 16 | memcpy(this->val_, val, VAL_SIZE); 17 | } 18 | 19 | bool operator<(const ReadElement& right) const { 20 | return this->key_ < right.key_; 21 | } 22 | }; 23 | 24 | template 25 | class WriteElement : public OpElement { 26 | public: 27 | using OpElement::OpElement; 28 | 29 | WriteElement(uint64_t key, T* rcdptr) 30 | : OpElement::OpElement(key, rcdptr) {} 31 | 32 | bool operator<(const WriteElement& right) const { 33 | return this->key_ < right.key_; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /cc_format/include/tuple.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "../../include/cache_line_size.hh" 10 | 11 | class Tuple { 12 | public: 13 | char val_[VAL_SIZE]; 14 | }; 15 | -------------------------------------------------------------------------------- /cc_format/include/util.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern void chkArg(); 4 | 5 | extern bool chkEpochLoaded(); 6 | 7 | extern void displayDB(); 8 | 9 | extern void displayParameter(); 10 | 11 | extern void genLogFile(std::string &logpath, const int thid); 12 | 13 | extern void leaderWork(uint64_t &epoch_timer_start, uint64_t &epoch_timer_stop); 14 | 15 | extern void makeDB(); 16 | 17 | extern void partTableInit([[maybe_unused]] size_t thid, uint64_t start, 18 | uint64_t end); 19 | 20 | extern void ShowOptParameters(); 21 | -------------------------------------------------------------------------------- /cc_format/result.cc: -------------------------------------------------------------------------------- 1 | #include "include/result.hh" 2 | #include "include/common.hh" 3 | 4 | #include "../include/cache_line_size.hh" 5 | #include "../include/result.hh" 6 | 7 | using namespace std; 8 | 9 | /** 10 | * Please declare it with an appropriate name. 11 | */ 12 | alignas(CACHE_LINE_SIZE) std::vector SiloResult; 13 | 14 | void initResult() { SiloResult.resize(FLAGS_thread_num); } 15 | -------------------------------------------------------------------------------- /cicada/include/cicada_op_element.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "version.hh" 4 | 5 | template 6 | class ReadElement : public OpElement { 7 | public: 8 | using OpElement::OpElement; 9 | 10 | Version *later_ver_, *ver_; 11 | 12 | ReadElement(uint64_t key, T *rcdptr, Version *later_ver, Version *ver) 13 | : OpElement::OpElement(key, rcdptr) { 14 | later_ver_ = later_ver; 15 | ver_ = ver; 16 | } 17 | 18 | bool operator<(const ReadElement &right) const { 19 | return this->key_ < right.key_; 20 | } 21 | }; 22 | 23 | template 24 | class WriteElement : public OpElement { 25 | public: 26 | using OpElement::OpElement; 27 | 28 | Version *later_ver_, *new_ver_; 29 | bool rmw_; 30 | bool finish_version_install_; 31 | 32 | WriteElement(uint64_t key, T *rcdptr, Version *later_ver, Version *new_ver, 33 | bool rmw) 34 | : OpElement::OpElement(key, rcdptr) { 35 | later_ver_ = later_ver; 36 | new_ver_ = new_ver; 37 | rmw_ = rmw; 38 | finish_version_install_ = false; 39 | } 40 | 41 | bool operator<(const WriteElement &right) const { 42 | return this->key_ < right.key_; 43 | } 44 | }; 45 | 46 | template 47 | class GCElement : public OpElement { 48 | public: 49 | using OpElement::OpElement; 50 | 51 | Version *ver_; 52 | uint64_t wts_; 53 | 54 | GCElement() : ver_(nullptr), wts_(0) { this->key_ = 0; } 55 | 56 | GCElement(uint64_t key, T *rcdptr, Version *ver, uint64_t wts) 57 | : OpElement::OpElement(key, rcdptr) { 58 | this->ver_ = ver; 59 | this->wts_ = wts; 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /cicada/include/lock.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class RWLock { 9 | public: 10 | std::atomic counter; 11 | // counter == -1, write locked; 12 | // counter == 0, not locked; 13 | // counter > 0, there are $counter readers who acquires read-lock. 14 | 15 | RWLock() { counter.store(0, std::memory_order_release); } 16 | 17 | // Read lock 18 | void r_lock() { 19 | int expected, desired; 20 | for (;;) { 21 | expected = counter.load(std::memory_order_acquire); 22 | RETRY_R_LOCK: 23 | if (expected != -1) 24 | desired = expected + 1; 25 | else { 26 | continue; 27 | } 28 | if (counter.compare_exchange_strong( 29 | expected, desired, memory_order_acq_rel, memory_order_acquire)) 30 | break; 31 | else 32 | goto RETRY_R_LOCK; 33 | } 34 | } 35 | 36 | void r_unlock() { counter--; } 37 | 38 | // Write lock 39 | void w_lock() { 40 | int expected; 41 | for (;;) { 42 | expected = counter.load(memory_order_acquire); 43 | RETRY_W_LOCK: 44 | if (expected != 0) continue; 45 | if (counter.compare_exchange_strong(expected, -1, memory_order_acq_rel, 46 | memory_order_acquire)) 47 | break; 48 | else 49 | goto RETRY_W_LOCK; 50 | } 51 | } 52 | 53 | void w_unlock() { counter++; } 54 | 55 | // Upgrae, read -> write 56 | void upgrade() { 57 | int one = 1; 58 | while (!counter.compare_exchange_strong(one, -1, memory_order_acq_rel, 59 | memory_order_acquire)) { 60 | } 61 | } 62 | }; 63 | -------------------------------------------------------------------------------- /cicada/include/result.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/result.hh" 6 | 7 | extern std::vector CicadaResult; 8 | 9 | extern void initResult(); 10 | -------------------------------------------------------------------------------- /cicada/include/time_stamp.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../include/cache_line_size.hh" 4 | #include "../../include/tsc.hh" 5 | 6 | class TimeStamp { 7 | public: 8 | alignas(CACHE_LINE_SIZE) uint64_t ts_ = 0; 9 | uint64_t localClock_ = 0; 10 | uint64_t clockBoost_ = 0; 11 | uint8_t thid_; 12 | 13 | TimeStamp() {} 14 | 15 | inline uint64_t get_ts() { return ts_; } 16 | 17 | inline void set_ts(uint64_t &ts) { this->ts_ = ts; } 18 | 19 | inline void set_clockBoost(unsigned int CLOCK_PER_US) { 20 | // set 0 or some value equivalent to 1 us. 21 | clockBoost_ = CLOCK_PER_US; 22 | } 23 | 24 | inline void generateTimeStampFirst(uint8_t tid) { 25 | localClock_ = rdtscp(); 26 | ts_ = (localClock_ << (sizeof(tid) * 8)) | tid; 27 | thid_ = tid; 28 | } 29 | 30 | inline void generateTimeStamp(uint8_t tid) { 31 | uint64_t tmp = rdtscp(); 32 | uint64_t elapsedTime = tmp - localClock_; 33 | if (tmp < localClock_) elapsedTime = 0; 34 | 35 | // current local clock + elapsed time + clockBoost 36 | localClock_ += elapsedTime; 37 | localClock_ += clockBoost_; 38 | 39 | ts_ = (localClock_ << (sizeof(tid) * 8)) | tid; 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /cicada/include/tuple.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "../../include/cache_line_size.hh" 7 | 8 | #include "version.hh" 9 | 10 | using namespace std; 11 | 12 | class Tuple { 13 | public: 14 | alignas(CACHE_LINE_SIZE) 15 | #if INLINE_VERSION_OPT 16 | Version inline_ver_; 17 | #endif 18 | atomic latest_; 19 | atomic min_wts_; 20 | atomic continuing_commit_; 21 | atomic gc_lock_; 22 | 23 | Tuple() : latest_(nullptr), gc_lock_(0) {} 24 | 25 | Version *ldAcqLatest() { return latest_.load(std::memory_order_acquire); } 26 | 27 | bool getGCRight(uint8_t thid) { 28 | uint8_t expected, desired(thid); 29 | expected = this->gc_lock_.load(std::memory_order_acquire); 30 | for (;;) { 31 | if (expected != 0) return false; 32 | if (this->gc_lock_.compare_exchange_strong(expected, desired, 33 | std::memory_order_acq_rel, 34 | std::memory_order_acquire)) 35 | return true; 36 | } 37 | } 38 | 39 | void returnGCRight() { this->gc_lock_.store(0, std::memory_order_release); } 40 | 41 | #if INLINE_VERSION_OPT 42 | // inline 43 | bool getInlineVersionRight() { 44 | VersionStatus expected, desired(VersionStatus::pending); 45 | expected = this->inline_ver_.status_.load(std::memory_order_acquire); 46 | for (;;) { 47 | if (expected != VersionStatus::unused) return false; 48 | if (this->inline_ver_.status_.compare_exchange_strong( 49 | expected, desired, std::memory_order_acq_rel, 50 | std::memory_order_acquire)) 51 | return true; 52 | } 53 | } 54 | 55 | void returnInlineVersionRight() { 56 | this->inline_ver_.status_.store(VersionStatus::unused, 57 | std::memory_order_release); 58 | } 59 | #endif 60 | }; 61 | -------------------------------------------------------------------------------- /cicada/include/util.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/backoff.hh" 6 | 7 | extern void chkArg(); 8 | 9 | extern void deleteDB(); 10 | 11 | [[maybe_unused]] extern void displayDB(); 12 | 13 | [[maybe_unused]] extern void displayMinRts(); 14 | 15 | [[maybe_unused]] extern void displayMinWts(); 16 | 17 | extern void displayParameter(); 18 | 19 | [[maybe_unused]] extern void displaySLogSet(); 20 | 21 | [[maybe_unused]] extern void displayThreadWtsArray(); 22 | 23 | [[maybe_unused]] extern void displayThreadRtsArray(); 24 | 25 | extern void leaderWork([[maybe_unused]] Backoff &backoff); 26 | 27 | extern void makeDB(uint64_t *initial_wts); 28 | 29 | extern void partTableDelete([[maybe_unused]] size_t thid, uint64_t start, 30 | uint64_t end); 31 | 32 | extern void partTableInit([[maybe_unused]] size_t thid, uint64_t initts, 33 | uint64_t start, uint64_t end); 34 | 35 | extern void ShowOptParameters(); 36 | -------------------------------------------------------------------------------- /cicada/result.cc: -------------------------------------------------------------------------------- 1 | #include "include/result.hh" 2 | #include "include/common.hh" 3 | 4 | #include "../include/cache_line_size.hh" 5 | #include "../include/result.hh" 6 | 7 | using namespace std; 8 | 9 | alignas(CACHE_LINE_SIZE) std::vector CicadaResult; 10 | 11 | void initResult() { CicadaResult.resize(FLAGS_thread_num); } 12 | -------------------------------------------------------------------------------- /cicada/script/ycsbA-xgcidbsize-cache.sh: -------------------------------------------------------------------------------- 1 | #ycsbA-xgcidbsize.sh(cicada) 2 | maxope=10 3 | thread=24 4 | rratio=50 5 | skew=0 6 | ycsb=ON 7 | wal=OFF 8 | group_commit=OFF 9 | cpu_mhz=2400 10 | io_time_ns=5 11 | group_commit_timeout_us=2 12 | lock_release=E 13 | extime=1 14 | epoch=1 15 | 16 | result=result_cicada_ycsbA_tuple100-10m_gci1us-100ms_cache-miss.dat 17 | rm $result 18 | echo "#tuple num, gci, throughput, min, max" >> $result 19 | for ((tuple=100; tuple<=10000000; tuple*=10)) 20 | do 21 | for ((gci=1; gci<=100000; gci*=10)) 22 | do 23 | sum=0 24 | echo "./cicada.exe $tuple $maxope $thread $rratio $skew $ycsb $wal $group_commit $cpu_mhz $io_time_ns $group_commit_timeout_us $lock_release $gci $extime" 25 | echo "$tuple $epoch" 26 | 27 | max=0 28 | min=0 29 | for ((i = 1; i <= epoch; ++i)) 30 | do 31 | perf stat -e cache-misses,cache-references -o cicada-cache-ana.txt ./cicada.exe $tuple $maxope $thread $rratio $skew $ycsb $wal $group_commit $cpu_mhz $io_time_ns $group_commit_timeout_us $lock_release $gci $extime 32 | tmp=`grep cache-misses ./cicada-cache-ana.txt | awk '{print $4}'` 33 | sum=`echo "$sum + $tmp" | bc -l` 34 | echo "sum: $sum, tmp: $tmp" 35 | 36 | if test $i -eq 1 ; then 37 | max=$tmp 38 | min=$tmp 39 | fi 40 | 41 | flag=`echo "$tmp > $max" | bc -l` 42 | if test $flag -eq 1 ; then 43 | max=$tmp 44 | fi 45 | flag=`echo "$tmp < $min" | bc -l` 46 | if test $flag -eq 1 ; then 47 | min=$tmp 48 | fi 49 | done 50 | avg=`echo "$sum / $epoch" | bc -l` 51 | echo "sum: $sum, epoch: $epoch" 52 | echo "avg $avg" 53 | echo "max: $max" 54 | echo "min: $min" 55 | echo "$tuple $gci $avg $min $max" >> $result 56 | done 57 | echo "" >> $result 58 | done 59 | -------------------------------------------------------------------------------- /cicada/script/ycsbA-xrs-cache.sh: -------------------------------------------------------------------------------- 1 | #ycsbA-xrs-cache.sh(cicada) 2 | maxope=10 3 | thread=24 4 | rratio=50 5 | skew=0 6 | ycsb=ON 7 | wal=OFF 8 | group_commit=OFF 9 | cpu_mhz=2400 10 | io_time_ns=5 11 | group_commit_timeout_us=2 12 | lock_release=E 13 | extime=1 14 | epoch=1 15 | 16 | result=result_cicada_ycsbA_tuple100-10m_cachemiss.dat 17 | rm $result 18 | echo "#tuple num, cache-misses, min, max" >> $result 19 | echo "#./cicada.exe tuple $maxope $thread $rratio $skew $ycsb $wal $group_commit $cpu_mhz $io_time_ns $group_commit_timeout_us $lock_release $extime" >> $result 20 | 21 | for ((tuple=100; tuple<=10000000; tuple*=10)) 22 | do 23 | sum=0 24 | echo "./cicada.exe $tuple $maxope $thread $rratio $skew $ycsb $wal $group_commit $cpu_mhz $io_time_ns $group_commit_timeout_us $lock_release $extime" 25 | echo "$tuple $epoch" 26 | 27 | max=0 28 | min=0 29 | for ((i = 1; i <= epoch; ++i)) 30 | do 31 | perf stat -e cache-misses,cache-references -o cicada-cache-ana.txt ./cicada.exe $tuple $maxope $thread $rratio $skew $ycsb $wal $group_commit $cpu_mhz $io_time_ns $group_commit_timeout_us $lock_release $extime 32 | tmp=`grep cache-misses ./cicada-cache-ana.txt | awk '{print $4}'` 33 | sum=`echo "$sum + $tmp" | bc -l` 34 | echo "sum: $sum, tmp: $tmp" 35 | 36 | if test $i -eq 1 ; then 37 | max=$tmp 38 | min=$tmp 39 | fi 40 | 41 | flag=`echo "$tmp > $max" | bc -l` 42 | if test $flag -eq 1 ; then 43 | max=$tmp 44 | fi 45 | flag=`echo "$tmp < $min" | bc -l` 46 | if test $flag -eq 1 ; then 47 | min=$tmp 48 | fi 49 | done 50 | avg=`echo "$sum / $epoch" | bc -l` 51 | echo "sum: $sum, epoch: $epoch" 52 | echo "avg $avg" 53 | echo "max: $max" 54 | echo "min: $min" 55 | echo "$tuple $avg $min $max" >> $result 56 | done 57 | 58 | -------------------------------------------------------------------------------- /cicada/testzip.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "include/debug.hpp" 7 | #include "include/random.hpp" 8 | #include "include/tsc.hpp" 9 | #include "include/zipf.hpp" 10 | 11 | using std::cout, std::endl; 12 | 13 | int 14 | main() { 15 | pid_t pid = syscall(SYS_gettid); 16 | cpu_set_t cpu_set; 17 | 18 | CPU_ZERO(&cpu_set); 19 | CPU_SET(0, &cpu_set); 20 | 21 | if (sched_setaffinity(pid, sizeof(cpu_set_t), &cpu_set) != 0) 22 | ERR; 23 | 24 | Xoroshiro128Plus rnd; 25 | rnd.init(); 26 | uint64_t start, stop, tmp; 27 | 28 | FastZipf zipf(&rnd, 0, 10); 29 | 30 | // warm up 31 | for (int i = 0; i < 100; ++i) 32 | start = rnd.next(); 33 | 34 | start = rdtscp(); 35 | for (int i = 0; i < 1000000; ++i) 36 | rnd.next(); 37 | stop = rdtscp(); 38 | 39 | cout << "xoroshiro : " << (stop - start) / 1000000 << endl; 40 | 41 | start = rdtscp(); 42 | zipf(); 43 | stop = rdtscp(); 44 | 45 | cout << "zipf() : " << stop - start << endl; 46 | 47 | //for (uint i = 0; i < 10; ++i) 48 | // cout << zipf() << endl; 49 | 50 | int ary[10] = {}; 51 | for (uint i = 0; i < 10000; ++i) 52 | ++ary[zipf()]; 53 | 54 | for (uint i = 0; i < 10; ++i) 55 | cout << "ary[" << i << "] = " << ary[i] << endl; 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /cmake/CompileOptions.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_CXX_STANDARD 17) 2 | set(CMAKE_CXX_EXTENSIONS OFF) 3 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 4 | 5 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer") 6 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fno-omit-frame-pointer") 7 | 8 | set(sanitizers "address") 9 | if (ENABLE_UB_SANITIZER) 10 | # NOTE: UB check requires instrumented libstdc++ 11 | set(sanitizers "${sanitizers},undefined") 12 | endif () 13 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 14 | # do nothing for gcc 15 | elseif (CMAKE_CXX_COMPILER_ID MATCHES "^(Clang|AppleClang)$") 16 | set(sanitizers "${sanitizers},nullability") 17 | else () 18 | message(FATAL_ERROR "unsupported compiler ${CMAKE_CXX_COMPILER_ID}") 19 | endif () 20 | 21 | if (ENABLE_SANITIZER) 22 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=${sanitizers}") 23 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-sanitize=alignment") 24 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-sanitize-recover=${sanitizers}") 25 | endif () 26 | if (ENABLE_COVERAGE) 27 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} --coverage") 28 | endif () 29 | 30 | function(set_compile_options target_name) 31 | target_compile_options(${target_name} 32 | PRIVATE -Wall -Wextra -Werror) 33 | endfunction(set_compile_options) 34 | -------------------------------------------------------------------------------- /cmake/Findgflags.cmake: -------------------------------------------------------------------------------- 1 | if(TARGET gflags::gflags) 2 | return() 3 | endif() 4 | 5 | find_library(gflags_LIBRARY_FILE NAMES gflags) 6 | find_path(gflags_INCLUDE_DIR NAMES gflags/gflags.h) 7 | 8 | include(FindPackageHandleStandardArgs) 9 | find_package_handle_standard_args(gflags DEFAULT_MSG 10 | gflags_LIBRARY_FILE 11 | gflags_INCLUDE_DIR) 12 | 13 | if(gflags_LIBRARY_FILE AND gflags_INCLUDE_DIR) 14 | set(gflags_FOUND ON) 15 | add_library(gflags::gflags SHARED IMPORTED) 16 | set_target_properties(gflags::gflags PROPERTIES 17 | IMPORTED_LOCATION "${gflags_LIBRARY_FILE}" 18 | INTERFACE_INCLUDE_DIRECTORIES "${gflags_INCLUDE_DIR}") 19 | else() 20 | set(gflags_FOUND OFF) 21 | endif() 22 | 23 | unset(gflags_LIBRARY_FILE CACHE) 24 | unset(gflags_INCLUDE_DIR CACHE) 25 | -------------------------------------------------------------------------------- /cmake/Findglog.cmake: -------------------------------------------------------------------------------- 1 | if(TARGET glog::glog) 2 | return() 3 | endif() 4 | 5 | find_library(glog_LIBRARY_FILE NAMES glog) 6 | find_path(glog_INCLUDE_DIR NAMES glog/logging.h) 7 | 8 | include(FindPackageHandleStandardArgs) 9 | find_package_handle_standard_args(glog DEFAULT_MSG 10 | glog_LIBRARY_FILE 11 | glog_INCLUDE_DIR) 12 | 13 | if(glog_LIBRARY_FILE AND glog_INCLUDE_DIR) 14 | set(glog_FOUND ON) 15 | add_library(glog::glog SHARED IMPORTED) 16 | set_target_properties(glog::glog PROPERTIES 17 | IMPORTED_LOCATION "${glog_LIBRARY_FILE}" 18 | INTERFACE_INCLUDE_DIRECTORIES "${glog_INCLUDE_DIR}") 19 | else() 20 | set(glog_FOUND OFF) 21 | endif() 22 | 23 | unset(glog_LIBRARY_FILE CACHE) 24 | unset(glog_INCLUDE_DIR CACHE) 25 | -------------------------------------------------------------------------------- /common/Makefile: -------------------------------------------------------------------------------- 1 | 2 | SV_FORMAT_SRCS1+=\ 3 | $(REL)result.cc\ 4 | $(REL)util.cc\ 5 | 6 | ###### 7 | INST_SRCS1+=\ 8 | $(REL)util.cc 9 | 10 | INST_SRCS2+=\ 11 | $(REL)util.cc 12 | 13 | INST_SRCS3+=\ 14 | $(REL)util.cc 15 | 16 | INST_SRCS4+=\ 17 | $(REL)util.cc 18 | ###### 19 | -------------------------------------------------------------------------------- /common/util.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "./../include/atomic_wrapper.hh" 3 | #include "./../include/util.hh" 4 | 5 | [[maybe_unused]] bool chkSpan(struct timeval &start, struct timeval &stop, long threshold) { 6 | long diff = 0; 7 | diff += (stop.tv_sec - start.tv_sec) * 1000 * 1000 + 8 | (stop.tv_usec - start.tv_usec); 9 | if (diff > threshold) { 10 | return true; 11 | } 12 | return false; 13 | } 14 | 15 | size_t decideParallelBuildNumber(size_t tuple_num) { 16 | // if table size is very small, it builds by single thread. 17 | if (tuple_num < 1000) return 1; 18 | 19 | // else 20 | for (size_t i = std::thread::hardware_concurrency(); i > 0; --i) { 21 | if (tuple_num % i == 0) { 22 | return i; 23 | } 24 | if (i == 1) ERR; 25 | } 26 | 27 | return 0; 28 | } 29 | 30 | void displayProcedureVector(std::vector &pro) { 31 | printf("--------------------\n"); 32 | size_t index = 0; 33 | for (auto &&elem : pro) { 34 | printf( 35 | "-----\n" 36 | "op_num\t: %zu\n" 37 | "key\t: %zu\n" 38 | "r/w\t: %d\n", 39 | index, elem.key_, (int) (elem.ope_)); 40 | ++index; 41 | } 42 | printf("--------------------\n"); 43 | } 44 | 45 | void displayRusageRUMaxrss() { 46 | struct rusage r{}; 47 | if (getrusage(RUSAGE_SELF, &r) != 0) ERR; 48 | printf("maxrss:\t%ld kB\n", r.ru_maxrss); 49 | } 50 | 51 | void readyAndWaitForReadyOfAllThread(std::atomic &running, 52 | const size_t thnm) { 53 | running++; 54 | while (running.load(std::memory_order_acquire) != thnm) _mm_pause(); 55 | } 56 | 57 | void waitForReadyOfAllThread(std::atomic &running, const size_t thnm) { 58 | while (running.load(std::memory_order_acquire) != thnm) _mm_pause(); 59 | } 60 | 61 | bool isReady(const std::vector &readys) { 62 | for (const char &b : readys) { 63 | if (!loadAcquire(b)) return false; 64 | } 65 | return true; 66 | } 67 | 68 | void waitForReady(const std::vector &readys) { 69 | while (!isReady(readys)) { 70 | _mm_pause(); 71 | } 72 | } 73 | 74 | void sleepMs(size_t ms) { 75 | std::this_thread::sleep_for(std::chrono::milliseconds(ms)); 76 | } 77 | -------------------------------------------------------------------------------- /ermia/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(ccbench_ermia 4 | VERSION 0.0.1 5 | DESCRIPTION "ermia of ccbench" 6 | LANGUAGES CXX) 7 | 8 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../cmake") 9 | 10 | option(ENABLE_SANITIZER "enable sanitizer on debug build" ON) 11 | option(ENABLE_UB_SANITIZER "enable undefined behavior sanitizer on debug build" OFF) 12 | option(ENABLE_COVERAGE "enable coverage on debug build" OFF) 13 | 14 | find_package(Doxygen) 15 | find_package(Threads REQUIRED) 16 | find_package(gflags REQUIRED) 17 | find_package(glog REQUIRED) 18 | find_package(Boost 19 | COMPONENTS filesystem) 20 | 21 | include(GNUInstallDirs) 22 | include(CMakePackageConfigHelpers) 23 | include(CompileOptions) 24 | 25 | file(GLOB ERMIA_SOURCES 26 | "../common/result.cc" 27 | "../common/util.cc" 28 | "ermia.cc" 29 | "garbage_collection.cc" 30 | "result.cc" 31 | "transaction.cc" 32 | "util.cc" 33 | ) 34 | 35 | add_executable(ermia.exe ${ERMIA_SOURCES}) 36 | 37 | target_link_libraries(ermia.exe 38 | Boost::filesystem 39 | gflags::gflags 40 | ${PROJECT_SOURCE_DIR}/../third_party/mimalloc/out/release/libmimalloc.a 41 | ${PROJECT_SOURCE_DIR}/../third_party/masstree/libkohler_masstree_json.a 42 | Threads::Threads 43 | ) 44 | 45 | if (DEFINED ADD_ANALYSIS) 46 | add_definitions(-DADD_ANALYSIS=${ADD_ANALYSIS}) 47 | else () 48 | add_definitions(-DADD_ANALYSIS=0) 49 | endif () 50 | 51 | if (DEFINED BACK_OFF) 52 | add_definitions(-DBACK_OFF=${BACK_OFF}) 53 | else () 54 | add_definitions(-DBACK_OFF=0) 55 | endif () 56 | 57 | if (DEFINED KEY_SIZE) 58 | add_definitions(-DKEY_SIZE=${KEY_SIZE}) 59 | else () 60 | add_definitions(-DKEY_SIZE=8) 61 | endif () 62 | 63 | if (DEFINED KEY_SORT) 64 | add_definitions(-DKEY_SORT=${KEY_SORT}) 65 | else () 66 | add_definitions(-DKEY_SORT=0) 67 | endif () 68 | 69 | if (DEFINED MASSTREE_USE) 70 | add_definitions(-DMASSTREE_USE=${MASSTREE_USE}) 71 | else () 72 | add_definitions(-DMASSTREE_USE=1) 73 | endif () 74 | 75 | if (DEFINED VAL_SIZE) 76 | add_definitions(-DVAL_SIZE=${VAL_SIZE}) 77 | else () 78 | add_definitions(-DVAL_SIZE=4) 79 | endif () 80 | -------------------------------------------------------------------------------- /ermia/README.md: -------------------------------------------------------------------------------- 1 | # ERMIA 2 | It was proposed at SIGMOD'2016 by Kangnyeon Kim. 3 | SSN is serialization certifier which has to be executed serial. 4 | Latch-free SSN was proposed at VLDB'2017 by Tianzheng Wang. 5 | 6 | ## How to use 7 | - Build masstree 8 | ``` 9 | $ cd ../ 10 | $ ./bootstrap.sh 11 | ``` 12 | This makes ../third_party/masstree/libkohler_masstree_json.a used by building ermia. 13 | - Build mimalloc 14 | ``` 15 | $ cd ../ 16 | $ ./bootstrap_mimalloc.sh 17 | ``` 18 | This makes ../third_party/mimalloc/out/release/libmimalloc.a used by building ermia. 19 | - Build 20 | ``` 21 | $ mkdir build 22 | $ cd build 23 | $ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release .. 24 | $ ninja 25 | ``` 26 | - Confirm usage 27 | ``` 28 | $ ./ermia.exe -help 29 | ``` 30 | - Execution example 31 | ``` 32 | $ numactl --interleave=all ./ermia.exe -tuple_num=1000 -max_ope=10 -thread_num=224 -rratio=100 -rmw=0 -zipf_skew=0 -ycsb=1 -clocks_per_us=2100 -gc_inter_us=10 -pre_reserve_version=10000 -pre_reserve_tmt_element=100 -extime=3 33 | ``` 34 | 35 | ## How to customize options in CMakeLists.txt 36 | - `ADD_ANALYSIS` : If this is 1, it is deeper analysis than setting 0.
37 | default : `0` 38 | - `BACK_OFF` : If this is 1, it use Cicada's backoff.
39 | default : `0` 40 | - `KEY_SORT` : If this is 1, its transaction accesses records in ascending key order.
41 | default : `0` 42 | - `MASSTREE_USE` : If this is 1, it use masstree as data structure. If not, it use simple array αs data structure. 43 | default : `1` 44 | - `VAL_SIZE` : Value of key-value size. In other words, payload size.
45 | default : `4` 46 | 47 | ## Custom build examples 48 | ``` 49 | $ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DKEY_SIZE=1000 -DVAL_SIZE=1000 .. 50 | ``` 51 | - Note: If you re-run cmake, don't forget to remove cmake cache. 52 | ``` 53 | $ rm CMakeCache.txt 54 | ``` 55 | The cmake cache definition data is used in preference to the command line definition data. 56 | 57 | ## Optimizations 58 | - Backoff. 59 | - Early aborts. 60 | - Latch-free SSN. 61 | - Leveraging existing infrastructure. 62 | - Rapid garbage collection. 63 | - Reduce cache line contention about transaction mapping table. 64 | - Reuse version. 65 | -------------------------------------------------------------------------------- /ermia/include/common.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "lock.hh" 7 | #include "transaction_table.hh" 8 | #include "tuple.hh" 9 | 10 | #include "../../include/cache_line_size.hh" 11 | #include "../../include/int64byte.hh" 12 | #include "../../include/masstree_wrapper.hh" 13 | 14 | #include "gflags/gflags.h" 15 | #include "glog/logging.h" 16 | 17 | #ifdef GLOBAL_VALUE_DEFINE 18 | #define GLOBAL 19 | GLOBAL std::atomic Lsn(0); 20 | #if MASSTREE_USE 21 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 22 | #endif 23 | #else 24 | #define GLOBAL extern 25 | GLOBAL std::atomic Lsn; 26 | #if MASSTREE_USE 27 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 28 | #endif 29 | #endif 30 | 31 | #ifdef GLOBAL_VALUE_DEFINE 32 | DEFINE_uint64(clocks_per_us, 2100, "CPU_MHz. Use this info for measuring time."); 33 | DEFINE_uint64(extime, 3, "Execution time[sec]."); 34 | DEFINE_uint64(gc_inter_us, 10, "GC interval[us]."); 35 | DEFINE_uint64(max_ope, 10, 36 | "Total number of operations per single transaction."); 37 | DEFINE_uint64(pre_reserve_tmt_element, 100, "Pre-allocating memory for the transaction mapping table elements."); 38 | DEFINE_uint64(pre_reserve_version, 10000, "Pre-allocating memory for the version."); 39 | DEFINE_bool(rmw, false, 40 | "True means read modify write, false means blind write."); 41 | DEFINE_uint64(rratio, 50, "read ratio of single transaction."); 42 | DEFINE_uint64(thread_num, 10, "Total number of worker threads."); 43 | DEFINE_uint64(tuple_num, 1000000, "Total number of records."); 44 | DEFINE_bool(ycsb, true, 45 | "True uses zipf_skew, false uses faster random generator."); 46 | DEFINE_double(zipf_skew, 0, "zipf skew. 0 ~ 0.999..."); 47 | #else 48 | DECLARE_uint64(clocks_per_us); 49 | DECLARE_uint64(extime); 50 | DECLARE_uint64(gc_inter_us); 51 | DECLARE_uint64(max_ope); 52 | DECLARE_uint64(pre_reserve_tmt_element); 53 | DECLARE_uint64(pre_reserve_version); 54 | DECLARE_bool(rmw); 55 | DECLARE_uint64(rratio); 56 | DECLARE_uint64(thread_num); 57 | DECLARE_uint64(tuple_num); 58 | DECLARE_bool(ycsb); 59 | DECLARE_double(zipf_skew); 60 | #endif 61 | 62 | 63 | alignas(CACHE_LINE_SIZE) GLOBAL Tuple *Table; 64 | alignas(CACHE_LINE_SIZE) GLOBAL 65 | TransactionTable **TMT; // Transaction Mapping Table 66 | 67 | GLOBAL std::mutex SsnLock; 68 | -------------------------------------------------------------------------------- /ermia/include/ermia_op_element.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../include/op_element.hh" 4 | 5 | #include "version.hh" 6 | 7 | template 8 | class SetElement : public OpElement { 9 | public: 10 | using OpElement::OpElement; 11 | 12 | Version *ver_; 13 | 14 | SetElement(uint64_t key, T *rcdptr, Version *ver) 15 | : OpElement::OpElement(key, rcdptr) { 16 | this->ver_ = ver; 17 | } 18 | 19 | bool operator<(const SetElement &right) const { 20 | return this->key_ < right.key_; 21 | } 22 | }; 23 | 24 | template 25 | class GCElement : public OpElement { 26 | public: 27 | using OpElement::OpElement; 28 | 29 | Version *ver_; 30 | uint32_t cstamp_; 31 | 32 | GCElement(uint64_t key, T *rcdptr, Version *ver, uint32_t cstamp) 33 | : OpElement::OpElement(key, rcdptr) { 34 | this->ver_ = ver; 35 | this->cstamp_ = cstamp; 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /ermia/include/garbage_collection.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "../../include/inline.hh" 7 | #include "../../include/op_element.hh" 8 | 9 | #include "ermia_op_element.hh" 10 | #include "tuple.hh" 11 | #include "version.hh" 12 | 13 | // forward declaration 14 | class TransactionTable; 15 | 16 | class GarbageCollection { 17 | private: 18 | uint32_t fmin_, fmax_; // first range of txid in TMT. 19 | uint32_t smin_, smax_; // second range of txid in TMT. 20 | static std::atomic 21 | GC_threshold_; // share for all object (meaning all thread). 22 | 23 | public: 24 | std::deque gcq_for_TMT_; 25 | std::deque reuse_TMT_element_from_gc_; 26 | std::deque > gcq_for_version_; 27 | std::deque reuse_version_from_gc_; 28 | uint8_t thid_; 29 | 30 | GarbageCollection() {} 31 | 32 | GarbageCollection(uint8_t thid) : thid_(thid) {} 33 | 34 | void set_thid_(uint8_t thid) { thid_ = thid; } 35 | 36 | // for all thread 37 | INLINE uint32_t getGcThreshold() { 38 | return GC_threshold_.load(std::memory_order_acquire); 39 | } 40 | // ----- 41 | 42 | // for leader thread 43 | bool chkSecondRange(); 44 | 45 | void decideFirstRange(); 46 | 47 | INLINE void decideGcThreshold() { 48 | GC_threshold_.store(fmin_, std::memory_order_release); 49 | } 50 | 51 | INLINE void mvSecondRangeToFirstRange() { 52 | fmin_ = smin_; 53 | fmax_ = smax_; 54 | } 55 | // ----- 56 | 57 | // for worker thread 58 | void gcVersion(Result *eres_); 59 | 60 | void gcTMTelement(Result *eres_); 61 | // ----- 62 | }; 63 | 64 | #ifdef GLOBAL_VALUE_DEFINE 65 | // declare in ermia.cc 66 | std::atomic GarbageCollection::GC_threshold_(0); 67 | #endif 68 | -------------------------------------------------------------------------------- /ermia/include/lock.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class RWLock { 9 | public: 10 | std::atomic counter; 11 | // counter == -1, write locked; 12 | // counter == 0, not locked; 13 | // counter > 0, there are $counter readers who acquires read-lock. 14 | 15 | RWLock() { counter.store(0, std::memory_order_release); } 16 | 17 | // Read lock 18 | void r_lock() { 19 | int expected, desired; 20 | for (;;) { 21 | expected = counter.load(std::memory_order_acquire); 22 | RETRY_R_LOCK: 23 | if (expected != -1) 24 | desired = expected + 1; 25 | else { 26 | continue; 27 | } 28 | if (counter.compare_exchange_strong( 29 | expected, desired, memory_order_acq_rel, memory_order_acquire)) 30 | break; 31 | else 32 | goto RETRY_R_LOCK; 33 | } 34 | } 35 | 36 | void r_unlock() { counter--; } 37 | 38 | // Write lock 39 | void w_lock() { 40 | int expected; 41 | for (;;) { 42 | expected = counter.load(memory_order_acquire); 43 | RETRY_W_LOCK: 44 | if (expected != 0) continue; 45 | if (counter.compare_exchange_strong(expected, -1, memory_order_acq_rel, 46 | memory_order_acquire)) 47 | break; 48 | else 49 | goto RETRY_W_LOCK; 50 | } 51 | } 52 | 53 | void w_unlock() { counter++; } 54 | 55 | // Upgrae, read -> write 56 | void upgrade() { 57 | int one = 1; 58 | while (!counter.compare_exchange_strong(one, -1, memory_order_acq_rel, 59 | memory_order_acquire)) { 60 | } 61 | } 62 | }; 63 | -------------------------------------------------------------------------------- /ermia/include/result.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/result.hh" 6 | 7 | extern std::vector ErmiaResult; 8 | 9 | extern void initResult(); 10 | -------------------------------------------------------------------------------- /ermia/include/transaction_status.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | enum class TransactionStatus : uint8_t { 6 | inFlight, 7 | committing, 8 | committed, 9 | aborted, 10 | }; 11 | -------------------------------------------------------------------------------- /ermia/include/transaction_table.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "transaction_status.hh" 7 | 8 | class TransactionTable { 9 | public: 10 | alignas(CACHE_LINE_SIZE) std::atomic txid_; 11 | std::atomic cstamp_; 12 | std::atomic sstamp_; 13 | std::atomic lastcstamp_; 14 | std::atomic status_; 15 | 16 | TransactionTable() {} 17 | 18 | TransactionTable(uint32_t txid, uint32_t cstamp, uint32_t sstamp, 19 | uint32_t lastcstamp, TransactionStatus status) { 20 | this->txid_.store(txid, memory_order_relaxed); 21 | this->cstamp_.store(cstamp, memory_order_relaxed); 22 | this->sstamp_.store(sstamp, memory_order_relaxed); 23 | this->lastcstamp_.store(lastcstamp, memory_order_relaxed); 24 | this->status_.store(status, memory_order_relaxed); 25 | } 26 | 27 | void set(uint32_t txid, uint32_t cstamp, uint32_t sstamp, uint32_t lastcstamp, 28 | TransactionStatus status) { 29 | this->txid_.store(txid, memory_order_relaxed); 30 | this->cstamp_.store(cstamp, memory_order_relaxed); 31 | this->sstamp_.store(sstamp, memory_order_relaxed); 32 | this->lastcstamp_.store(lastcstamp, memory_order_relaxed); 33 | this->status_.store(status, memory_order_relaxed); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /ermia/include/tuple.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "../../include/cache_line_size.hh" 7 | #include "version.hh" 8 | 9 | class Tuple { 10 | public: 11 | alignas(CACHE_LINE_SIZE) std::atomic latest_; 12 | std::atomic min_cstamp_; 13 | std::atomic gc_lock_; 14 | 15 | Tuple() { 16 | latest_.store(nullptr); 17 | gc_lock_.store(0, std::memory_order_release); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /ermia/include/util.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "garbage_collection.hh" 4 | 5 | extern void chkArg(); 6 | 7 | extern void displayDB(); 8 | 9 | extern void displayParameter(); 10 | 11 | extern void leaderWork(GarbageCollection &gcob); 12 | 13 | extern void makeDB(); 14 | 15 | extern void naiveGarbageCollection(const bool &quit); 16 | 17 | extern void partTableInit([[maybe_unused]] size_t thid, uint64_t start, 18 | uint64_t end); 19 | 20 | extern void ShowOptParameters(); 21 | -------------------------------------------------------------------------------- /ermia/result.cc: -------------------------------------------------------------------------------- 1 | #include "include/result.hh" 2 | #include "include/common.hh" 3 | 4 | #include "../include/cache_line_size.hh" 5 | #include "../include/result.hh" 6 | 7 | using namespace std; 8 | 9 | alignas(CACHE_LINE_SIZE) std::vector ErmiaResult; 10 | 11 | void initResult() { ErmiaResult.resize(FLAGS_thread_num); } 12 | -------------------------------------------------------------------------------- /ermia/script/test_cache_ana.sh: -------------------------------------------------------------------------------- 1 | #test_cache_ana.sh(ermia) 2 | tuple=1000000 3 | maxope=10 4 | thread=24 5 | cpu_mhz=2400 6 | extime=3 7 | epoch=5 8 | 9 | rratio=0 10 | result=result_ermia_r0-10_cache-references.dat 11 | result2=result_ermia_r0-10_cache-misses.dat 12 | rm $result 13 | rm $result2 14 | echo "#rratio, cache-references, min, max" >> $result 15 | echo "#rratio, cache-misses, min, max" >> $result2 16 | echo "#./ermia.exe $tuple $maxope $thread $rratio $cpu_mhz $extime" >> $result 17 | echo "#./ermia.exe $tuple $maxope $thread $rratio $cpu_mhz $extime" >> $result2 18 | 19 | for ((rratio=0; rratio <= 10; ++rratio)) 20 | do 21 | echo "./ermia.exe $tuple $maxope $thread $rratio $cpu_mhz $extime" 22 | sum=0 23 | max=0 24 | min=0 25 | sum2=0 26 | max2=0 27 | min2=0 28 | for ((i = 1; i <= epoch; ++i)) 29 | do 30 | perf stat -e cache-references,cache-misses -o ermia_cache_ana.txt ./ermia.exe $tuple $maxope $thread $rratio $cpu_mhz $extime 31 | tmp=`grep cache-references ./ermia_cache_ana.txt | awk '{print $1}' | tr -d ,` 32 | tmp2=`grep cache-misses ./ermia_cache_ana.txt | awk '{print $1}' | tr -d ,` 33 | sum=`echo "$sum + $tmp" | bc -l` 34 | sum2=`echo "$sum2 + $tmp2" | bc -l` 35 | echo "sum: $sum, tmp: $tmp" 36 | echo "sum2: $sum2, tmp2: $tmp2" 37 | 38 | if test $i -eq 1 ; then 39 | max=$tmp 40 | min=$tmp 41 | max2=$tmp2 42 | min2=$tmp2 43 | fi 44 | 45 | flag=`echo "$tmp > $max" | bc -l` 46 | if test $flag -eq 1 ; then 47 | max=$tmp 48 | fi 49 | 50 | flag=`echo "$tmp < $min" | bc -l` 51 | if test $flag -eq 1 ; then 52 | min=$tmp 53 | fi 54 | flag=`echo "$tmp2 > $max2" | bc -l` 55 | if test $flag -eq 1 ; then 56 | max2=$tmp2 57 | fi 58 | 59 | flag=`echo "$tmp2 < $min2" | bc -l` 60 | if test $flag -eq 1 ; then 61 | min2=$tmp2 62 | fi 63 | done 64 | 65 | avg=`echo "$sum / $epoch" | bc -l` 66 | avg2=`echo "$sum2 / $epoch" | bc -l` 67 | echo "sum: $sum, epoch: $epoch" 68 | echo "sum2: $sum2, epoch: $epoch" 69 | echo "avg $avg" 70 | echo "avg2 $avg2" 71 | echo "max: $max" 72 | echo "max2: $max2" 73 | echo "min: $min" 74 | echo "min2: $min2" 75 | echo "$rratio $avg $min $max" >> $result 76 | echo "$rratio $avg2 $min2 $max2" >> $result2 77 | done 78 | -------------------------------------------------------------------------------- /ermia/script/ycsbA-xgcidbsize-cache.sh: -------------------------------------------------------------------------------- 1 | #ycsbA-xgcidbsize.sh(ermia) 2 | maxope=10 3 | thread=24 4 | rratio=50 5 | skew=0 6 | ycsb=ON 7 | cpu_mhz=2400 8 | extime=3 9 | epoch=5 10 | 11 | result=result_ermia_ycsbA_tuple100-10m_gci1us-100ms_cache-miss.dat 12 | rm $result 13 | echo "#tuple num, gci, throughput, min, max" >> $result 14 | for ((tuple=100; tuple<=10000000; tuple*=10)) 15 | do 16 | for ((gci=1; gci<=100000; gci*=10)) 17 | do 18 | sum=0 19 | echo "./ermia.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $gci $extime" 20 | echo "$tuple $epoch" 21 | 22 | max=0 23 | min=0 24 | for ((i = 1; i <= epoch; ++i)) 25 | do 26 | perf stat -e cache-misses,cache-references -o ermia-cache-ana.txt ./ermia.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $gci $extime 27 | tmp=`grep cache-misses ./ermia-cache-ana.txt | awk '{print $4}'` 28 | sum=`echo "$sum + $tmp" | bc -l` 29 | echo "sum: $sum, tmp: $tmp" 30 | 31 | if test $i -eq 1 ; then 32 | max=$tmp 33 | min=$tmp 34 | fi 35 | 36 | flag=`echo "$tmp > $max" | bc -l` 37 | if test $flag -eq 1 ; then 38 | max=$tmp 39 | fi 40 | flag=`echo "$tmp < $min" | bc -l` 41 | if test $flag -eq 1 ; then 42 | min=$tmp 43 | fi 44 | done 45 | 46 | avg=`echo "$sum / $epoch" | bc -l` 47 | echo "sum: $sum, epoch: $epoch" 48 | echo "avg $avg" 49 | echo "max: $max" 50 | echo "min: $min" 51 | echo "$tuple $gci $avg $min $max" >> $result 52 | done 53 | echo "" >> $result 54 | done 55 | -------------------------------------------------------------------------------- /ermia/script/ycsbA-xgcidbsize.sh: -------------------------------------------------------------------------------- 1 | #ycsbA-xgcidbsize.sh(ermia) 2 | maxope=10 3 | thread=24 4 | rratio=50 5 | skew=0 6 | ycsb=ON 7 | cpu_mhz=2400 8 | extime=3 9 | epoch=5 10 | 11 | result=result_ermia_ycsbA_tuple100-10m_gci1us-100ms_ar.dat 12 | rm $result 13 | echo "#tuple num, gci, throughput, min, max" >> $result 14 | for ((tuple=100; tuple<=10000000; tuple*=10)) 15 | do 16 | for ((gci=1; gci<=100000; gci*=10)) 17 | do 18 | sum=0 19 | echo "./ermia.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $gci $extime" 20 | echo "$tuple $epoch" 21 | 22 | max=0 23 | min=0 24 | for ((i = 1; i <= epoch; ++i)) 25 | do 26 | tmp=`./ermia.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $gci $extime` 27 | sum=`echo "$sum + $tmp" | bc -l` 28 | echo "sum: $sum, tmp: $tmp" 29 | 30 | if test $i -eq 1 ; then 31 | max=$tmp 32 | min=$tmp 33 | fi 34 | 35 | flag=`echo "$tmp > $max" | bc -l` 36 | if test $flag -eq 1 ; then 37 | max=$tmp 38 | fi 39 | flag=`echo "$tmp < $min" | bc -l` 40 | if test $flag -eq 1 ; then 41 | min=$tmp 42 | fi 43 | done 44 | avg=`echo "$sum / $epoch" | bc -l` 45 | echo "sum: $sum, epoch: $epoch" 46 | echo "avg $avg" 47 | echo "max: $max" 48 | echo "min: $min" 49 | echo "$tuple $gci $avg $min $max" >> $result 50 | done 51 | echo "" >> $result 52 | done 53 | -------------------------------------------------------------------------------- /ermia/script/ycsbA-xrs-cache.sh: -------------------------------------------------------------------------------- 1 | #ycsbA-xrs-cache.sh(ermia) 2 | maxope=10 3 | thread=24 4 | rratio=50 5 | skew=0 6 | ycsb=ON 7 | cpu_mhz=2400 8 | extime=3 9 | epoch=5 10 | 11 | result=result_ermia_ycsbA_tuple100-10m_cachemiss.dat 12 | rm $result 13 | echo "#tuple num, cache-misses, min, max" >> $result 14 | echo "#./ermia.exe tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $extime" >> $result 15 | 16 | for ((tuple=100; tuple<=10000000; tuple*=10)) 17 | do 18 | sum=0 19 | echo "./ermia.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $extime" 20 | echo "$tuple $epoch" 21 | 22 | max=0 23 | min=0 24 | for ((i = 1; i <= epoch; ++i)) 25 | do 26 | perf stat -e cache-misses,cache-references -o ermia-cache-ana.txt ./ermia.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $extime 27 | tmp=`grep cache-misses ./ermia-cache-ana.txt | awk '{print $4}'` 28 | sum=`echo "$sum + $tmp" | bc -l` 29 | echo "sum: $sum, tmp: $tmp" 30 | 31 | if test $i -eq 1 ; then 32 | max=$tmp 33 | min=$tmp 34 | fi 35 | 36 | flag=`echo "$tmp > $max" | bc -l` 37 | if test $flag -eq 1 ; then 38 | max=$tmp 39 | fi 40 | flag=`echo "$tmp < $min" | bc -l` 41 | if test $flag -eq 1 ; then 42 | min=$tmp 43 | fi 44 | done 45 | avg=`echo "$sum / $epoch" | bc -l` 46 | echo "sum: $sum, epoch: $epoch" 47 | echo "avg $avg" 48 | echo "max: $max" 49 | echo "min: $min" 50 | echo "$tuple $avg $min $max" >> $result 51 | done 52 | 53 | -------------------------------------------------------------------------------- /include/Makefile: -------------------------------------------------------------------------------- 1 | INCLUDE_ALLSRC = $(wildcard *.hh) 2 | 3 | format: 4 | clang-format -i -verbose -style=Google $(INCLUDE_ALLSRC) 5 | -------------------------------------------------------------------------------- /include/atomic_wrapper.hh: -------------------------------------------------------------------------------- 1 | /** 2 | * This file was created with reference to the following URL. 3 | * Special thanks to Mr. Hoshino. 4 | * https://github.com/starpos/oltp-cc-bench/blob/master/include/atomic_wrapper.hpp 5 | */ 6 | 7 | #pragma once 8 | 9 | template 10 | T load(T &ptr) { 11 | return __atomic_load_n(&ptr, __ATOMIC_RELAXED); 12 | } 13 | 14 | template 15 | T loadAcquire(T &ptr) { 16 | return __atomic_load_n(&ptr, __ATOMIC_ACQUIRE); 17 | } 18 | 19 | template 20 | void store(T &ptr, T2 val) { 21 | __atomic_store_n(&ptr, (T) val, __ATOMIC_RELAXED); 22 | } 23 | 24 | template 25 | void storeRelease(T &ptr, T2 val) { 26 | __atomic_store_n(&ptr, (T) val, __ATOMIC_RELEASE); 27 | } 28 | 29 | template 30 | bool compareExchange(T &m, T &before, T2 after) { 31 | return __atomic_compare_exchange_n(&m, &before, (T) after, false, 32 | __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE); 33 | } 34 | -------------------------------------------------------------------------------- /include/cache_line_size.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define CACHE_LINE_SIZE 64 6 | -------------------------------------------------------------------------------- /include/check.hh: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | static bool chkInt(const char *arg) { 8 | for (uint i = 0; i < strlen(arg); ++i) { 9 | if (!isdigit(arg[i])) { 10 | std::cout << std::string(arg) << " is not a number." << std::endl; 11 | exit(0); 12 | } 13 | } 14 | 15 | return true; 16 | } 17 | -------------------------------------------------------------------------------- /include/compiler.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define likely(x) __builtin_expect(!!(x), 1) 4 | #define unlikely(x) __builtin_expect(!!(x), 0) 5 | -------------------------------------------------------------------------------- /include/config.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define PAGE_SIZE 4096 4 | -------------------------------------------------------------------------------- /include/cpu.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "debug.hh" 9 | 10 | #define CPUID(INFO, LEAF, SUBLEAF) \ 11 | __cpuid_count(LEAF, SUBLEAF, INFO[0], INFO[1], INFO[2], INFO[3]) 12 | 13 | #define GETCPU(CPU) \ 14 | { \ 15 | uint32_t CPUInfo[4]; \ 16 | CPUID(CPUInfo, 1, 0); \ 17 | /* CPUInfo[1] is EBX, bits 24-31 are APIC ID */ \ 18 | if ((CPUInfo[3] & (1 << 9)) == 0) { \ 19 | CPU = -1; /* no APIC on chip */ \ 20 | } else { \ 21 | CPU = (unsigned)CPUInfo[1] >> 24; \ 22 | /*unsigned int cores = ((unsigned)CPUInfo[1] >> 16) & 0xff;*/ \ 23 | /*if ((CPUInfo[3] & (1 << 28)) == 1) printf("HTT\n");*/ \ 24 | /*printf("total core number : %d\n", cores);*/ \ 25 | } \ 26 | if (CPU < 0) CPU = 0; \ 27 | } 28 | 29 | #ifdef Linux 30 | static void setThreadAffinity(const int myid) { 31 | pid_t pid = syscall(SYS_gettid); 32 | cpu_set_t cpu_set; 33 | 34 | CPU_ZERO(&cpu_set); 35 | CPU_SET(myid % sysconf(_SC_NPROCESSORS_CONF), &cpu_set); 36 | 37 | if (sched_setaffinity(pid, sizeof(cpu_set_t), &cpu_set) != 0) ERR; 38 | 39 | // printf("thread affinity (id==%d) [ok]\n", myid); 40 | return; 41 | } 42 | #endif // Linux 43 | -------------------------------------------------------------------------------- /include/delay.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "tsc.hh" 8 | 9 | using namespace std; 10 | 11 | [[maybe_unused]] static void 12 | clock_delay(size_t clocks) { 13 | std::size_t start(rdtscp()), stop; 14 | 15 | for (;;) { 16 | stop = rdtscp(); 17 | if (stop - start > clocks) { 18 | break; 19 | } else { 20 | _mm_pause(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /include/fence.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "inline.hh" 4 | 5 | INLINE void compilerFence() { asm volatile("":: : "memory"); } 6 | -------------------------------------------------------------------------------- /include/inline.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define INLINE __attribute__((always_inline)) inline 4 | -------------------------------------------------------------------------------- /include/int64byte.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "./cache_line_size.hh" 6 | 7 | class uint64_t_64byte { 8 | public: 9 | alignas(CACHE_LINE_SIZE) uint64_t obj_; 10 | 11 | uint64_t_64byte() : obj_(0) {} 12 | 13 | uint64_t_64byte(uint64_t initial) : obj_(initial) {} 14 | }; 15 | -------------------------------------------------------------------------------- /include/logger.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thawk on 2020/11/10. 3 | // 4 | 5 | #pragma once 6 | 7 | #ifdef NDEBUG 8 | #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO 9 | #else 10 | #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG // NOLINT 11 | #endif 12 | 13 | #include "spdlog/spdlog.h" 14 | 15 | namespace ccbench { 16 | 17 | static inline void setup_spdlog() { 18 | 19 | #ifdef NDEBUG 20 | spdlog::set_level(spdlog::level::info); 21 | #else 22 | spdlog::set_level(spdlog::level::debug); 23 | #endif 24 | 25 | } 26 | 27 | } // namespace ccbench 28 | -------------------------------------------------------------------------------- /include/op_element.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "debug.hh" 4 | 5 | template 6 | class OpElement { 7 | public: 8 | uint64_t key_; 9 | T *rcdptr_; 10 | 11 | OpElement() : key_(0), rcdptr_(nullptr) {} 12 | 13 | OpElement(uint64_t key) : key_(key) {} 14 | 15 | OpElement(uint64_t key, T *rcdptr) : key_(key), rcdptr_(rcdptr) {} 16 | }; 17 | -------------------------------------------------------------------------------- /include/procedure.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | using std::cout; 6 | using std::endl; 7 | 8 | enum class Ope : uint8_t { 9 | READ, 10 | WRITE, 11 | READ_MODIFY_WRITE, 12 | }; 13 | 14 | class Procedure { 15 | public: 16 | Ope ope_; 17 | uint64_t key_; 18 | bool ronly_ = false; 19 | bool wonly_ = false; 20 | 21 | Procedure() : ope_(Ope::READ), key_(0) {} 22 | 23 | Procedure(Ope ope, uint64_t key) : ope_(ope), key_(key) {} 24 | 25 | bool operator<(const Procedure &right) const { 26 | if (this->key_ == right.key_ && this->ope_ == Ope::WRITE && 27 | right.ope_ == Ope::READ) { 28 | return true; 29 | } else if (this->key_ == right.key_ && this->ope_ == Ope::WRITE && 30 | right.ope_ == Ope::WRITE) { 31 | return true; 32 | } 33 | /* キーが同値なら先に write ope を実行したい.read -> write よりも write -> 34 | * read. 35 | * キーが同値で自分が read でここまで来たら,下記の式によって絶対に false 36 | * となり,自分 (read) が昇順で後ろ回しになるので ok */ 37 | 38 | return this->key_ < right.key_; 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /include/string.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "debug.hh" 4 | #include "fence.hh" 5 | 6 | using std::cout; 7 | using std::endl; 8 | 9 | [[maybe_unused]] static void genStringRepeatedNumber(char *string, size_t val_size, 10 | size_t thid) { 11 | size_t digit(1), thidnum(thid); 12 | for (;;) { 13 | thidnum /= 10; 14 | if (thidnum != 0) 15 | ++digit; 16 | else 17 | break; 18 | } 19 | 20 | // generate write value for this thread. 21 | sprintf(string, "%ld", thid); 22 | for (uint i = digit; i < val_size - 2; ++i) { 23 | string[i] = '0'; 24 | } 25 | // printf("%s\n", string); 26 | } 27 | -------------------------------------------------------------------------------- /include/tsc.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | [[maybe_unused]] static uint64_t 6 | rdtsc() { 7 | uint64_t rax; 8 | uint64_t rdx; 9 | 10 | asm volatile("rdtsc" : "=a"(rax), "=d"(rdx)); 11 | // store higher bits to rdx, lower bits to rax. 12 | // シリアライズ命令でないため,全ての先行命令を待機せずに 13 | // カウンタ値を読み込む.同様に後続命令が読み取り命令を追い越すことを許容する. 14 | 15 | return (rdx << 32) | rax; 16 | } 17 | 18 | [[maybe_unused]] static uint64_t 19 | rdtsc_serial() { 20 | uint64_t rax; 21 | uint64_t rdx; 22 | 23 | asm volatile("cpuid":: : "rax", "rbx", "rcx", "rdx"); 24 | asm volatile("rdtsc" : "=a"(rax), "=d"(rdx)); 25 | 26 | return (rdx << 32) | rax; 27 | } 28 | 29 | [[maybe_unused]] static uint64_t 30 | rdtscp() { 31 | uint64_t rax; 32 | uint64_t rdx; 33 | uint32_t aux; 34 | asm volatile("rdtscp" : "=a"(rax), "=d"(rdx), "=c"(aux)::); 35 | // store EDX:EAX. 36 | // 全ての先行命令を待機してからカウンタ値を読み取る.ただし,後続命令は 37 | // 同読み取り操作を追い越す可能性がある. 38 | 39 | return (rdx << 32) | rax; 40 | } 41 | -------------------------------------------------------------------------------- /include/zipf.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "inline.hh" 11 | #include "random.hh" 12 | 13 | using std::cout; 14 | using std::endl; 15 | 16 | // Fast zipf distribution by Jim Gray et al. 17 | class FastZipf { 18 | Xoroshiro128Plus *rnd_; 19 | const size_t nr_; 20 | const double alpha_, zetan_, eta_; 21 | const double threshold_; 22 | 23 | public: 24 | FastZipf(Xoroshiro128Plus *rnd, double theta, size_t nr) 25 | : rnd_(rnd), 26 | nr_(nr), 27 | alpha_(1.0 / (1.0 - theta)), 28 | zetan_(zeta(nr, theta)), 29 | eta_((1.0 - std::pow(2.0 / (double) nr, 1.0 - theta)) / 30 | (1.0 - zeta(2, theta) / zetan_)), 31 | threshold_(1.0 + std::pow(0.5, theta)) { 32 | assert(0.0 <= theta); 33 | assert(theta < 1.0); // 1.0 can not be specified. 34 | } 35 | 36 | // Use this constructor if zeta is pre-calculated. 37 | FastZipf(Xoroshiro128Plus *rnd, double theta, size_t nr, double zetan) 38 | : rnd_(rnd), 39 | nr_(nr), 40 | alpha_(1.0 / (1.0 - theta)), 41 | zetan_(zetan), 42 | eta_((1.0 - std::pow(2.0 / (double) nr, 1.0 - theta)) / 43 | (1.0 - zeta(2, theta) / zetan_)), 44 | threshold_(1.0 + std::pow(0.5, theta)) { 45 | assert(0.0 <= theta); 46 | assert(theta < 1.0); // 1.0 can not be specified. 47 | } 48 | 49 | INLINE size_t operator()() { 50 | double u = rnd_->next() / (double) UINT64_MAX; 51 | double uz = u * zetan_; 52 | if (uz < 1.0) return 0; 53 | if (uz < threshold_) return 1; 54 | return (size_t)((double) nr_ * std::pow(eta_ * u - eta_ + 1.0, alpha_)); 55 | } 56 | 57 | uint64_t rand() { return rnd_->next(); } 58 | 59 | static double zeta(size_t nr, double theta) { 60 | double ans = 0.0; 61 | for (size_t i = 0; i < nr; ++i) 62 | ans += std::pow(1.0 / (double) (i + 1), theta); 63 | return ans; 64 | } 65 | }; 66 | -------------------------------------------------------------------------------- /instruction/Makefile: -------------------------------------------------------------------------------- 1 | PROG1 = fetch_add 2 | INST_SRCS1 = fetch_add.cc 3 | 4 | PROG2 = cache-test 5 | INST_SRCS2 = cache-test.cc 6 | 7 | PROG3 = membench 8 | INST_SRCS3 = membench.cc 9 | 10 | PROG4 = rdtscBench 11 | INST_SRCS4 = rdtscBench.cc 12 | 13 | PROG5 = xoroshiro 14 | INST_SRCS5 = xoroshiro.cc 15 | 16 | REL := ../common/ 17 | include $(REL)Makefile 18 | 19 | CC = g++ 20 | CFLAGS = -c -pipe -g -O3 -std=c++17 -march=native \ 21 | -Wall -Wextra -Wchkp -Winvalid-memory-model -Wdangling-else \ 22 | -D$(shell uname) \ 23 | -D$(shell hostname) \ 24 | 25 | ifeq ($(shell hostname), chris41.omni.hpcc.jp) 26 | LDFLAGS = -L/home/tanabe/package/tbb/build/linux_intel64_gcc_cc7.1.0_libc2.12_kernel2.6.32_release 27 | endif 28 | ifeq ($(shell hostname), dbs11) 29 | LDFLAGS = -L/home/tanabe/package/tbb/build/linux_intel64_gcc_cc7_libc2.27_kernel4.15.0_release 30 | endif 31 | 32 | LIBS = -lpthread -ltbbmalloc_proxy -ltbbmalloc 33 | ifneq ($(shell hostname), chris41.omni.hpcc.jp) 34 | ifneq ($(shell hostname), dbs11) 35 | LIBS = -lpthread 36 | endif 37 | endif 38 | 39 | OBJS1 = $(INST_SRCS1:.cc=.o) 40 | OBJS2 = $(INST_SRCS2:.cc=.o) 41 | OBJS3 = $(INST_SRCS3:.cc=.o) 42 | OBJS4 = $(INST_SRCS4:.cc=.o) 43 | OBJS5 = $(INST_SRCS5:.cc=.o) 44 | 45 | all: $(PROG1) $(PROG2) $(PROG3) $(PROG4) $(PROG5) 46 | 47 | $(PROG1) : $(OBJS1) ../common/util.o 48 | $(CC) -o $@ $^ $(LDFLAGS) $(LIBS) 49 | 50 | $(PROG2) : $(OBJS2) 51 | $(CC) -o $@ $^ $(LDFLAGS) $(LIBS) 52 | 53 | $(PROG3) : $(OBJS3) 54 | $(CC) -o $@ $^ $(LDFLAGS) $(LIBS) 55 | 56 | $(PROG4) : $(OBJS4) 57 | $(CC) -o $@ $^ $(LDFLAGS) $(LIBS) 58 | 59 | $(PROG5) : $(OBJS5) 60 | $(CC) -o $@ $^ $(LDFLAGS) $(LIBS) 61 | 62 | .cc.o: 63 | $(CC) $(CFLAGS) -c $< -o $@ 64 | 65 | format: 66 | clang-format -i -verbose -style=Google $(wildcard *.cc) 67 | 68 | clean: 69 | rm -f *~ *.o *.exe *.stackdump 70 | rm -f ../common/*~ ../common/*.o ../common/*.exe ../common/*.stackdump 71 | -------------------------------------------------------------------------------- /instruction/README.md: -------------------------------------------------------------------------------- 1 | # Instruction Survey 2 | 3 | ## fetch\_add 4 | ## xoroshiro128+ 5 | ## memory benchmark 6 | ## masstree unit test 7 | -------------------------------------------------------------------------------- /instruction/include/common.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../../include/int64byte.hh" 8 | 9 | #ifdef GLOBAL_VALUE_DEFINE 10 | #define GLOBAL 11 | GLOBAL std::atomic Running(0); 12 | GLOBAL std::atomic Counter(0); 13 | GLOBAL std::atomic Finish(false); 14 | 15 | #else 16 | #define GLOBAL extern 17 | GLOBAL std::atomic Running; 18 | GLOBAL std::atomic Counter; 19 | GLOBAL std::atomic Finish; 20 | 21 | #endif 22 | 23 | //run-time args 24 | GLOBAL unsigned int THREAD_NUM; 25 | GLOBAL uint64_t CLOCK_PER_US; 26 | GLOBAL unsigned int EXTIME; 27 | 28 | GLOBAL uint64_t_64byte *CounterIncrements; 29 | 30 | GLOBAL uint64_t Bgn; 31 | GLOBAL uint64_t End; 32 | 33 | -------------------------------------------------------------------------------- /instruction/masstree_simple_test/GNUmakefile: -------------------------------------------------------------------------------- 1 | AR = ar 2 | CC = gcc 3 | CXX = g++ 4 | CPPFLAGS = 5 | CXXFLAGS = -g -W -Wall -O2 -pipe 6 | CXXFLAGS += -march=native 7 | 8 | DEPSDIR := .deps 9 | DEPCFLAGS = #-MD -MF $(DEPSDIR)/$*.d -MP 10 | ifeq ($(strip $(MEMMGR)), ) 11 | MEMMGR = 12 | endif 13 | ifneq ($(strip $(KEYSWAP)), ) 14 | CPPFLAGS += -DKEYSWAP 15 | endif 16 | ifneq ($(strip $(NOPREFETCH)), ) 17 | CPPFLAGS += -DNOPREFETCH 18 | endif 19 | ifneq ($(strip $(NOSUPERPAGE)), ) 20 | CPPFLAGS += -DNOSUPERPAGE 21 | endif 22 | 23 | LIBS = -lnuma -lpthread -lm 24 | ifeq (0, 0) # for easy switch 25 | ifeq ($(shell hostname), dbs11) 26 | LIBS += -ltbb -ltbbmalloc_proxy -ltbbmalloc 27 | endif 28 | endif 29 | 30 | DEFINE = 31 | ifeq ($(shell hostname), dbs11) 32 | DEFINE += -Ddbs11 33 | endif 34 | 35 | INCLUDE = 36 | ifeq ($(shell hostname), dbs11) 37 | INCLUDE += -I/home/tanabe/package/tbb/include/tbb 38 | endif 39 | 40 | LDFLAGS = 41 | ifeq ($(shell hostname), dbs11) 42 | LDFLAGS += -L/home/tanabe/package/tbb/build/linux_intel64_gcc_cc7_libc2.27_kernel4.15.0_release 43 | endif 44 | 45 | all: unit-mt unit-mt2 46 | 47 | %.o: %.c ../../masstree/config.h #$(DEPSDIR)/stamp 48 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEPCFLAGS) $(INCLUDE) $(DEFINE) -c -o $@ $< 49 | 50 | %.o: %.cc ../../masstree/config.h #$(DEPSDIR)/stamp 51 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEPCFLAGS) $(INCLUDE) $(DEFINE) -c -o $@ $< 52 | 53 | %.S: %.o 54 | objdump -S $< > $@ 55 | 56 | ../../masstree/libjson.a: ../../masstree/json.o ../../masstree/string.o ../../masstree/straccum.o ../../masstree/str.o ../../masstree/msgpack.o \ 57 | ../../masstree/clp.o ../../masstree/kvrandom.o ../../masstree/compiler.o ../../masstree/memdebug.o ../../masstree/kvthread.o 58 | @/bin/rm -f $@ 59 | $(AR) cru $@ $^ 60 | 61 | unit-mt: unit-mt.o ../../masstree/compiler.o ../../masstree/misc.o ../../masstree/libjson.a ../../common/util.o 62 | $(CXX) $(CXXFLAGS) -o $@ $^ $(MEMMGR) $(LDFLAGS) $(LIBS) 63 | 64 | unit-mt2: unit-mt2.o ../../masstree/compiler.o ../../masstree/misc.o ../../masstree/libjson.a ../../common/util.o 65 | $(CXX) $(CXXFLAGS) -o $@ $^ $(MEMMGR) $(LDFLAGS) $(LIBS) 66 | 67 | $(DEPSDIR)/stamp: 68 | mkdir -p $(DEPSDIR) 69 | touch $@ 70 | 71 | clean: 72 | rm -f mtd mtclient mttest test_string test_atomics *.o libjson.a 73 | rm -rf .deps 74 | rm -f ../../common/*.o 75 | 76 | DEPFILES := $(wildcard $(DEPSDIR)/*.d) 77 | ifneq ($(DEPFILES),) 78 | include $(DEPFILES) 79 | endif 80 | 81 | .PHONY: clean all 82 | -------------------------------------------------------------------------------- /instruction/masstree_simple_test/script/test.sh: -------------------------------------------------------------------------------- 1 | 2 | result=result_masstree_put.dat 3 | rm $result 4 | epoch=3 5 | thread=1 6 | 7 | sumTH=0 8 | avgTH=0 9 | tmpTH=0 10 | for ((i = 1; i <= epoch; ++i)) 11 | do 12 | ../unit-mt $thread > out 13 | tmpTH=`cat out` 14 | sumTH=`echo "$sumTH + $tmpTH" | bc` 15 | done 16 | 17 | avgTH=`echo "$sumTH / $epoch" | bc` 18 | echo "$thread $avgTH" | tee -a $result 19 | 20 | for ((thread = 28; thread <= 224; thread+=28)) 21 | do 22 | 23 | sumTH=0 24 | avgTH=0 25 | tmpTH=0 26 | for ((i = 1; i <= epoch; ++i)) 27 | do 28 | ../unit-mt $thread > out 29 | tmpTH=`cat out` 30 | sumTH=`echo "$sumTH + $tmpTH" | bc` 31 | done 32 | 33 | avgTH=`echo "$sumTH / $epoch" | bc` 34 | echo "$thread $avgTH" | tee -a $result 35 | 36 | done 37 | 38 | -------------------------------------------------------------------------------- /instruction/masstree_simple_test/script/xrs.sh: -------------------------------------------------------------------------------- 1 | 2 | result=result_masstree_put_xrs.dat 3 | rm $result 4 | epoch=3 5 | thread=224 6 | rs=1000 7 | 8 | sumTH=0 9 | avgTH=0 10 | tmpTH=0 11 | for ((i = 1; i <= epoch; ++i)) 12 | do 13 | ../unit-mt $thread $rs > out 14 | tmpTH=`cat out` 15 | sumTH=`echo "$sumTH + $tmpTH" | bc` 16 | done 17 | 18 | avgTH=`echo "$sumTH / $epoch" | bc` 19 | echo "$rs $avgTH" | tee -a $result 20 | 21 | for ((rs = 10000; rs <= 1000000000; rs *= 10)) 22 | do 23 | 24 | sumTH=0 25 | avgTH=0 26 | tmpTH=0 27 | for ((i = 1; i <= epoch; ++i)) 28 | do 29 | ../unit-mt $thread $rs > out 30 | tmpTH=`cat out` 31 | sumTH=`echo "$sumTH + $tmpTH" | bc` 32 | done 33 | 34 | avgTH=`echo "$sumTH / $epoch" | bc` 35 | echo "$rs $avgTH" | tee -a $result 36 | 37 | done 38 | 39 | -------------------------------------------------------------------------------- /instruction/pow_test.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../include/debug.hh" 7 | 8 | #define TRIAL 1000000 9 | 10 | using namespace std; 11 | 12 | int main(const int argc, const char *argv[]) try { 13 | cout << "#pow_arg, time" << endl; 14 | for (double j = 0; j <= 3; j += 0.1) { 15 | chrono::system_clock::time_point start, end; 16 | start = chrono::system_clock::now(); 17 | for (size_t i = 0; i < TRIAL; ++i) 18 | pow(2, j); 19 | end = chrono::system_clock::now(); 20 | double time = static_cast(chrono::duration_cast(end - start).count() / 1000.0); 21 | cout << j << " " << time << endl; 22 | } 23 | return 0; 24 | } catch (std::bad_alloc) { 25 | ERR; 26 | } 27 | -------------------------------------------------------------------------------- /instruction/rdtscBench.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "../include/tsc.hh" 5 | 6 | #define LOOP 1000000 7 | 8 | using std::cout; 9 | using std::endl; 10 | 11 | int main() { 12 | uint64_t start, stop; 13 | start = rdtscp(); 14 | for (uint64_t i = 0; i < LOOP; ++i) rdtsc(); 15 | stop = rdtscp(); 16 | 17 | cout << "rdtscBench[clocks] :\t" << (stop - start) / LOOP << endl; 18 | 19 | start = rdtscp(); 20 | for (unsigned int i = 0; i < LOOP; ++i) rdtscp(); 21 | stop = rdtscp(); 22 | 23 | cout << "rdtscpBench[clocks] :\t" << (stop - start) / LOOP << endl; 24 | } 25 | -------------------------------------------------------------------------------- /instruction/script/fetch_add.sh: -------------------------------------------------------------------------------- 1 | #membench.sh 2 | thnr=1 3 | epoch=3; 4 | 5 | host=`hostname` 6 | chris41="chris41.omni.hpcc.jp" 7 | dbs11="dbs11" 8 | 9 | #basically 10 | inith=1 11 | enth=24 12 | inc=1 13 | if test $host = $dbs11 ; then 14 | inith=1 15 | enth=224 16 | inc=28 17 | fi 18 | 19 | result=fetch_add.dat 20 | rm $result 21 | echo "#thnr, throughput, cache-miss-rate" >> $result 22 | 23 | for ((thread=$inith; thread<=$enth; thread+=$inc)) 24 | do 25 | if test $host = $dbs11 ; then 26 | if test $thread -eq 29 ; then 27 | thread=28 28 | fi 29 | fi 30 | sumtps=0 31 | sumcm=0 32 | for ((i = 1; i <= epoch; ++i)) 33 | do 34 | echo "#thread: $thread, #epoch: $i" 35 | perf stat -e cache-misses,cache-references -o ana.txt numactl --interleave=all ../fetch_add $thread > out 36 | tmptps=`cat out` 37 | tmpcm=`grep cache-misses ./ana.txt | awk '{print $4}'` 38 | sumtps=`echo "$sumtps + $tmptps" | bc` 39 | sumcm=`echo "$sumcm + $tmpcm" | bc` 40 | done 41 | 42 | avgtps=`echo "$sumtps / $epoch" | bc` 43 | avgcm=`echo "$sumcm / $epoch" | bc` 44 | 45 | echo "avgtps: $avgtps, avgcm: $avgcm" 46 | echo "$thread $avgtps $avgcm" >> $result 47 | done 48 | -------------------------------------------------------------------------------- /instruction/script/membench.sh: -------------------------------------------------------------------------------- 1 | #membench.sh 2 | thnr=1 3 | alc=1; 4 | epoch=3; 5 | 6 | host=`hostname` 7 | chris41="chris41.omni.hpcc.jp" 8 | dbs11="dbs11" 9 | 10 | #basically 11 | inith=4 12 | enth=24 13 | inc=4 14 | if test $host = $dbs11 ; then 15 | inith=28 16 | enth=224 17 | inc=28 18 | fi 19 | 20 | result=membench.dat 21 | rm $result 22 | echo "#array size was $alc GB." >> $result 23 | echo "#thnr, srbw, swbw, rrbw, rwbw" >> $result 24 | 25 | for ((thread=$inith; thread<=$enth; thread+=$inc)) 26 | do 27 | sumSRBW=0 28 | sumSWBW=0 29 | sumRRBW=0 30 | sumRWBW=0 31 | for ((i = 1; i <= epoch; ++i)) 32 | do 33 | numactl --localalloc ../membench.exe $thread $alc > out 34 | echo "thread $thread" 35 | cat out | grep -v Th\# 36 | echo "" 37 | 38 | tmpSRBW=`grep -v Th# out | grep sequentialRead | awk '{print $2}'` 39 | tmpSWBW=`grep -v Th# out | grep sequentialWrite | awk '{print $2}'` 40 | tmpRRBW=`grep -v Th# out | grep randomRead | awk '{print $2}'` 41 | tmpRWBW=`grep -v Th# out | grep randomWrite | awk '{print $2}'` 42 | echo "tmpSRBW $tmpSRBW" 43 | sumSRBW=`echo "$sumSRBW + $tmpSRBW" | bc` 44 | sumSWBW=`echo "$sumSWBW + $tmpSWBW" | bc` 45 | sumRRBW=`echo "$sumRRBW + $tmpRRBW" | bc` 46 | sumRWBW=`echo "$sumRWBW + $tmpRWBW" | bc` 47 | done 48 | 49 | avgSRBW=`echo "$sumSRBW / $epoch" | bc` 50 | avgSWBW=`echo "$sumSWBW / $epoch" | bc` 51 | avgRRBW=`echo "$sumRRBW / $epoch" | bc` 52 | avgRWBW=`echo "$sumRWBW / $epoch" | bc` 53 | 54 | echo "$thread $avgSRBW $avgSWBW $avgRRBW $avgRWBW" >> $result 55 | done 56 | -------------------------------------------------------------------------------- /instruction/test_fetch_add.sh: -------------------------------------------------------------------------------- 1 | #test.sh(ermia) 2 | cpu_mhz=2400 3 | extime=3 4 | epoch=3 5 | 6 | result=fetch_add.dat 7 | rm $result 8 | echo "#worker threads, increments, min, max" >> $result 9 | for ((thread=2; thread<=24; thread+=2)) 10 | do 11 | sum=0 12 | echo "./fetch_add.exe $thread $cpu_mhz $extime" 13 | 14 | max=0 15 | min=0 16 | for ((i=1; i <= epoch; ++i)) 17 | do 18 | tmp=`./fetch_add.exe $thread $cpu_mhz $extime` 19 | sum=`echo "$sum + $tmp" | bc -l` 20 | echo "sum: $sum, tmp: $tmp" 21 | 22 | if test $i -eq 1 ; then 23 | max=$tmp 24 | min=$tmp 25 | fi 26 | 27 | flag=`echo "$tmp > $max" | bc -l` 28 | if test $flag -eq 1 ; then 29 | max=$tmp 30 | fi 31 | flag=`echo "$tmp < $min" | bc -l` 32 | if test $flag -eq 1 ; then 33 | min=$tmp 34 | fi 35 | done 36 | avg=`echo "$sum / $epoch" | bc` 37 | echo "sum: $sum, epoch: $epoch" 38 | echo "avg: $avg" 39 | echo "max: $max" 40 | echo "min: $min" 41 | echo "$thread $avg $min $max" >> $result 42 | done 43 | -------------------------------------------------------------------------------- /instruction/test_xoroshiro.sh: -------------------------------------------------------------------------------- 1 | #test.sh(ermia) 2 | cpu_mhz=2400 3 | extime=3 4 | epoch=3 5 | 6 | result=xoroshiro.dat 7 | rm $result 8 | echo "#worker threads, increments, min, max" >> $result 9 | for ((thread=2; thread<=24; thread+=2)) 10 | do 11 | sum=0 12 | echo "./xoroshiro.exe $thread $cpu_mhz $extime" 13 | 14 | max=0 15 | min=0 16 | for ((i=1; i <= epoch; ++i)) 17 | do 18 | tmp=`./xoroshiro.exe $thread $cpu_mhz $extime` 19 | sum=`echo "$sum + $tmp" | bc -l` 20 | echo "sum: $sum, tmp: $tmp" 21 | 22 | if test $i -eq 1 ; then 23 | max=$tmp 24 | min=$tmp 25 | fi 26 | 27 | flag=`echo "$tmp > $max" | bc -l` 28 | if test $flag -eq 1 ; then 29 | max=$tmp 30 | fi 31 | flag=`echo "$tmp < $min" | bc -l` 32 | if test $flag -eq 1 ; then 33 | min=$tmp 34 | fi 35 | done 36 | avg=`echo "$sum / $epoch" | bc` 37 | echo "sum: $sum, epoch: $epoch" 38 | echo "avg: $avg" 39 | echo "max: $max" 40 | echo "min: $min" 41 | echo "$thread $avg $min $max" >> $result 42 | done 43 | -------------------------------------------------------------------------------- /instruction/xoroshiro.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "../include/random.hh" 6 | #include "../include/tsc.hh" 7 | #include "../include/util.hh" 8 | 9 | #define CLOCKS_PER_US 2100 10 | #define LOOP 1000000 11 | #define EX_TIME 3 12 | 13 | using std::cout; 14 | using std::endl; 15 | 16 | int main() { 17 | Xoroshiro128Plus rnd; 18 | rnd.init(); 19 | 20 | uint64_t start, stop; 21 | start = rdtscp(); 22 | for (uint32_t i = 0; i < UINT32_MAX; ++i) rnd.next(); 23 | stop = rdtscp(); 24 | 25 | cout << "xoroshiro128PlusBench[clocks] :\t" 26 | << (double) (stop - start) / (double) UINT32_MAX << endl; 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /instruction/zipf_dist_test.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "../include/debug.hh" 5 | #include "../include/util.hh" 6 | #include "../include/zipf.hh" 7 | 8 | size_t LENGTH; 9 | double SKEW; 10 | size_t TRIAL; 11 | 12 | int main(const int argc, const char *argv[]) try { 13 | if (argc == 1) { 14 | cout << "./a.out LENGTH SKEW TRIAL" << endl; 15 | exit(0); 16 | } 17 | 18 | LENGTH = atoi(argv[1]); 19 | SKEW = atof(argv[2]); 20 | TRIAL = atoi(argv[3]); 21 | 22 | uint64_t Ctr[LENGTH]; 23 | // if (posix_memalign((void**)&Ctr, CACHE_LINE_SIZE, LENGTH * sizeof(uint64_t))); 24 | Xoroshiro128Plus rnd; 25 | FastZipf zipf(&rnd, SKEW, LENGTH); 26 | 27 | for (size_t i = 0; i < LENGTH; ++i) 28 | Ctr[i] = 0; 29 | 30 | for (size_t i = 0; i < TRIAL; ++i) 31 | ++Ctr[zipf() % LENGTH]; 32 | 33 | cout << "#number : count" << endl; 34 | for (size_t i = 0; i < LENGTH; ++i) { 35 | cout << i << " " << (double) Ctr[i] / (double) TRIAL << endl; 36 | } 37 | 38 | return 0; 39 | } catch (std::bad_alloc) { 40 | ERR; 41 | } 42 | -------------------------------------------------------------------------------- /mocc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(ccbench_mocc 4 | VERSION 0.0.1 5 | DESCRIPTION "mocc of ccbench" 6 | LANGUAGES CXX) 7 | 8 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../cmake") 9 | 10 | option(ENABLE_SANITIZER "enable sanitizer on debug build" ON) 11 | option(ENABLE_UB_SANITIZER "enable undefined behavior sanitizer on debug build" OFF) 12 | option(ENABLE_COVERAGE "enable coverage on debug build" OFF) 13 | 14 | find_package(Doxygen) 15 | find_package(Threads REQUIRED) 16 | find_package(gflags REQUIRED) 17 | find_package(glog REQUIRED) 18 | find_package(Boost 19 | COMPONENTS filesystem) 20 | 21 | include(GNUInstallDirs) 22 | include(CMakePackageConfigHelpers) 23 | include(CompileOptions) 24 | 25 | file(GLOB MOCC_SOURCES 26 | "../common/result.cc" 27 | "../common/util.cc" 28 | "lock.cc" 29 | "mocc.cc" 30 | "result.cc" 31 | "transaction.cc" 32 | "util.cc" 33 | ) 34 | 35 | add_executable(mocc.exe ${MOCC_SOURCES}) 36 | 37 | target_link_libraries(mocc.exe 38 | Boost::filesystem 39 | gflags::gflags 40 | ${PROJECT_SOURCE_DIR}/../third_party/mimalloc/out/release/libmimalloc.a 41 | ${PROJECT_SOURCE_DIR}/../third_party/masstree/libkohler_masstree_json.a 42 | Threads::Threads 43 | ) 44 | 45 | if (DEFINED ADD_ANALYSIS) 46 | add_definitions(-DADD_ANALYSIS=${ADD_ANALYSIS}) 47 | else () 48 | add_definitions(-DADD_ANALYSIS=0) 49 | endif () 50 | 51 | if (DEFINED BACK_OFF) 52 | add_definitions(-DBACK_OFF=${BACK_OFF}) 53 | else () 54 | add_definitions(-DBACK_OFF=0) 55 | endif () 56 | 57 | if (DEFINED KEY_SIZE) 58 | add_definitions(-DKEY_SIZE=${KEY_SIZE}) 59 | else () 60 | add_definitions(-DKEY_SIZE=8) 61 | endif () 62 | 63 | if (DEFINED KEY_SORT) 64 | add_definitions(-DKEY_SORT=${KEY_SORT}) 65 | else () 66 | add_definitions(-DKEY_SORT=0) 67 | endif () 68 | 69 | if (DEFINED MASSTREE_USE) 70 | add_definitions(-DMASSTREE_USE=${MASSTREE_USE}) 71 | else () 72 | add_definitions(-DMASSTREE_USE=1) 73 | endif () 74 | 75 | add_definitions(-DRWLOCK) 76 | 77 | if (DEFINED TEMPERATURE_RESET_OPT) 78 | add_definitions(-DTEMPERATURE_RESET_OPT=${TEMPERATURE_RESET_OPT}) 79 | else () 80 | add_definitions(-DTEMPERATURE_RESET_OPT=1) 81 | endif () 82 | 83 | if (DEFINED VAL_SIZE) 84 | add_definitions(-DVAL_SIZE=${VAL_SIZE}) 85 | else () 86 | add_definitions(-DVAL_SIZE=4) 87 | endif () 88 | -------------------------------------------------------------------------------- /mocc/README.md: -------------------------------------------------------------------------------- 1 | # MOCC 2 | It was proposed at VLDB'2017 by Tianzheng Wang. 3 | 4 | ## How to use 5 | - Build masstree 6 | ``` 7 | $ cd ../ 8 | $ ./bootstrap.sh 9 | ``` 10 | This makes ../third_party/masstree/libkohler_masstree_json.a used by building mocc. 11 | - Build mimalloc 12 | ``` 13 | $ cd ../ 14 | $ ./bootstrap_mimalloc.sh 15 | ``` 16 | This makes ../third_party/mimalloc/out/release/libmimalloc.a used by building mocc. 17 | - Build 18 | ``` 19 | $ mkdir build 20 | $ cd build 21 | $ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release .. 22 | $ ninja 23 | ``` 24 | - Confirm usage 25 | ``` 26 | $ ./mocc.exe -help 27 | ``` 28 | - Execution example 29 | ``` 30 | $ numactl --interleave=all ./mocc.exe -clocks_per_us=2100 -epoch_time=40 -extime=3 -max_ope=10 -rmw=0 -rratio=100 -thread_num=224 -tuple_num=1000000 -ycsb=1 -zipf_skew=0 -per_xx_temp=4096 31 | ``` 32 | 33 | ## How to customize options in CMakeLists.txt 34 | - `ADD_ANALYSIS` : If this is 1, it is deeper analysis than setting 0.
35 | default : `0` 36 | - `BACK_OFF` : If this is 1, it use Cicada's backoff.
37 | default : `0` 38 | - `KEY_SORT` : If this is 1, its transaction accesses records in ascending key order.
39 | default : `0` 40 | - `MASSTREE_USE` : If this is 1, it use masstree as data structure. If not, it use simple array αs data structure. 41 | default : `1` 42 | - `TEMPERATURE_RESET_OPT` : If this is 1, it uses new temprature control protocol which reduces contentions and improves throughput much.
43 | default : `1` 44 | - `VAL_SIZE` : Value of key-value size. In other words, payload size.
45 | default : `4` 46 | 47 | ## Custom build examples 48 | ``` 49 | $ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DKEY_SIZE=1000 -DVAL_SIZE=1000 .. 50 | ``` 51 | - Note: If you re-run cmake, don't forget to remove cmake cache. 52 | ``` 53 | $ rm CMakeCache.txt 54 | ``` 55 | The cmake cache definition data is used in preference to the command line definition data. 56 | 57 | ## Optimizations 58 | - Backoff. 59 | - Early aborts (by setting threshold of whether it executes try lock or wait lock). 60 | - New temprature protocol reduces contentions and improves throughput much. 61 | 62 | ## Missing features 63 | - MQL lock. It uses custom reader-writer lock instead of MQL lock because author's experimental environment has few NUMA architecture. 64 | -------------------------------------------------------------------------------- /mocc/include/atomic_tool.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../include/inline.hh" 4 | 5 | #include "common.hh" 6 | 7 | INLINE uint64_t_64byte loadAcquireGE() { 8 | return __atomic_load_n(&(GlobalEpoch.obj_), __ATOMIC_ACQUIRE); 9 | } 10 | 11 | INLINE void atomicAddGE() { 12 | uint64_t_64byte expected, desired; 13 | 14 | expected = loadAcquireGE(); 15 | for (;;) { 16 | desired.obj_ = expected.obj_ + 1; 17 | if (__atomic_compare_exchange_n(&(GlobalEpoch.obj_), &(expected.obj_), 18 | desired.obj_, false, __ATOMIC_ACQ_REL, 19 | __ATOMIC_ACQUIRE)) 20 | break; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /mocc/include/mocc_op_element.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/op_element.hh" 6 | 7 | using std::cout; 8 | using std::endl; 9 | 10 | template 11 | class ReadElement : public OpElement { 12 | public: 13 | using OpElement::OpElement; 14 | 15 | Tidword tidword_; 16 | char val_[VAL_SIZE]; 17 | bool failed_verification_; 18 | 19 | ReadElement(Tidword tidword, uint64_t key, T *rcdptr, char *newVal) 20 | : OpElement::OpElement(key, rcdptr) { 21 | this->tidword_ = tidword; 22 | memcpy(val_, newVal, VAL_SIZE); 23 | this->failed_verification_ = false; 24 | } 25 | 26 | ReadElement(uint64_t key, T *rcdptr) : OpElement::OpElement(key, rcdptr) { 27 | failed_verification_ = true; 28 | } 29 | 30 | bool operator<(const ReadElement &right) const { 31 | return this->key_ < right.key_; 32 | } 33 | }; 34 | 35 | template 36 | class WriteElement : public OpElement { 37 | public: 38 | using OpElement::OpElement; 39 | 40 | bool operator<(const WriteElement &right) const { 41 | return this->key_ < right.key_; 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /mocc/include/result.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/result.hh" 6 | 7 | extern std::vector MoccResult; 8 | 9 | extern void initResult(); 10 | -------------------------------------------------------------------------------- /mocc/include/transaction.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/procedure.hh" 6 | #include "../../include/result.hh" 7 | #include "../../include/string.hh" 8 | #include "../../include/util.hh" 9 | #include "common.hh" 10 | #include "lock.hh" 11 | #include "mocc_op_element.hh" 12 | #include "tuple.hh" 13 | 14 | using namespace std; 15 | 16 | enum class TransactionStatus : uint8_t { 17 | inFlight, 18 | committed, 19 | aborted, 20 | }; 21 | 22 | class TxExecutor { 23 | public: 24 | vector > read_set_; 25 | vector > write_set_; 26 | vector pro_set_; 27 | #ifdef RWLOCK 28 | vector> RLL_; 29 | vector> CLL_; 30 | #endif // RWLOCK 31 | #ifdef MQLOCK 32 | vector> RLL_; 33 | vector> CLL_; 34 | #endif // MQLOCK 35 | TransactionStatus status_; 36 | 37 | int thid_; 38 | Tidword mrctid_; 39 | Tidword max_rset_; 40 | Tidword max_wset_; 41 | Xoroshiro128Plus *rnd_; 42 | Result *mres_; 43 | 44 | char write_val_[VAL_SIZE] = {}; 45 | char return_val_[VAL_SIZE] = {}; 46 | 47 | TxExecutor(int thid, Xoroshiro128Plus *rnd, Result *mres) 48 | : thid_(thid), mres_(mres) { 49 | read_set_.reserve(FLAGS_max_ope); 50 | write_set_.reserve(FLAGS_max_ope); 51 | pro_set_.reserve(FLAGS_max_ope); 52 | RLL_.reserve(FLAGS_max_ope); 53 | CLL_.reserve(FLAGS_max_ope); 54 | 55 | this->status_ = TransactionStatus::inFlight; 56 | this->rnd_ = rnd; 57 | max_rset_.obj_ = 0; 58 | max_wset_.obj_ = 0; 59 | 60 | genStringRepeatedNumber(write_val_, VAL_SIZE, thid); 61 | } 62 | 63 | ReadElement *searchReadSet(uint64_t key); 64 | 65 | WriteElement *searchWriteSet(uint64_t key); 66 | 67 | template 68 | T *searchRLL(uint64_t key); 69 | 70 | void removeFromCLL(uint64_t key); 71 | 72 | void begin(); 73 | 74 | void read(uint64_t key); 75 | 76 | void write(uint64_t key); 77 | 78 | void read_write(uint64_t key); 79 | 80 | void lock(uint64_t key, Tuple *tuple, bool mode); 81 | 82 | void construct_RLL(); // invoked on abort; 83 | void unlockCLL(); 84 | 85 | bool commit(); 86 | 87 | void abort(); 88 | 89 | void writePhase(); 90 | 91 | void dispCLL(); 92 | 93 | void dispRLL(); 94 | 95 | void dispWS(); 96 | 97 | Tuple *get_tuple(Tuple *table, uint64_t key) { return &table[key]; } 98 | }; 99 | -------------------------------------------------------------------------------- /mocc/include/tuple.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include // memcpy 4 | #include 5 | #include 6 | 7 | #include "lock.hh" 8 | 9 | #include "../../include/cache_line_size.hh" 10 | 11 | #define TEMP_THRESHOLD 5 12 | #define TEMP_MAX 20 13 | #define TEMP_RESET_US 100 14 | 15 | struct Tidword { 16 | union { 17 | uint64_t obj_; 18 | struct { 19 | uint64_t tid: 32; 20 | uint64_t epoch: 32; 21 | }; 22 | }; 23 | 24 | Tidword() { obj_ = 0; } 25 | 26 | bool operator==(const Tidword &right) const { return obj_ == right.obj_; } 27 | 28 | bool operator!=(const Tidword &right) const { return !operator==(right); } 29 | 30 | bool operator<(const Tidword &right) const { return this->obj_ < right.obj_; } 31 | }; 32 | 33 | // 32bit temprature, 32bit epoch 34 | struct Epotemp { 35 | union { 36 | alignas(CACHE_LINE_SIZE) uint64_t obj_; 37 | struct { 38 | uint64_t temp: 32; 39 | uint64_t epoch: 32; 40 | }; 41 | }; 42 | 43 | Epotemp() : obj_(0) {} 44 | 45 | Epotemp(uint64_t temp2, uint64_t epoch2) : temp(temp2), epoch(epoch2) {} 46 | 47 | bool operator==(const Epotemp &right) const { return obj_ == right.obj_; } 48 | 49 | bool operator!=(const Epotemp &right) const { return !operator==(right); } 50 | 51 | bool eqEpoch(uint64_t epo) { 52 | if (epoch == epo) 53 | return true; 54 | else 55 | return false; 56 | } 57 | }; 58 | 59 | class Tuple { 60 | public: 61 | alignas(CACHE_LINE_SIZE) Tidword tidword_; 62 | #ifdef RWLOCK 63 | RWLock rwlock_; // 4byte 64 | // size to here is 20 bytes 65 | #endif 66 | #ifdef MQLOCK 67 | MQLock mqlock_; 68 | #endif 69 | 70 | char val_[VAL_SIZE]; 71 | }; 72 | -------------------------------------------------------------------------------- /mocc/include/util.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern void chkArg(); 4 | 5 | extern bool chkEpochLoaded(); 6 | 7 | extern void displayDB(); 8 | 9 | extern void displayParameter(); 10 | 11 | extern void displayLockedTuple(); 12 | 13 | extern void leaderWork(uint64_t &epoch_timer_start, uint64_t &epoch_timer_stop, 14 | [[maybe_unused]] Result &res); 15 | 16 | extern void makeDB(); 17 | 18 | extern void partTableInit([[maybe_unused]] size_t thid, uint64_t start, 19 | uint64_t end); 20 | 21 | extern void ShowOptParameters(); 22 | -------------------------------------------------------------------------------- /mocc/result.cc: -------------------------------------------------------------------------------- 1 | #include "include/result.hh" 2 | #include "include/common.hh" 3 | 4 | #include "../include/cache_line_size.hh" 5 | #include "../include/result.hh" 6 | 7 | using namespace std; 8 | 9 | alignas(CACHE_LINE_SIZE) std::vector MoccResult; 10 | 11 | void initResult() { MoccResult.resize(FLAGS_thread_num); } 12 | -------------------------------------------------------------------------------- /mocc/script/ycsbA-xrs-cache.sh: -------------------------------------------------------------------------------- 1 | #ycsbA-xrs-cache.sh(mocc) 2 | maxope=10 3 | thread=24 4 | rratio=50 5 | skew=0 6 | ycsb=ON 7 | cpu_mhz=2400 8 | epochtime=40 9 | extime=3 10 | epoch=5 11 | 12 | result=result_mocc_ycsbA_tuple100-10m_cachemiss.dat 13 | rm $result 14 | echo "#tuple num, cache-misses, min, max" >> $result 15 | echo "#./mocc.exe tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $epochtime $extime" >> $result 16 | 17 | for ((tuple=100; tuple<=10000000; tuple*=10)) 18 | do 19 | sum=0 20 | echo "./mocc.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $epochtime $extime" 21 | echo "$tuple $epoch" 22 | 23 | max=0 24 | min=0 25 | for ((i = 1; i <= epoch; ++i)) 26 | do 27 | perf stat -e cache-misses,cache-references -o mocc-cache-ana.txt ./mocc.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $epochtime $extime 28 | tmp=`grep cache-misses ./mocc-cache-ana.txt | awk '{print $4}'` 29 | sum=`echo "$sum + $tmp" | bc -l` 30 | echo "sum: $sum, tmp: $tmp" 31 | 32 | if test $i -eq 1 ; then 33 | max=$tmp 34 | min=$tmp 35 | fi 36 | 37 | flag=`echo "$tmp > $max" | bc -l` 38 | if test $flag -eq 1 ; then 39 | max=$tmp 40 | fi 41 | flag=`echo "$tmp < $min" | bc -l` 42 | if test $flag -eq 1 ; then 43 | min=$tmp 44 | fi 45 | done 46 | avg=`echo "$sum / $epoch" | bc -l` 47 | echo "sum: $sum, epoch: $epoch" 48 | echo "avg $avg" 49 | echo "max: $max" 50 | echo "min: $min" 51 | echo "$tuple $avg $min $max" >> $result 52 | done 53 | 54 | -------------------------------------------------------------------------------- /occ/Makefile: -------------------------------------------------------------------------------- 1 | PROG1 = occ.exe 2 | SV_FORMAT_SRCS1 := occ.cc transaction.cc util.cc result.cc 3 | 4 | REL := ../common/ 5 | include $(REL)Makefile 6 | SV_FORMAT_ALLSRC = $(SV_FORMAT_SRCS1) $(SRCS2) $(wildcard include/*.hh) 7 | 8 | # start of initialization of some parameters. 9 | ADD_ANALYSIS=1 10 | BACK_OFF=0 11 | KEY_SIZE=8 12 | MASSTREE_USE=1 13 | PARTITION_TABLE=0 14 | PROCEDURE_SORT=0 15 | OCC_GC_THRESHOLD=10000 # How many write sets to keep 16 | VAL_SIZE=4 17 | WAL=0 18 | # end of initialization 19 | 20 | CC = g++ 21 | CFLAGS = -c -pipe -g -O3 -std=c++17 -march=native \ 22 | -Wall -Wextra -Wdangling-else -Wchkp -Winvalid-memory-model \ 23 | -D$(shell uname) \ 24 | -D$(shell hostname) \ 25 | -DKEY_SIZE=$(KEY_SIZE) \ 26 | -DVAL_SIZE=$(VAL_SIZE) \ 27 | -DADD_ANALYSIS=$(ADD_ANALYSIS) \ 28 | -DBACK_OFF=$(BACK_OFF) \ 29 | -DMASSTREE_USE=$(MASSTREE_USE) \ 30 | -DNO_WAIT_LOCKING_IN_VALIDATION=$(NO_WAIT_LOCKING_IN_VALIDATION) \ 31 | -DNO_WAIT_OF_TICTOC=$(NO_WAIT_OF_TICTOC) \ 32 | -DPARTITION_TABLE=$(PARTITION_TABLE) \ 33 | -DPROCEDURE_SORT=$(PROCEDURE_SORT) \ 34 | -DOCC_GC_THRESHOLD=$(OCC_GC_THRESHOLD) \ 35 | -DWAL=$(WAL) \ 36 | 37 | INCLUDE = -I/usr/include \ 38 | -I../third_party/ \ 39 | 40 | LDLIBS = -lpthread -lboost_filesystem -lboost_system -lgflags -lglog 41 | 42 | OBJS1 = $(SV_FORMAT_SRCS1:.cc=.o) 43 | 44 | all: $(PROG1) 45 | 46 | include ../include/MakefileForMasstreeUse 47 | $(PROG1) : $(OBJS1) $(MASSOBJ) 48 | $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) $(INCLUDE) 49 | 50 | .cc.o: 51 | $(CC) $(CFLAGS) -c $< -o $@ 52 | 53 | format: 54 | clang-format -i -verbose -style=Google $(SV_FORMAT_ALLSRC) 55 | 56 | clean: 57 | rm -f *~ *.o *.exe *.stackdump 58 | rm -f ../common/*~ ../common/*.o ../common/*.exe ../common/*.stackdump 59 | rm -rf .deps 60 | -------------------------------------------------------------------------------- /occ/README.md: -------------------------------------------------------------------------------- 1 | # OCC 2 | The original proposal is as follows. 3 | 4 | ``` 5 | H. T. Kung and John T. Robinson. 1981. 6 | On optimistic methods for concurrency control. 7 | ACM Trans. Database Syst. 6, 2 (June 1981), 213-226. 8 | DOI=http://dx.doi.org/10.1145/319566.319567 9 | ``` 10 | 11 | ## How to use 12 | - Build 13 | ``` 14 | $ make 15 | ``` 16 | - Confirm usage 17 | ``` 18 | $ ./occ.exe -help 19 | ``` 20 | - Execution example 21 | ``` 22 | $ numactl --interleave=all ./occ.exe -tuple_num=1000 -max_ope=10 -thread_num=224 -rratio=100 -rmw=0 -zipf_skew=0 -ycsb=1 -clocks_per_us=2100 -extime=3 23 | ``` 24 | 25 | ## How to select build options in Makefile 26 | - `OCC_GC_THRESHOLD` : Number of committed write sets to be kept before performing garbage collection. 27 | - `ADD_ANALYSIS` : If this is 1, it is deeper analysis than setting 0 (currently no analysis point for OCC). 28 | - `BACK_OFF` : If this is 1, it use backoff. 29 | - `MASSTREE_USE` : If this is 1, it use masstree as data structure. If not, it use simple array αs data structure. 30 | - `PARTITION_TABLE` : If this is 1, it devide the table into the number of worker threads not to occur read/write conflicts. 31 | - `VAL_SIZE` : Value of key-value size. In other words, payload size. 32 | 33 | ## Optimizations 34 | - Backoff. 35 | -------------------------------------------------------------------------------- /occ/include/atomic_tool.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.hh" 4 | 5 | #include "../../include/inline.hh" 6 | 7 | INLINE uint64_t atomicLoadGE(); 8 | 9 | INLINE void atomicAddGE() { 10 | uint64_t expected, desired; 11 | 12 | expected = atomicLoadGE(); 13 | for (;;) { 14 | desired = expected + 1; 15 | if (__atomic_compare_exchange_n(&(GlobalEpoch.obj_), &expected, desired, 16 | false, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) 17 | break; 18 | } 19 | } 20 | 21 | INLINE uint64_t atomicLoadGE() { 22 | uint64_t_64byte result = 23 | __atomic_load_n(&(GlobalEpoch.obj_), __ATOMIC_ACQUIRE); 24 | return result.obj_; 25 | } 26 | 27 | INLINE void atomicStoreThLocalEpoch(unsigned int thid, uint64_t newval) { 28 | __atomic_store_n(&(ThLocalEpoch[thid].obj_), newval, __ATOMIC_RELEASE); 29 | } 30 | -------------------------------------------------------------------------------- /occ/include/common.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "tuple.hh" 8 | 9 | #include "../../include/cache_line_size.hh" 10 | #include "../../include/int64byte.hh" 11 | #include "../../include/masstree_wrapper.hh" 12 | 13 | #include "gflags/gflags.h" 14 | #include "glog/logging.h" 15 | 16 | #ifdef GLOBAL_VALUE_DEFINE 17 | #define GLOBAL 18 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte GlobalEpoch(1); 19 | #if MASSTREE_USE 20 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 21 | #endif 22 | #else 23 | #define GLOBAL extern 24 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte GlobalEpoch; 25 | #if MASSTREE_USE 26 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 27 | #endif 28 | #endif 29 | 30 | #ifdef GLOBAL_VALUE_DEFINE 31 | DEFINE_uint64(clocks_per_us, 2100, 32 | "CPU_MHz. Use this info for measuring time."); 33 | DEFINE_uint64(epoch_time, 40, "Epoch interval[msec]."); 34 | DEFINE_uint64(extime, 3, "Execution time[sec]."); 35 | DEFINE_uint64(max_ope, 10, 36 | "Total number of operations per single transaction."); 37 | DEFINE_bool(rmw, false, 38 | "True means read modify write, false means blind write."); 39 | DEFINE_uint64(rratio, 50, "read ratio of single transaction."); 40 | DEFINE_uint64(thread_num, 10, "Total number of worker threads."); 41 | DEFINE_uint64(tuple_num, 1000000, "Total number of records."); 42 | DEFINE_bool(ycsb, true, 43 | "True uses zipf_skew, false uses faster random generator."); 44 | DEFINE_double(zipf_skew, 0, "zipf skew. 0 ~ 0.999..."); 45 | #else 46 | DECLARE_uint64(clocks_per_us); 47 | DECLARE_uint64(epoch_time); 48 | DECLARE_uint64(extime); 49 | DECLARE_uint64(max_ope); 50 | DECLARE_bool(rmw); 51 | DECLARE_uint64(rratio); 52 | DECLARE_uint64(thread_num); 53 | DECLARE_uint64(tuple_num); 54 | DECLARE_bool(ycsb); 55 | DECLARE_double(zipf_skew); 56 | #endif 57 | 58 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte *ThLocalEpoch; 59 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte *CTIDW; 60 | 61 | alignas(CACHE_LINE_SIZE) GLOBAL Tuple *Table; 62 | -------------------------------------------------------------------------------- /occ/include/log.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | class LogHeader { 9 | public: 10 | int chkSum_ = 0; 11 | unsigned int logRecNum_ = 0; 12 | const std::size_t len_val_ = VAL_SIZE; 13 | 14 | void init() { 15 | chkSum_ = 0; 16 | logRecNum_ = 0; 17 | } 18 | 19 | void convertChkSumIntoComplementOnTwo() { 20 | chkSum_ ^= 0xffffffff; 21 | ++chkSum_; 22 | } 23 | }; 24 | 25 | class LogRecord { 26 | public: 27 | uint64_t tid_; 28 | unsigned int key_; 29 | char val_[VAL_SIZE]; 30 | 31 | LogRecord() : tid_(0), key_(0) {} 32 | 33 | LogRecord(uint64_t tid, unsigned int key, char *val) : tid_(tid), key_(key) { 34 | memcpy(this->val_, val, VAL_SIZE); 35 | } 36 | 37 | int computeChkSum() { 38 | // compute checksum 39 | int chkSum = 0; 40 | int *itr = (int *)this; 41 | for (unsigned int i = 0; i < sizeof(LogRecord) / sizeof(int); ++i) { 42 | chkSum += (*itr); 43 | ++itr; 44 | } 45 | 46 | return chkSum; 47 | } 48 | }; 49 | 50 | class LogPackage { 51 | public: 52 | LogHeader header_; 53 | std::unique_ptr log_records_; 54 | }; 55 | -------------------------------------------------------------------------------- /occ/include/occ_op_element.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../include/op_element.hh" 4 | 5 | template 6 | class ReadElement : public OpElement { 7 | public: 8 | using OpElement::OpElement; 9 | 10 | char val_[VAL_SIZE]; 11 | 12 | ReadElement(uint64_t key, T* rcdptr, char* val) 13 | : OpElement::OpElement(key, rcdptr) { 14 | memcpy(this->val_, val, VAL_SIZE); 15 | } 16 | 17 | bool operator<(const ReadElement& right) const { 18 | return this->key_ < right.key_; 19 | } 20 | }; 21 | 22 | template 23 | class WriteElement : public OpElement { 24 | public: 25 | using OpElement::OpElement; 26 | 27 | WriteElement(uint64_t key, T* rcdptr) 28 | : OpElement::OpElement(key, rcdptr) {} 29 | 30 | bool operator<(const WriteElement& right) const { 31 | return this->key_ < right.key_; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /occ/include/result.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/result.hh" 6 | 7 | extern std::vector OccResult; 8 | 9 | extern void initResult(); 10 | -------------------------------------------------------------------------------- /occ/include/tuple.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "../../include/cache_line_size.hh" 10 | 11 | class Tuple { 12 | public: 13 | char val_[VAL_SIZE]; 14 | }; 15 | -------------------------------------------------------------------------------- /occ/include/util.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern void chkArg(); 4 | 5 | extern bool chkEpochLoaded(); 6 | 7 | extern void displayDB(); 8 | 9 | extern void displayParameter(); 10 | 11 | extern void genLogFile(std::string &logpath, const int thid); 12 | 13 | extern void leaderWork(); 14 | 15 | extern void makeDB(); 16 | 17 | extern void partTableInit([[maybe_unused]] size_t thid, uint64_t start, 18 | uint64_t end); 19 | 20 | extern void ShowOptParameters(); 21 | -------------------------------------------------------------------------------- /occ/result.cc: -------------------------------------------------------------------------------- 1 | #include "include/result.hh" 2 | #include "include/common.hh" 3 | 4 | #include "../include/cache_line_size.hh" 5 | #include "../include/result.hh" 6 | 7 | using namespace std; 8 | 9 | /** 10 | * Please declare it with an appropriate name. 11 | */ 12 | alignas(CACHE_LINE_SIZE) std::vector OccResult; 13 | 14 | void initResult() { OccResult.resize(FLAGS_thread_num); } 15 | -------------------------------------------------------------------------------- /si/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(ccbench_si 4 | VERSION 0.0.1 5 | DESCRIPTION "si of ccbench" 6 | LANGUAGES CXX) 7 | 8 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../cmake") 9 | 10 | option(ENABLE_SANITIZER "enable sanitizer on debug build" ON) 11 | option(ENABLE_UB_SANITIZER "enable undefined behavior sanitizer on debug build" OFF) 12 | option(ENABLE_COVERAGE "enable coverage on debug build" OFF) 13 | 14 | find_package(Doxygen) 15 | find_package(Threads REQUIRED) 16 | find_package(gflags REQUIRED) 17 | find_package(glog REQUIRED) 18 | find_package(Boost 19 | COMPONENTS filesystem) 20 | 21 | include(GNUInstallDirs) 22 | include(CMakePackageConfigHelpers) 23 | include(CompileOptions) 24 | 25 | file(GLOB SI_SOURCES 26 | "../common/result.cc" 27 | "../common/util.cc" 28 | "si.cc" 29 | "garbage_collection.cc" 30 | "result.cc" 31 | "transaction.cc" 32 | "util.cc" 33 | ) 34 | 35 | add_executable(si.exe ${SI_SOURCES}) 36 | 37 | target_link_libraries(si.exe 38 | Boost::filesystem 39 | gflags::gflags 40 | ${PROJECT_SOURCE_DIR}/../third_party/mimalloc/out/release/libmimalloc.a 41 | ${PROJECT_SOURCE_DIR}/../third_party/masstree/libkohler_masstree_json.a 42 | Threads::Threads 43 | ) 44 | 45 | if (DEFINED ADD_ANALYSIS) 46 | add_definitions(-DADD_ANALYSIS=${ADD_ANALYSIS}) 47 | else () 48 | add_definitions(-DADD_ANALYSIS=0) 49 | endif () 50 | 51 | if (DEFINED BACK_OFF) 52 | add_definitions(-DBACK_OFF=${BACK_OFF}) 53 | else () 54 | add_definitions(-DBACK_OFF=0) 55 | endif () 56 | 57 | add_definitions(-DCCTR_ON) 58 | 59 | if (DEFINED KEY_SIZE) 60 | add_definitions(-DKEY_SIZE=${KEY_SIZE}) 61 | else () 62 | add_definitions(-DKEY_SIZE=8) 63 | endif () 64 | 65 | if (DEFINED MASSTREE_USE) 66 | add_definitions(-DMASSTREE_USE=${MASSTREE_USE}) 67 | else () 68 | add_definitions(-DMASSTREE_USE=1) 69 | endif () 70 | 71 | if (DEFINED VAL_SIZE) 72 | add_definitions(-DVAL_SIZE=${VAL_SIZE}) 73 | else () 74 | add_definitions(-DVAL_SIZE=4) 75 | endif () 76 | -------------------------------------------------------------------------------- /si/include/common.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "../../include/cache_line_size.hh" 7 | #include "../../include/int64byte.hh" 8 | #include "../../include/masstree_wrapper.hh" 9 | #include "transaction_table.hh" 10 | #include "tuple.hh" 11 | 12 | #include "gflags/gflags.h" 13 | #include "glog/logging.h" 14 | 15 | #ifdef GLOBAL_VALUE_DEFINE 16 | #define GLOBAL 17 | alignas(CACHE_LINE_SIZE) GLOBAL std::atomic CCtr(0); 18 | #if MASSTREE_USE 19 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 20 | #endif 21 | #else 22 | #define GLOBAL extern 23 | alignas(CACHE_LINE_SIZE) GLOBAL std::atomic CCtr; 24 | #if MASSTREE_USE 25 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 26 | #endif 27 | #endif 28 | 29 | #ifdef GLOBAL_VALUE_DEFINE 30 | DEFINE_uint64(clocks_per_us, 2100, 31 | "CPU_MHz. Use this info for measuring time."); 32 | DEFINE_uint64(extime, 3, "Execution time[sec]."); 33 | DEFINE_uint64(gc_inter_us, 10, "GC interval[us]."); 34 | DEFINE_uint64(max_ope, 10, 35 | "Total number of operations per single transaction."); 36 | DEFINE_uint64( 37 | pre_reserve_tmt_element, 100, 38 | "Pre-allocating memory for the transaction mapping table elements."); 39 | DEFINE_uint64(pre_reserve_version, 10000, 40 | "Pre-allocating memory for the version."); 41 | DEFINE_bool(rmw, false, 42 | "True means read modify write, false means blind write."); 43 | DEFINE_uint64(rratio, 50, "read ratio of single transaction."); 44 | DEFINE_uint64(thread_num, 10, "Total number of worker threads."); 45 | DEFINE_uint64(tuple_num, 1000000, "Total number of records."); 46 | DEFINE_bool(ycsb, true, 47 | "True uses zipf_skew, false uses faster random generator."); 48 | DEFINE_double(zipf_skew, 0, "zipf skew. 0 ~ 0.999..."); 49 | #else 50 | DECLARE_uint64(clocks_per_us); 51 | DECLARE_uint64(extime); 52 | DECLARE_uint64(gc_inter_us); 53 | DECLARE_uint64(max_ope); 54 | DECLARE_uint64(pre_reserve_tmt_element); 55 | DECLARE_uint64(pre_reserve_version); 56 | DECLARE_bool(rmw); 57 | DECLARE_uint64(rratio); 58 | DECLARE_uint64(thread_num); 59 | DECLARE_uint64(tuple_num); 60 | DECLARE_bool(ycsb); 61 | DECLARE_double(zipf_skew); 62 | #endif 63 | 64 | #include "transaction.hh" 65 | 66 | alignas(CACHE_LINE_SIZE) GLOBAL Tuple *Table; 67 | alignas(CACHE_LINE_SIZE) GLOBAL 68 | TransactionTable **TMT; // Transaction Mapping Table 69 | -------------------------------------------------------------------------------- /si/include/garbage_collection.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "../../include/inline.hh" 7 | #include "../../include/result.hh" 8 | #include "si_op_element.hh" 9 | #include "tuple.hh" 10 | #include "version.hh" 11 | 12 | // forward declaration 13 | class TransactionTable; 14 | 15 | class GarbageCollection { 16 | private: 17 | uint32_t fmin_, fmax_; // first range of txid in TMT. 18 | uint32_t smin_, smax_; // second range of txid in TMT. 19 | 20 | static std::atomic 21 | GC_threshold_; // share for all object (meaning all thread). 22 | 23 | public: 24 | // deque を使うのは,どこまでサイズが肥大するか不明瞭であるから. 25 | // vector のリサイズは要素の全コピーが発生するなどして重いから. 26 | #ifdef CCTR_ON 27 | std::deque gcq_for_TMT_; 28 | std::deque reuse_TMT_element_from_gc_; 29 | #endif // CCTR_ON 30 | std::deque > gcq_for_versions_; 31 | std::deque reuse_version_from_gc_; 32 | uint8_t thid_; 33 | 34 | GarbageCollection() { 35 | //#ifdef CCTR_ON 36 | // gcqForTMT.resize(1000); 37 | //#endif // CCTR_ON 38 | // gcqForVersion.resize(1000); 39 | } 40 | 41 | // for all thread 42 | INLINE uint32_t getGcThreshold() { 43 | return GC_threshold_.load(std::memory_order_acquire); 44 | } 45 | // ----- 46 | 47 | // for leader thread 48 | bool chkSecondRange(); 49 | 50 | void decideFirstRange(); 51 | 52 | INLINE void decideGcThreshold() { 53 | GC_threshold_.store(fmin_, std::memory_order_release); 54 | } 55 | 56 | INLINE void mvSecondRangeToFirstRange() { 57 | fmin_ = smin_; 58 | fmax_ = smax_; 59 | } 60 | // ----- 61 | 62 | // for worker thread 63 | void gcVersion(Result *sres_); 64 | 65 | #ifdef CCTR_ON 66 | void gcTMTElements(Result *sres_); 67 | #endif // CCTR_ON 68 | // ----- 69 | }; 70 | 71 | #ifdef GLOBAL_VALUE_DEFINE 72 | // declare in ermia.cc 73 | std::atomic GarbageCollection::GC_threshold_(0); 74 | #endif 75 | -------------------------------------------------------------------------------- /si/include/result.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/result.hh" 6 | 7 | extern std::vector SIResult; 8 | 9 | extern void initResult(); 10 | -------------------------------------------------------------------------------- /si/include/si_op_element.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../include/op_element.hh" 4 | 5 | #include "transaction_table.hh" 6 | #include "version.hh" 7 | 8 | template 9 | class SetElement : public OpElement { 10 | public: 11 | using OpElement::OpElement; 12 | 13 | Version *ver_; 14 | 15 | SetElement(uint64_t key, T *rcdptr, Version *ver) 16 | : OpElement::OpElement(key, rcdptr) { 17 | this->ver_ = ver; 18 | } 19 | 20 | bool operator<(const SetElement &right) const { 21 | return this->key_ < right.key; 22 | } 23 | }; 24 | 25 | template 26 | class GCElement : public OpElement { 27 | public: 28 | using OpElement::OpElement; 29 | 30 | Version *ver_; 31 | uint32_t cstamp_; 32 | 33 | GCElement() : OpElement::OpElement() { 34 | this->ver_ = nullptr; 35 | cstamp_ = 0; 36 | } 37 | 38 | GCElement(uint64_t key, T *rcdptr, Version *ver, uint32_t cstamp) 39 | : OpElement::OpElement(key, rcdptr) { 40 | this->ver_ = ver; 41 | this->cstamp_ = cstamp; 42 | } 43 | }; 44 | 45 | class GCTMTElement { 46 | public: 47 | TransactionTable *tmt_; 48 | 49 | GCTMTElement() : tmt_(nullptr) {} 50 | 51 | GCTMTElement(TransactionTable *tmt) : tmt_(tmt) {} 52 | }; 53 | -------------------------------------------------------------------------------- /si/include/transaction.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../../include/config.hh" 8 | #include "../../include/procedure.hh" 9 | #include "../../include/result.hh" 10 | #include "../../include/string.hh" 11 | #include "../../include/util.hh" 12 | #include "common.hh" 13 | #include "garbage_collection.hh" 14 | #include "tuple.hh" 15 | #include "version.hh" 16 | 17 | enum class TransactionStatus : uint8_t { 18 | inFlight, 19 | committing, 20 | committed, 21 | aborted, 22 | }; 23 | 24 | class TxExecutor { 25 | public: 26 | uint8_t thid_; // thread ID 27 | uint32_t cstamp_ = 0; // Transaction end time, c(T) 28 | uint32_t 29 | txid_; // TID and begin timestamp - the current log sequence number (LSN) 30 | uint32_t pre_gc_threshold_ = 0; 31 | uint64_t gcstart_, gcstop_; 32 | char return_val_[VAL_SIZE] = {}; 33 | char write_val_[VAL_SIZE] = {}; 34 | 35 | std::vector> read_set_; 36 | std::vector> write_set_; 37 | std::vector pro_set_; 38 | 39 | GarbageCollection gcobject_; 40 | Result *sres_; 41 | TransactionStatus status_ = 42 | TransactionStatus::inFlight; // Status: inFlight, committed, or aborted 43 | 44 | TxExecutor(uint8_t thid, unsigned int max_ope, Result *sres) 45 | : thid_(thid), sres_(sres) { 46 | gcobject_.thid_ = thid; 47 | read_set_.reserve(max_ope); 48 | write_set_.reserve(max_ope); 49 | pro_set_.reserve(max_ope); 50 | 51 | if (FLAGS_pre_reserve_tmt_element) { 52 | for (size_t i = 0; i < FLAGS_pre_reserve_tmt_element; ++i) 53 | gcobject_.reuse_TMT_element_from_gc_.emplace_back( 54 | new TransactionTable()); 55 | } 56 | 57 | if (FLAGS_pre_reserve_version) { 58 | for (size_t i = 0; i < FLAGS_pre_reserve_version; ++i) { 59 | gcobject_.reuse_version_from_gc_.emplace_back(new Version()); 60 | } 61 | } 62 | 63 | genStringRepeatedNumber(write_val_, VAL_SIZE, thid); 64 | } 65 | 66 | SetElement *searchReadSet(uint64_t key); 67 | 68 | SetElement *searchWriteSet(uint64_t key); 69 | 70 | void tbegin(); 71 | 72 | void tread(uint64_t key); 73 | 74 | void twrite(uint64_t key); 75 | 76 | void commit(); 77 | 78 | void abort(); 79 | 80 | void mainte(); 81 | 82 | void dispWS(); 83 | 84 | void dispRS(); 85 | 86 | static Tuple *get_tuple(Tuple *table, uint64_t key) { return &table[key]; } 87 | }; 88 | -------------------------------------------------------------------------------- /si/include/transaction_table.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class TransactionTable { 4 | public: 5 | alignas(CACHE_LINE_SIZE) std::atomic txid_; 6 | std::atomic lastcstamp_; 7 | 8 | TransactionTable() {}; 9 | 10 | TransactionTable(uint32_t txid, uint32_t lastcstamp) { 11 | this->txid_.store(txid, std::memory_order_relaxed); 12 | this->lastcstamp_.store(lastcstamp, std::memory_order_relaxed); 13 | } 14 | 15 | void set(uint32_t txid, uint32_t lastcstamp) { 16 | this->txid_.store(txid, std::memory_order_relaxed); 17 | this->lastcstamp_.store(lastcstamp, std::memory_order_relaxed); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /si/include/tuple.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "../../include/cache_line_size.hh" 7 | 8 | #include "version.hh" 9 | 10 | class Tuple { 11 | public: 12 | alignas(CACHE_LINE_SIZE) std::atomic latest_; 13 | std::atomic min_cstamp_; 14 | std::atomic g_clock_; 15 | 16 | Tuple() { 17 | latest_.store(nullptr); 18 | g_clock_.store(0, std::memory_order_release); 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /si/include/util.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern void chkArg(); 4 | 5 | extern void displayDB(); 6 | 7 | extern void displayParameter(); 8 | 9 | extern void leaderWork(GarbageCollection &gcob); 10 | 11 | extern void makeDB(); 12 | 13 | extern void naiveGarbageCollection(const bool &quit); 14 | 15 | extern void partTableInit([[maybe_unused]] size_t thid, uint64_t start, 16 | uint64_t end); 17 | 18 | extern void ShowOptParameters(); 19 | -------------------------------------------------------------------------------- /si/result.cc: -------------------------------------------------------------------------------- 1 | #include "include/result.hh" 2 | #include "include/common.hh" 3 | 4 | #include "../include/cache_line_size.hh" 5 | #include "../include/result.hh" 6 | 7 | using namespace std; 8 | 9 | alignas(CACHE_LINE_SIZE) std::vector SIResult; 10 | 11 | void initResult() { SIResult.resize(FLAGS_thread_num); } 12 | -------------------------------------------------------------------------------- /si/script/ycsbA-xrs-cache.sh: -------------------------------------------------------------------------------- 1 | #ycsbA-xrs-cache.sh(si) 2 | maxope=10 3 | thread=24 4 | rratio=50 5 | skew=0 6 | ycsb=ON 7 | cpu_mhz=2400 8 | extime=3 9 | epoch=5 10 | 11 | result=result_si_ycsbA_tuple100-10m_cachemiss.dat 12 | rm $result 13 | echo "#tuple num, cache-misses, min, max" >> $result 14 | echo "#./si.exe tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $extime" >> $result 15 | 16 | for ((tuple=100; tuple<=10000000; tuple*=10)) 17 | do 18 | sum=0 19 | echo "./si.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $extime" 20 | echo "$tuple $epoch" 21 | 22 | max=0 23 | min=0 24 | for ((i = 1; i <= epoch; ++i)) 25 | do 26 | perf stat -e cache-misses,cache-references -o si-cache-ana.txt ./si.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $extime 27 | tmp=`grep cache-misses ./si-cache-ana.txt | awk '{print $4}'` 28 | sum=`echo "$sum + $tmp" | bc -l` 29 | echo "sum: $sum, tmp: $tmp" 30 | 31 | if test $i -eq 1 ; then 32 | max=$tmp 33 | min=$tmp 34 | fi 35 | 36 | flag=`echo "$tmp > $max" | bc -l` 37 | if test $flag -eq 1 ; then 38 | max=$tmp 39 | fi 40 | flag=`echo "$tmp < $min" | bc -l` 41 | if test $flag -eq 1 ; then 42 | min=$tmp 43 | fi 44 | done 45 | avg=`echo "$sum / $epoch" | bc -l` 46 | echo "sum: $sum, epoch: $epoch" 47 | echo "avg $avg" 48 | echo "max: $max" 49 | echo "min: $min" 50 | echo "$tuple $avg $min $max" >> $result 51 | done 52 | 53 | -------------------------------------------------------------------------------- /silo/include/atomic_tool.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.hh" 4 | 5 | #include "../../include/inline.hh" 6 | 7 | INLINE uint64_t atomicLoadGE(); 8 | 9 | INLINE void atomicAddGE() { 10 | uint64_t expected, desired; 11 | 12 | expected = atomicLoadGE(); 13 | for (;;) { 14 | desired = expected + 1; 15 | if (__atomic_compare_exchange_n(&(GlobalEpoch.obj_), &expected, desired, 16 | false, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) 17 | break; 18 | } 19 | } 20 | 21 | INLINE uint64_t atomicLoadGE() { 22 | uint64_t_64byte result = 23 | __atomic_load_n(&(GlobalEpoch.obj_), __ATOMIC_ACQUIRE); 24 | return result.obj_; 25 | } 26 | 27 | INLINE void atomicStoreThLocalEpoch(unsigned int thid, uint64_t newval) { 28 | __atomic_store_n(&(ThLocalEpoch[thid].obj_), newval, __ATOMIC_RELEASE); 29 | } 30 | -------------------------------------------------------------------------------- /silo/include/common.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "tuple.hh" 9 | 10 | #include "../../include/cache_line_size.hh" 11 | #include "../../include/int64byte.hh" 12 | #include "../../include/masstree_wrapper.hh" 13 | 14 | #include "gflags/gflags.h" 15 | #include "glog/logging.h" 16 | 17 | #ifdef GLOBAL_VALUE_DEFINE 18 | #define GLOBAL 19 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte GlobalEpoch(1); 20 | #if MASSTREE_USE 21 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 22 | #endif 23 | #else 24 | #define GLOBAL extern 25 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte GlobalEpoch; 26 | #if MASSTREE_USE 27 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 28 | #endif 29 | #endif 30 | 31 | #ifdef GLOBAL_VALUE_DEFINE 32 | DEFINE_uint64(clocks_per_us, 2100, 33 | "CPU_MHz. Use this info for measuring time."); 34 | DEFINE_uint64(epoch_time, 40, "Epoch interval[msec]."); 35 | DEFINE_uint64(extime, 3, "Execution time[sec]."); 36 | DEFINE_uint64(max_ope, 10, 37 | "Total number of operations per single transaction."); 38 | DEFINE_bool(rmw, false, 39 | "True means read modify write, false means blind write."); 40 | DEFINE_uint64(rratio, 50, "read ratio of single transaction."); 41 | DEFINE_uint64(thread_num, 10, "Total number of worker threads."); 42 | DEFINE_uint64(tuple_num, 1000000, "Total number of records."); 43 | DEFINE_bool(ycsb, true, 44 | "True uses zipf_skew, false uses faster random generator."); 45 | DEFINE_double(zipf_skew, 0, "zipf skew. 0 ~ 0.999..."); 46 | #else 47 | DECLARE_uint64(clocks_per_us); 48 | DECLARE_uint64(epoch_time); 49 | DECLARE_uint64(extime); 50 | DECLARE_uint64(max_ope); 51 | DECLARE_bool(rmw); 52 | DECLARE_uint64(rratio); 53 | DECLARE_uint64(thread_num); 54 | DECLARE_uint64(tuple_num); 55 | DECLARE_bool(ycsb); 56 | DECLARE_double(zipf_skew); 57 | #endif 58 | 59 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte *ThLocalEpoch; 60 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte *CTIDW; 61 | 62 | alignas(CACHE_LINE_SIZE) GLOBAL Tuple *Table; 63 | -------------------------------------------------------------------------------- /silo/include/log.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | class LogHeader { 9 | public: 10 | int chkSum_ = 0; 11 | unsigned int logRecNum_ = 0; 12 | const std::size_t len_val_ = VAL_SIZE; 13 | 14 | void init() { 15 | chkSum_ = 0; 16 | logRecNum_ = 0; 17 | } 18 | 19 | void convertChkSumIntoComplementOnTwo() { 20 | chkSum_ ^= 0xffffffff; 21 | ++chkSum_; 22 | } 23 | }; 24 | 25 | class LogRecord { 26 | public: 27 | uint64_t tid_; 28 | unsigned int key_; 29 | char val_[VAL_SIZE]; 30 | 31 | LogRecord() : tid_(0), key_(0) {} 32 | 33 | LogRecord(uint64_t tid, unsigned int key, char *val) : tid_(tid), key_(key) { 34 | memcpy(this->val_, val, VAL_SIZE); 35 | } 36 | 37 | int computeChkSum() { 38 | // compute checksum 39 | int chkSum = 0; 40 | int *itr = (int *) this; 41 | for (unsigned int i = 0; i < sizeof(LogRecord) / sizeof(int); ++i) { 42 | chkSum += (*itr); 43 | ++itr; 44 | } 45 | 46 | return chkSum; 47 | } 48 | }; 49 | 50 | class LogPackage { 51 | public: 52 | LogHeader header_; 53 | std::unique_ptr log_records_; 54 | }; 55 | -------------------------------------------------------------------------------- /silo/include/result.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/result.hh" 6 | 7 | extern std::vector SiloResult; 8 | 9 | extern void initResult(); 10 | -------------------------------------------------------------------------------- /silo/include/silo_op_element.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/op_element.hh" 6 | 7 | template 8 | class ReadElement : public OpElement { 9 | public: 10 | using OpElement::OpElement; 11 | 12 | 13 | ReadElement(uint64_t key, T *rcdptr, char *val, Tidword tidword) 14 | : OpElement::OpElement(key, rcdptr) { 15 | tidword_.obj_ = tidword.obj_; 16 | memcpy(this->val_, val, VAL_SIZE); 17 | } 18 | 19 | bool operator<(const ReadElement &right) const { 20 | return this->key_ < right.key_; 21 | } 22 | 23 | Tidword get_tidword() { 24 | return tidword_; 25 | } 26 | 27 | private: 28 | Tidword tidword_; 29 | char val_[VAL_SIZE]; 30 | }; 31 | 32 | template 33 | class WriteElement : public OpElement { 34 | public: 35 | using OpElement::OpElement; 36 | 37 | WriteElement(uint64_t key, T *rcdptr, std::string_view val) 38 | : OpElement::OpElement(key, rcdptr) { 39 | static_assert(std::string_view("").size() == 0, "Expected behavior was broken."); 40 | if (val.size() != 0) { 41 | val_ptr_ = std::make_unique(val.size()); 42 | memcpy(val_ptr_.get(), val.data(), val.size()); 43 | val_length_ = val.size(); 44 | } else { 45 | val_length_ = 0; 46 | } 47 | // else : fast approach for benchmark 48 | } 49 | 50 | bool operator<(const WriteElement &right) const { 51 | return this->key_ < right.key_; 52 | } 53 | 54 | char *get_val_ptr() { 55 | return val_ptr_.get(); 56 | } 57 | 58 | std::size_t get_val_length() { 59 | return val_length_; 60 | } 61 | 62 | private: 63 | std::unique_ptr val_ptr_; // NOLINT 64 | std::size_t val_length_{}; 65 | }; 66 | -------------------------------------------------------------------------------- /silo/include/tuple.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "../../include/cache_line_size.hh" 10 | 11 | struct Tidword { 12 | union { 13 | uint64_t obj_; 14 | struct { 15 | bool lock: 1; 16 | bool latest: 1; 17 | bool absent: 1; 18 | uint64_t tid: 29; 19 | uint64_t epoch: 32; 20 | }; 21 | }; 22 | 23 | Tidword() : obj_(0) {}; 24 | 25 | bool operator==(const Tidword &right) const { return obj_ == right.obj_; } 26 | 27 | bool operator!=(const Tidword &right) const { return !operator==(right); } 28 | 29 | bool operator<(const Tidword &right) const { return this->obj_ < right.obj_; } 30 | }; 31 | 32 | class Tuple { 33 | public: 34 | alignas(CACHE_LINE_SIZE) Tidword tidword_; 35 | 36 | char val_[VAL_SIZE]; 37 | }; 38 | -------------------------------------------------------------------------------- /silo/include/util.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern void chkArg(); 4 | 5 | extern bool chkEpochLoaded(); 6 | 7 | extern void displayDB(); 8 | 9 | extern void displayParameter(); 10 | 11 | extern void genLogFile(std::string &logpath, const int thid); 12 | 13 | extern void leaderWork(uint64_t &epoch_timer_start, uint64_t &epoch_timer_stop); 14 | 15 | extern void makeDB(); 16 | 17 | extern void partTableInit([[maybe_unused]] size_t thid, uint64_t start, 18 | uint64_t end); 19 | 20 | extern void ShowOptParameters(); 21 | -------------------------------------------------------------------------------- /silo/replayTest.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "include/common.hh" 5 | #include "include/log.hh" 6 | #include "include/tuple.hh" 7 | 8 | #include "../include/debug.hh" 9 | #include "../include/fileio.hh" 10 | 11 | using std::cout; 12 | using std::endl; 13 | 14 | extern void genLogFile(std::string &logpath, const int thid); 15 | 16 | int main() { 17 | std::string logpath; 18 | genLogFileName(logpath, 1); 19 | File loadfile(logpath, O_RDONLY, 0644); 20 | 21 | LogHeader loadhd; 22 | LogRecord logrec; 23 | 24 | loadfile.read((void *) &loadhd, sizeof(LogHeader)); 25 | cout << "chkSum_ : " << loadhd.chkSum_ << endl; 26 | cout << "logRecNum_ : " << loadhd.logRecNum_ << endl; 27 | 28 | int chkSum_ = 0; 29 | for (unsigned int i = 0; i < loadhd.logRecNum_; ++i) { 30 | loadfile.read((void *) &logrec, sizeof(LogRecord)); 31 | chkSum_ += logrec.computeChkSum(); 32 | cout << "tid : " << logrec.tid_ << endl; 33 | cout << "key : " << logrec.key_ << endl; 34 | cout << "val : " << logrec.val_ << endl << endl; 35 | } 36 | 37 | cout << "computed chkSum_ : " << chkSum_ << endl; 38 | cout << "before chkSum_ + after chkSum_ = " << loadhd.chkSum_ + chkSum_ 39 | << endl; 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /silo/result.cc: -------------------------------------------------------------------------------- 1 | #include "include/result.hh" 2 | #include "include/common.hh" 3 | 4 | #include "../include/cache_line_size.hh" 5 | #include "../include/result.hh" 6 | 7 | using namespace std; 8 | 9 | alignas(CACHE_LINE_SIZE) std::vector SiloResult; 10 | 11 | void initResult() { SiloResult.resize(FLAGS_thread_num); } 12 | -------------------------------------------------------------------------------- /silo/script/ycsbA-xrs-cache.sh: -------------------------------------------------------------------------------- 1 | #ycsbA-xrs-cache.sh(silo) 2 | maxope=10 3 | thread=24 4 | rratio=50 5 | skew=0 6 | ycsb=ON 7 | cpu_mhz=2400 8 | epochtime=40 9 | extime=3 10 | epoch=5 11 | 12 | result=result_silo_ycsbA_tuple100-10m_cachemiss.dat 13 | rm $result 14 | echo "#tuple num, cache-misses, min, max" >> $result 15 | echo "#./silo.exe tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $epochtime $extime" >> $result 16 | 17 | for ((tuple=100; tuple<=10000000; tuple*=10)) 18 | do 19 | sum=0 20 | echo "./silo.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $epochtime $extime" 21 | echo "$tuple $epoch" 22 | 23 | max=0 24 | min=0 25 | for ((i = 1; i <= epoch; ++i)) 26 | do 27 | perf stat -e cache-misses,cache-references -o silo-cache-ana.txt ./silo.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $epochtime $extime 28 | tmp=`grep cache-misses ./silo-cache-ana.txt | awk '{print $4}'` 29 | sum=`echo "$sum + $tmp" | bc -l` 30 | echo "sum: $sum, tmp: $tmp" 31 | 32 | if test $i -eq 1 ; then 33 | max=$tmp 34 | min=$tmp 35 | fi 36 | 37 | flag=`echo "$tmp > $max" | bc -l` 38 | if test $flag -eq 1 ; then 39 | max=$tmp 40 | fi 41 | flag=`echo "$tmp < $min" | bc -l` 42 | if test $flag -eq 1 ; then 43 | min=$tmp 44 | fi 45 | done 46 | avg=`echo "$sum / $epoch" | bc -l` 47 | echo "sum: $sum, epoch: $epoch" 48 | echo "avg $avg" 49 | echo "max: $max" 50 | echo "min: $min" 51 | echo "$tuple $avg $min $max" >> $result 52 | done 53 | 54 | -------------------------------------------------------------------------------- /ss2pl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(ccbench_ss2pl 4 | VERSION 0.0.1 5 | DESCRIPTION "ss2pl of ccbench" 6 | LANGUAGES CXX) 7 | 8 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../cmake") 9 | 10 | option(ENABLE_SANITIZER "enable sanitizer on debug build" ON) 11 | option(ENABLE_UB_SANITIZER "enable undefined behavior sanitizer on debug build" OFF) 12 | option(ENABLE_COVERAGE "enable coverage on debug build" OFF) 13 | 14 | find_package(Doxygen) 15 | find_package(Threads REQUIRED) 16 | find_package(gflags REQUIRED) 17 | find_package(glog REQUIRED) 18 | find_package(Boost 19 | COMPONENTS filesystem) 20 | 21 | include(GNUInstallDirs) 22 | include(CMakePackageConfigHelpers) 23 | include(CompileOptions) 24 | 25 | enable_testing() 26 | add_subdirectory(test) 27 | 28 | file(GLOB SS2PL_SOURCES 29 | "../common/result.cc" 30 | "../common/util.cc" 31 | "ss2pl.cc" 32 | "result.cc" 33 | "transaction.cc" 34 | "util.cc" 35 | ) 36 | 37 | add_executable(ss2pl.exe ${SS2PL_SOURCES}) 38 | 39 | target_link_libraries(ss2pl.exe 40 | Boost::filesystem 41 | gflags::gflags 42 | ${PROJECT_SOURCE_DIR}/../third_party/mimalloc/out/release/libmimalloc.a 43 | ${PROJECT_SOURCE_DIR}/../third_party/masstree/libkohler_masstree_json.a 44 | Threads::Threads 45 | ) 46 | 47 | if (DEFINED ADD_ANALYSIS) 48 | add_definitions(-DADD_ANALYSIS=${ADD_ANALYSIS}) 49 | else () 50 | add_definitions(-DADD_ANALYSIS=0) 51 | endif () 52 | 53 | if (DEFINED BACK_OFF) 54 | add_definitions(-DBACK_OFF=${BACK_OFF}) 55 | else () 56 | add_definitions(-DBACK_OFF=0) 57 | endif () 58 | 59 | add_definitions(-DDLR1) 60 | 61 | if (DEFINED KEY_SIZE) 62 | add_definitions(-DKEY_SIZE=${KEY_SIZE}) 63 | else () 64 | add_definitions(-DKEY_SIZE=8) 65 | endif () 66 | 67 | if (DEFINED KEY_SORT) 68 | add_definitions(-DKEY_SORT=${KEY_SORT}) 69 | else () 70 | add_definitions(-DKEY_SORT=0) 71 | endif () 72 | 73 | if (DEFINED MASSTREE_USE) 74 | add_definitions(-DMASSTREE_USE=${MASSTREE_USE}) 75 | else () 76 | add_definitions(-DMASSTREE_USE=1) 77 | endif () 78 | 79 | if (DEFINED VAL_SIZE) 80 | add_definitions(-DVAL_SIZE=${VAL_SIZE}) 81 | else () 82 | add_definitions(-DVAL_SIZE=4) 83 | endif () 84 | -------------------------------------------------------------------------------- /ss2pl/README.md: -------------------------------------------------------------------------------- 1 | # 2PL 2 | 3 | ## How to use 4 | - Build masstree 5 | ``` 6 | $ cd ../ 7 | $ ./bootstrap.sh 8 | ``` 9 | This makes ../third_party/masstree/libkohler_masstree_json.a used by building ss2pl. 10 | - Build mimalloc 11 | ``` 12 | $ cd ../ 13 | $ ./bootstrap_mimalloc.sh 14 | ``` 15 | This makes ../third_party/mimalloc/out/release/libmimalloc.a used by building ss2pl. 16 | - Build 17 | ``` 18 | $ mkdir build 19 | $ cd build 20 | $ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release .. 21 | $ ninja 22 | ``` 23 | - Confirm usage 24 | ``` 25 | $ ./ss2pl.exe -help 26 | ``` 27 | - Execution example 28 | ``` 29 | $ numactl --interleave=all ./ss2pl.exe -clocks_per_us=2100 -extime=3 -max_ope=10 -rmw=0 -rratio=100 -thread_num=224 -tuple_num=1000000 -ycsb=1 -zipf_skew=0 30 | ``` 31 | 32 | ## How to customize options in CMakeLists.txt 33 | - `ADD_ANALYSIS` : If this is 1, it is deeper analysis than setting 0.
34 | default : `0` 35 | - `BACK_OFF` : If this is 1, it use Cicada's backoff.
36 | default : `0` 37 | - `KEY_SORT` : If this is 1, its transaction accesses records in ascending key order.
38 | default : `0` 39 | - `MASSTREE_USE` : If this is 1, it use masstree as data structure. If not, it use simple array αs data structure. 40 | default : `1` 41 | - `VAL_SIZE` : Value of key-value size. In other words, payload size.
42 | default : `4` 43 | - `DLR0` : Dead lock resolution is timeout. 44 | - `DLR1` : Dead lock resolution is no-wait. 45 | 46 | ## Optimizations 47 | - Backoff. 48 | - Timeout of dead lock resolution. 49 | - No-wait of dead lock resolution. 50 | 51 | ## Implementation 52 | - Lock : reader/writer lock 53 | -------------------------------------------------------------------------------- /ss2pl/include/common.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/cache_line_size.hh" 6 | #include "../../include/int64byte.hh" 7 | #include "../../include/masstree_wrapper.hh" 8 | #include "tuple.hh" 9 | 10 | #include "gflags/gflags.h" 11 | #include "glog/logging.h" 12 | 13 | #ifdef GLOBAL_VALUE_DEFINE 14 | #define GLOBAL 15 | 16 | #if MASSTREE_USE 17 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 18 | #endif 19 | 20 | #else 21 | #define GLOBAL extern 22 | 23 | #if MASSTREE_USE 24 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 25 | #endif 26 | 27 | #endif 28 | 29 | #ifdef GLOBAL_VALUE_DEFINE 30 | DEFINE_uint64(clocks_per_us, 2100, 31 | "CPU_MHz. Use this info for measuring time."); 32 | DEFINE_uint64(extime, 3, "Execution time[sec]."); 33 | DEFINE_uint64(max_ope, 10, 34 | "Total number of operations per single transaction."); 35 | DEFINE_bool(rmw, false, 36 | "True means read modify write, false means blind write."); 37 | DEFINE_uint64(rratio, 50, "read ratio of single transaction."); 38 | DEFINE_uint64(thread_num, 10, "Total number of worker threads."); 39 | DEFINE_uint64(tuple_num, 1000000, "Total number of records."); 40 | DEFINE_bool(ycsb, true, 41 | "True uses zipf_skew, false uses faster random generator."); 42 | DEFINE_double(zipf_skew, 0, "zipf skew. 0 ~ 0.999..."); 43 | #else 44 | DECLARE_uint64(clocks_per_us); 45 | DECLARE_uint64(extime); 46 | DECLARE_uint64(max_ope); 47 | DECLARE_bool(rmw); 48 | DECLARE_uint64(rratio); 49 | DECLARE_uint64(thread_num); 50 | DECLARE_uint64(tuple_num); 51 | DECLARE_bool(ycsb); 52 | DECLARE_double(zipf_skew); 53 | #endif 54 | 55 | alignas(CACHE_LINE_SIZE) GLOBAL Tuple *Table; 56 | -------------------------------------------------------------------------------- /ss2pl/include/result.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/result.hh" 6 | 7 | extern std::vector SS2PLResult; 8 | 9 | extern void initResult(); 10 | -------------------------------------------------------------------------------- /ss2pl/include/ss2pl_op_element.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../include/op_element.hh" 4 | 5 | template 6 | class SetElement : public OpElement { 7 | public: 8 | using OpElement::OpElement; 9 | 10 | char val_[VAL_SIZE]; 11 | 12 | SetElement(uint64_t key, T *rcdptr) : OpElement::OpElement(key, rcdptr) {} 13 | 14 | SetElement(uint64_t key, T *rcdptr, char *val) 15 | : OpElement::OpElement(key, rcdptr) { 16 | memcpy(this->val_, val, VAL_SIZE); 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /ss2pl/include/transaction.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/procedure.hh" 6 | #include "../../include/result.hh" 7 | #include "../../include/rwlock.hh" 8 | #include "../../include/string.hh" 9 | #include "../../include/util.hh" 10 | #include "ss2pl_op_element.hh" 11 | #include "tuple.hh" 12 | 13 | enum class TransactionStatus : uint8_t { 14 | inFlight, 15 | committed, 16 | aborted, 17 | }; 18 | 19 | extern void writeValGenerator(char *writeVal, size_t val_size, size_t thid); 20 | 21 | class TxExecutor { 22 | public: 23 | alignas(CACHE_LINE_SIZE) int thid_; 24 | std::vector r_lock_list_; 25 | std::vector w_lock_list_; 26 | TransactionStatus status_ = TransactionStatus::inFlight; 27 | Result *sres_; 28 | vector > read_set_; 29 | vector > write_set_; 30 | vector pro_set_; 31 | 32 | char write_val_[VAL_SIZE]; 33 | char return_val_[VAL_SIZE]; 34 | 35 | TxExecutor(int thid, Result *sres) : thid_(thid), sres_(sres) { 36 | read_set_.reserve(FLAGS_max_ope); 37 | write_set_.reserve(FLAGS_max_ope); 38 | pro_set_.reserve(FLAGS_max_ope); 39 | r_lock_list_.reserve(FLAGS_max_ope); 40 | w_lock_list_.reserve(FLAGS_max_ope); 41 | 42 | genStringRepeatedNumber(write_val_, VAL_SIZE, thid); 43 | } 44 | 45 | SetElement *searchReadSet(uint64_t key); 46 | 47 | SetElement *searchWriteSet(uint64_t key); 48 | 49 | void begin(); 50 | 51 | void read(uint64_t key); 52 | 53 | void write(uint64_t key); 54 | 55 | void readWrite(uint64_t key); 56 | 57 | void commit(); 58 | 59 | void abort(); 60 | 61 | void unlockList(); 62 | 63 | // inline 64 | Tuple *get_tuple(Tuple *table, uint64_t key) { return &table[key]; } 65 | }; 66 | -------------------------------------------------------------------------------- /ss2pl/include/tuple.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "../../include/cache_line_size.hh" 7 | #include "../../include/inline.hh" 8 | #include "../../include/rwlock.hh" 9 | 10 | using namespace std; 11 | 12 | class Tuple { 13 | public: 14 | alignas(CACHE_LINE_SIZE) RWLock lock_; 15 | char val_[VAL_SIZE]; 16 | }; 17 | -------------------------------------------------------------------------------- /ss2pl/include/util.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern void chkArg(); 4 | 5 | extern void displayDB(); 6 | 7 | extern void displayParameter(); 8 | 9 | extern void makeDB(); 10 | 11 | extern void partTableInit([[maybe_unused]] size_t thid, uint64_t start, uint64_t end); 12 | 13 | extern void ShowOptParameters(); 14 | -------------------------------------------------------------------------------- /ss2pl/result.cc: -------------------------------------------------------------------------------- 1 | #include "include/result.hh" 2 | #include "include/common.hh" 3 | 4 | #include "../include/cache_line_size.hh" 5 | #include "../include/result.hh" 6 | 7 | using namespace std; 8 | 9 | alignas(CACHE_LINE_SIZE) std::vector SS2PLResult; 10 | 11 | void initResult() { SS2PLResult.resize(FLAGS_thread_num); } 12 | -------------------------------------------------------------------------------- /ss2pl/script/ycsbA-xrs-cache.sh: -------------------------------------------------------------------------------- 1 | #ycsbA-xrs-cache.sh(ss2pl) 2 | maxope=10 3 | thread=24 4 | rratio=50 5 | skew=0 6 | ycsb=ON 7 | cpu_mhz=2400 8 | extime=3 9 | epoch=5 10 | 11 | result=result_ss2pl_ycsbA_tuple100-10m_cachemiss.dat 12 | rm $result 13 | echo "#tuple num, cache-misses, min, max" >> $result 14 | echo "#./ss2pl.exe tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $extime" >> $result 15 | 16 | for ((tuple=100; tuple<=10000000; tuple*=10)) 17 | do 18 | sum=0 19 | echo "./ss2pl.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $extime" 20 | echo "$tuple $epoch" 21 | 22 | max=0 23 | min=0 24 | for ((i = 1; i <= epoch; ++i)) 25 | do 26 | perf stat -e cache-misses,cache-references -o ss2pl-cache-ana.txt ./ss2pl.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $extime 27 | tmp=`grep cache-misses ./ss2pl-cache-ana.txt | awk '{print $4}'` 28 | sum=`echo "$sum + $tmp" | bc -l` 29 | echo "sum: $sum, tmp: $tmp" 30 | 31 | if test $i -eq 1 ; then 32 | max=$tmp 33 | min=$tmp 34 | fi 35 | 36 | flag=`echo "$tmp > $max" | bc -l` 37 | if test $flag -eq 1 ; then 38 | max=$tmp 39 | fi 40 | flag=`echo "$tmp < $min" | bc -l` 41 | if test $flag -eq 1 ; then 42 | min=$tmp 43 | fi 44 | done 45 | avg=`echo "$sum / $epoch" | bc -l` 46 | echo "sum: $sum, epoch: $epoch" 47 | echo "avg $avg" 48 | echo "max: $max" 49 | echo "min: $min" 50 | echo "$tuple $avg $min $max" >> $result 51 | done 52 | 53 | -------------------------------------------------------------------------------- /ss2pl/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB SS2PL_SOURCES 2 | "${PROJECT_SOURCE_DIR}/../common/result.cc" 3 | "${PROJECT_SOURCE_DIR}/../common/util.cc" 4 | "${PROJECT_SOURCE_DIR}/result.cc" 5 | "${PROJECT_SOURCE_DIR}/transaction.cc" 6 | "${PROJECT_SOURCE_DIR}/util.cc" 7 | ) 8 | 9 | file (GLOB TEST_SOURCES 10 | "make_db_test.cpp" 11 | ) 12 | 13 | if (DEFINED ADD_ANALYSIS) 14 | add_definitions(-DADD_ANALYSIS=${ADD_ANALYSIS}) 15 | else () 16 | add_definitions(-DADD_ANALYSIS=0) 17 | endif () 18 | 19 | if (DEFINED BACK_OFF) 20 | add_definitions(-DBACK_OFF=${BACK_OFF}) 21 | else () 22 | add_definitions(-DBACK_OFF=0) 23 | endif () 24 | 25 | add_definitions(-DDLR1) 26 | 27 | if (DEFINED KEY_SIZE) 28 | add_definitions(-DKEY_SIZE=${KEY_SIZE}) 29 | else () 30 | add_definitions(-DKEY_SIZE=8) 31 | endif () 32 | 33 | if (DEFINED KEY_SORT) 34 | add_definitions(-DKEY_SORT=${KEY_SORT}) 35 | else () 36 | add_definitions(-DKEY_SORT=0) 37 | endif () 38 | 39 | if (DEFINED MASSTREE_USE) 40 | add_definitions(-DMASSTREE_USE=${MASSTREE_USE}) 41 | else () 42 | add_definitions(-DMASSTREE_USE=1) 43 | endif () 44 | 45 | if (DEFINED VAL_SIZE) 46 | add_definitions(-DVAL_SIZE=${VAL_SIZE}) 47 | else () 48 | add_definitions(-DVAL_SIZE=4) 49 | endif () 50 | 51 | foreach(src IN LISTS TEST_SOURCES) 52 | get_filename_component(fname "${src}" NAME_WE) 53 | set(test_name "${fname}") 54 | 55 | add_executable(${test_name} ${src} ${SS2PL_SOURCES}) 56 | 57 | target_include_directories(${test_name} 58 | PRIVATE ${PROJECT_SOURCE_DIR}/../third_party/googletest/googletest/include 59 | ) 60 | 61 | target_link_libraries(${test_name} 62 | Boost::filesystem 63 | gflags::gflags 64 | glog::glog 65 | ${PROJECT_SOURCE_DIR}/../third_party/mimalloc/out/release/libmimalloc.a 66 | ${PROJECT_SOURCE_DIR}/../third_party/masstree/libkohler_masstree_json.a 67 | Threads::Threads 68 | ${PROJECT_SOURCE_DIR}/../third_party/googletest/build/lib/libgtest.a 69 | ${PROJECT_SOURCE_DIR}/../third_party/googletest/build/lib/libgtest_main.a 70 | ) 71 | set_compile_options(${test_name}) 72 | add_test( 73 | NAME ${test_name} 74 | COMMAND ${test_name} --gtest_output=xml:${test_name}_gtest_result.xml 75 | ) 76 | endforeach() -------------------------------------------------------------------------------- /ss2pl/test/make_db_test.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #define GLOBAL_VALUE_DEFINE 5 | 6 | #include "../../include/backoff.hh" 7 | #include "../include/common.hh" 8 | #include "../include/util.hh" 9 | 10 | #include "glog/logging.h" 11 | #include "gtest/gtest.h" 12 | 13 | namespace ccbench::testing { 14 | 15 | class make_db_test : public ::testing::Test { 16 | public: 17 | static void call_once_f() { 18 | google::InitGoogleLogging("make_db_test_log"); 19 | FLAGS_stderrthreshold = 0; 20 | } 21 | 22 | void SetUp() override { std::call_once(init_, call_once_f); } 23 | 24 | void TearDown() override {} 25 | 26 | private: 27 | static inline std::once_flag init_; // NOLINT 28 | }; 29 | 30 | TEST_F(make_db_test, simple) { // NOLINT 31 | makeDB(); 32 | // verify effect makeDb 33 | for (std::uint64_t i = 0; i < FLAGS_tuple_num; ++i) { 34 | ASSERT_EQ(Table[i].val_[0], 'a'); 35 | ASSERT_EQ(Table[i].val_[1], '\0'); 36 | ASSERT_EQ(Table[i].lock_.counter.load(std::memory_order_acquire), 0); 37 | } 38 | } 39 | 40 | } // namespace ccbench::testing -------------------------------------------------------------------------------- /tictoc/include/common.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "../../include/cache_line_size.hh" 10 | #include "../../include/int64byte.hh" 11 | #include "../../include/masstree_wrapper.hh" 12 | #include "tuple.hh" 13 | 14 | #include "gflags/gflags.h" 15 | #include "glog/logging.h" 16 | 17 | #ifdef GLOBAL_VALUE_DEFINE 18 | #define GLOBAL 19 | 20 | #if MASSTREE_USE 21 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 22 | #endif 23 | 24 | #else 25 | #define GLOBAL extern 26 | 27 | #if MASSTREE_USE 28 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 29 | #endif 30 | 31 | #endif 32 | 33 | #ifdef GLOBAL_VALUE_DEFINE 34 | DEFINE_uint64(clocks_per_us, 2100, 35 | "CPU_MHz. Use this info for measuring time."); 36 | DEFINE_uint64(extime, 3, "Execution time[sec]."); 37 | DEFINE_uint64(max_ope, 10, 38 | "Total number of operations per single transaction."); 39 | DEFINE_bool(rmw, false, 40 | "True means read modify write, false means blind write."); 41 | DEFINE_uint64(rratio, 50, "read ratio of single transaction."); 42 | DEFINE_uint64(thread_num, 10, "Total number of worker threads."); 43 | DEFINE_uint64(tuple_num, 1000000, "Total number of records."); 44 | DEFINE_bool(ycsb, true, 45 | "True uses zipf_skew, false uses faster random generator."); 46 | DEFINE_double(zipf_skew, 0, "zipf skew. 0 ~ 0.999..."); 47 | #else 48 | DECLARE_uint64(clocks_per_us); 49 | DECLARE_uint64(extime); 50 | DECLARE_uint64(max_ope); 51 | DECLARE_bool(rmw); 52 | DECLARE_uint64(rratio); 53 | DECLARE_uint64(thread_num); 54 | DECLARE_uint64(tuple_num); 55 | DECLARE_bool(ycsb); 56 | DECLARE_double(zipf_skew); 57 | #endif 58 | 59 | alignas(CACHE_LINE_SIZE) GLOBAL Tuple *Table; 60 | -------------------------------------------------------------------------------- /tictoc/include/result.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/result.hh" 6 | 7 | extern std::vector TicTocResult; 8 | 9 | extern void initResult(); 10 | -------------------------------------------------------------------------------- /tictoc/include/tictoc_op_element.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../include/op_element.hh" 4 | 5 | template 6 | class SetElement : public OpElement { 7 | public: 8 | using OpElement::OpElement; 9 | 10 | char val_[VAL_SIZE]; 11 | TsWord tsw_; 12 | 13 | SetElement(uint64_t key, T *rcdptr, char *val, TsWord tsw) 14 | : OpElement::OpElement(key, rcdptr) { 15 | memcpy(this->val_, val, VAL_SIZE); 16 | this->tsw_.obj_ = tsw.obj_; 17 | } 18 | 19 | SetElement(uint64_t key, T *rcdptr, TsWord tsw) 20 | : OpElement::OpElement(key, rcdptr) { 21 | this->tsw_.obj_ = tsw.obj_; 22 | } 23 | 24 | bool operator<(const SetElement &right) const { 25 | return this->key_ < right.key_; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /tictoc/include/tuple.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "../../include/cache_line_size.hh" 10 | 11 | struct TsWord { 12 | union { 13 | uint64_t obj_; 14 | struct { 15 | bool lock: 1; 16 | uint16_t delta: 15; 17 | uint64_t wts: 48; 18 | }; 19 | }; 20 | 21 | TsWord() { obj_ = 0; } 22 | 23 | bool operator==(const TsWord &right) const { return obj_ == right.obj_; } 24 | 25 | bool operator!=(const TsWord &right) const { return !operator==(right); } 26 | 27 | bool isLocked() { 28 | if (lock) 29 | return true; 30 | else 31 | return false; 32 | } 33 | 34 | uint64_t rts() const { return wts + delta; } 35 | }; 36 | 37 | class Tuple { 38 | public: 39 | alignas(CACHE_LINE_SIZE) TsWord tsw_; 40 | TsWord pre_tsw_; 41 | char val_[VAL_SIZE]; 42 | }; 43 | -------------------------------------------------------------------------------- /tictoc/include/util.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | extern void chkArg(); 6 | 7 | extern void displayDB(); 8 | 9 | extern void displayParameter(); 10 | 11 | extern void makeDB(); 12 | 13 | extern void partTableInit([[maybe_unused]] std::size_t thid, uint64_t start, 14 | uint64_t end); 15 | 16 | extern void ShowOptParameters(); 17 | -------------------------------------------------------------------------------- /tictoc/result.cc: -------------------------------------------------------------------------------- 1 | #include "include/result.hh" 2 | #include "include/common.hh" 3 | 4 | #include "../include/cache_line_size.hh" 5 | #include "../include/result.hh" 6 | 7 | using namespace std; 8 | 9 | alignas(CACHE_LINE_SIZE) std::vector TicTocResult; 10 | 11 | void initResult() { TicTocResult.resize(FLAGS_thread_num); } 12 | -------------------------------------------------------------------------------- /tictoc/script/ycsbA-xrs-cache.sh: -------------------------------------------------------------------------------- 1 | #ycsbA-xrs-cache.sh(tictoc) 2 | maxope=10 3 | thread=24 4 | rratio=50 5 | skew=0 6 | ycsb=ON 7 | cpu_mhz=2400 8 | extime=3 9 | epoch=5 10 | 11 | result=result_tictoc_ycsbA_tuple100-10m_cachemiss.dat 12 | rm $result 13 | echo "#tuple num, cache-misses, min, max" >> $result 14 | echo "#./tictoc.exe tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $extime" >> $result 15 | 16 | for ((tuple=100; tuple<=10000000; tuple*=10)) 17 | do 18 | sum=0 19 | echo "./tictoc.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $extime" 20 | echo "$tuple $epoch" 21 | 22 | max=0 23 | min=0 24 | for ((i = 1; i <= epoch; ++i)) 25 | do 26 | perf stat -e cache-misses,cache-references -o tictoc-cache-ana.txt ./tictoc.exe $tuple $maxope $thread $rratio $skew $ycsb $cpu_mhz $extime 27 | tmp=`grep cache-misses ./tictoc-cache-ana.txt | awk '{print $4}'` 28 | sum=`echo "$sum + $tmp" | bc -l` 29 | echo "sum: $sum, tmp: $tmp" 30 | 31 | if test $i -eq 1 ; then 32 | max=$tmp 33 | min=$tmp 34 | fi 35 | 36 | flag=`echo "$tmp > $max" | bc -l` 37 | if test $flag -eq 1 ; then 38 | max=$tmp 39 | fi 40 | flag=`echo "$tmp < $min" | bc -l` 41 | if test $flag -eq 1 ; then 42 | min=$tmp 43 | fi 44 | done 45 | avg=`echo "$sum / $epoch" | bc -l` 46 | echo "sum: $sum, epoch: $epoch" 47 | echo "avg $avg" 48 | echo "max: $max" 49 | echo "min: $min" 50 | echo "$tuple $avg $min $max" >> $result 51 | done 52 | 53 | -------------------------------------------------------------------------------- /tpcc_silo/build_script.sh: -------------------------------------------------------------------------------- 1 | #apt update -y && apt install -y libgflags-dev libgoogle-glog-dev libboost-filesystem-dev 2 | 3 | pushd ../ 4 | ./bootstrap.sh 5 | ./bootstrap_apt.sh 6 | ./bootstrap_mimalloc.sh 7 | ./bootstrap_googletest.sh 8 | 9 | popd 10 | mkdir -p build 11 | cd build 12 | cmake .. 13 | make -j`grep '^processor' /proc/cpuinfo | wc -l` 14 | -------------------------------------------------------------------------------- /tpcc_silo/epoch.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file epoch.cpp 3 | * @brief implement about epoch 4 | */ 5 | 6 | #include "epoch.h" 7 | 8 | #include // NOLINT 9 | 10 | #include "session_info_table.h" 11 | #include "clock.h" 12 | #include "../include/util.hh" 13 | #include 14 | 15 | 16 | namespace ccbench::epoch { 17 | 18 | uint32_t atomic_add_global_epoch() { 19 | std::uint32_t expected = load_acquire_global_epoch(); 20 | for (;;) { 21 | std::uint32_t desired = expected + 1; 22 | if (__atomic_compare_exchange_n(&(kGlobalEpoch), &(expected), desired, 23 | false, __ATOMIC_ACQ_REL, 24 | __ATOMIC_ACQUIRE)) { 25 | return desired; 26 | } 27 | } 28 | } 29 | 30 | bool check_epoch_loaded() { // NOLINT 31 | std::uint64_t curEpoch = load_acquire_global_epoch(); 32 | 33 | for (auto &&itr : session_info_table::get_thread_info_table()) { // NOLINT 34 | if (itr.get_visible() && itr.get_epoch() != curEpoch) { 35 | return false; 36 | } 37 | } 38 | 39 | return true; 40 | } 41 | 42 | void epocher() { 43 | /** 44 | * Increment global epoch in each 40ms. 45 | * To increment it, 46 | * all the worker-threads need to read the latest one. 47 | */ 48 | while (likely(!kEpochThreadEnd.load(std::memory_order_acquire))) { 49 | sleepMs(KVS_EPOCH_TIME); 50 | 51 | { 52 | // reset timestamp. 53 | struct timespec ts; 54 | [[maybe_unused]] int ret = ::clock_gettime(CLOCK_MONOTONIC, &ts); 55 | assert(ret == 0); 56 | if (get_lightweight_timestamp() != ts.tv_sec) { 57 | storeRelease(timestamp_, ts.tv_sec); 58 | } 59 | } 60 | 61 | /** 62 | * check_epoch_loaded() checks whether the 63 | * latest global epoch is read by all the threads 64 | */ 65 | std::size_t exp_ctr{1}; 66 | while (!check_epoch_loaded()) { 67 | if (kEpochThreadEnd.load(std::memory_order_acquire)) return; 68 | usleep(exp_ctr); 69 | exp_ctr = std::min(exp_ctr * 2, 1000); 70 | } 71 | 72 | uint32_t curEpoch = atomic_add_global_epoch(); 73 | storeRelease(kReclamationEpoch, curEpoch - 2); 74 | } 75 | } 76 | 77 | } // namespace ccbench::epoch 78 | -------------------------------------------------------------------------------- /tpcc_silo/garbage_collection.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file garbage_collection.cpp 3 | * @brief about garbage collection. 4 | */ 5 | 6 | #include "garbage_collection.h" 7 | 8 | #include "index/masstree_beta/include/masstree_beta_wrapper.h" 9 | #include "session_info.h" 10 | 11 | namespace ccbench::garbage_collection { 12 | 13 | [[maybe_unused]] void release_all_heap_objects() { 14 | remove_all_leaf_from_mt_db_and_release(); 15 | delete_all_garbage_records(); 16 | delete_all_garbage_values(); 17 | } 18 | 19 | void remove_all_leaf_from_mt_db_and_release() { 20 | std::vector scan_res; 21 | for (std::size_t i = 0; i < kohler_masstree::db_length; ++i) { 22 | kohler_masstree::get_mtdb(static_cast(i)).scan(nullptr, 0, false, nullptr, 0, false, 23 | &scan_res, false); // NOLINT 24 | for (auto &&itr : scan_res) { 25 | std::string_view key_view = itr->get_tuple().get_key(); 26 | kohler_masstree::get_mtdb(static_cast(i)).remove_value(key_view.data(), key_view.size()); 27 | if (i == static_cast(Storage::SECONDARY)) { 28 | std::vector *ctn_ptr; 29 | memcpy(&ctn_ptr, 30 | reinterpret_cast(const_cast(itr->get_tuple().get_val().data())), 8); 31 | delete ctn_ptr; 32 | } 33 | delete itr; // NOLINT 34 | } 35 | 36 | /** 37 | * check whether index_kohler_masstree::get_mtdb() is empty. 38 | */ 39 | scan_res.clear(); 40 | kohler_masstree::get_mtdb(static_cast(i)).scan(nullptr, 0, false, nullptr, 0, false, 41 | &scan_res, false); // NOLINT 42 | if (!scan_res.empty()) std::abort(); 43 | } 44 | } 45 | 46 | void delete_all_garbage_records() { 47 | for (auto i = 0; i < KVS_NUMBER_OF_LOGICAL_CORES; ++i) { 48 | RecPtrContainer& q = get_garbage_records_at(i); 49 | while (!q.empty()) { 50 | Record* rec = q.front(); 51 | delete rec; // NOLINT 52 | q.pop_front(); 53 | } 54 | } 55 | } 56 | 57 | void delete_all_garbage_values() { 58 | for (auto i = 0; i < KVS_NUMBER_OF_LOGICAL_CORES; ++i) { 59 | ObjEpochContainer& q = get_garbage_values_at(i); 60 | q.clear(); // HeapObject instances are automatically deallocated. 61 | } 62 | } 63 | 64 | } // namespace ccbench::garbage_collection 65 | -------------------------------------------------------------------------------- /tpcc_silo/include/aligned_allocator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file aligned_allocator.h 3 | * @brief atomic wrapper of builtin function. 4 | */ 5 | 6 | #pragma once 7 | 8 | namespace ccbench { 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /** 17 | * @return pointer. (success) allocated pointer. (fail) nullptr. 18 | */ 19 | template 20 | static inline T * 21 | aligned_malloc(std::size_t n_bytes, std::size_t alignment = alignof(T)) noexcept { 22 | void *p; 23 | return reinterpret_cast(posix_memalign(&p, alignment, n_bytes) == 0 ? p : nullptr); 24 | } 25 | 26 | template 27 | static inline T * 28 | aligned_alloc_array(std::size_t size, std::size_t alignment = alignof(T)) noexcept { 29 | return aligned_malloc(size * sizeof(T), alignment); 30 | } 31 | 32 | 33 | static inline void 34 | aligned_free(void *ptr) noexcept { 35 | std::free(ptr); 36 | } 37 | 38 | template 39 | class aligned_allocator { 40 | public: 41 | using value_type = T; 42 | using size_type = std::size_t; 43 | using pointer = typename std::add_pointer::type; 44 | using const_pointer = typename std::add_pointer::type; 45 | 46 | template 47 | struct rebind { 48 | using other = aligned_allocator; 49 | }; 50 | 51 | aligned_allocator() noexcept {} 52 | 53 | template 54 | aligned_allocator(const aligned_allocator &) noexcept {} 55 | 56 | pointer allocate(size_type n, const_pointer = nullptr) const { 57 | auto p = aligned_alloc_array(n, k_alignment); 58 | if (p == nullptr) { 59 | throw std::bad_alloc{}; 60 | } 61 | return p; 62 | } 63 | 64 | void deallocate(pointer p, size_type) const noexcept { 65 | aligned_free(p); 66 | } 67 | }; // class aligned_allocator 68 | 69 | 70 | template 71 | static inline bool 72 | operator==(const aligned_allocator &, const aligned_allocator &) noexcept { 73 | return k_alignment1 == k_alignment2; 74 | } 75 | 76 | 77 | template 78 | static inline bool 79 | operator!=(const aligned_allocator &lhs, const aligned_allocator &rhs) noexcept { 80 | return !(lhs == rhs); 81 | } 82 | 83 | } // namespace ccbench 84 | -------------------------------------------------------------------------------- /tpcc_silo/include/atomic_tool.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.hh" 4 | 5 | #include "../../include/inline.hh" 6 | 7 | INLINE uint64_t atomicLoadGE(); 8 | 9 | INLINE void atomicAddGE() { 10 | uint64_t expected, desired; 11 | 12 | expected = atomicLoadGE(); 13 | for (;;) { 14 | desired = expected + 1; 15 | if (__atomic_compare_exchange_n(&(GlobalEpoch.obj_), &expected, desired, 16 | false, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) 17 | break; 18 | } 19 | } 20 | 21 | INLINE uint64_t atomicLoadGE() { 22 | uint64_t_64byte result = 23 | __atomic_load_n(&(GlobalEpoch.obj_), __ATOMIC_ACQUIRE); 24 | return result.obj_; 25 | } 26 | 27 | INLINE void atomicStoreThLocalEpoch(unsigned int thid, uint64_t newval) { 28 | __atomic_store_n(&(ThLocalEpoch[thid].obj_), newval, __ATOMIC_RELEASE); 29 | } 30 | -------------------------------------------------------------------------------- /tpcc_silo/include/atomic_wrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * @file 5 | * @brief atomic wrapper of builtin function. 6 | */ 7 | 8 | namespace ccbench { 9 | 10 | /** 11 | * @brief atomic relaxed load. 12 | */ 13 | template 14 | [[maybe_unused]] static T loadRelaxed(T &ptr) { // NOLINT 15 | return __atomic_load_n(&ptr, __ATOMIC_RELAXED); // NOLINT 16 | } 17 | 18 | template 19 | [[maybe_unused]] static T loadRelaxed(T *ptr) { // NOLINT 20 | return __atomic_load_n(ptr, __ATOMIC_RELAXED); // NOLINT 21 | } 22 | 23 | /** 24 | * @brief atomic acquire load. 25 | */ 26 | template 27 | static T loadAcquire(T &ptr) { // NOLINT 28 | return __atomic_load_n(&ptr, __ATOMIC_ACQUIRE); // NOLINT 29 | } 30 | 31 | template 32 | [[maybe_unused]] static T loadAcquire(T *ptr) { // NOLINT 33 | return __atomic_load_n(ptr, __ATOMIC_ACQUIRE); // NOLINT 34 | } 35 | 36 | /** 37 | * @brief atomic relaxed store. 38 | */ 39 | template 40 | [[maybe_unused]] static void storeRelaxed(T &ptr, T2 val) { 41 | __atomic_store_n(&ptr, (T) val, __ATOMIC_RELAXED); // NOLINT 42 | } 43 | 44 | template 45 | [[maybe_unused]] static void storeRelaxed(T *ptr, T2 val) { 46 | __atomic_store_n(ptr, (T) val, __ATOMIC_RELAXED); // NOLINT 47 | } 48 | 49 | /** 50 | * @brief atomic release store. 51 | */ 52 | template 53 | static void storeRelease(T &ptr, T2 val) { 54 | __atomic_store_n(&ptr, (T) val, __ATOMIC_RELEASE); // NOLINT 55 | } 56 | 57 | template 58 | [[maybe_unused]] static void storeRelease(T *ptr, T2 val) { 59 | __atomic_store_n(ptr, (T) val, __ATOMIC_RELEASE); // NOLINT 60 | } 61 | 62 | /** 63 | * @brief atomic acq-rel cas. 64 | */ 65 | template 66 | static bool compareExchange(T &m, T &before, T2 after) { // NOLINT 67 | return __atomic_compare_exchange_n(&m, &before, (T) after, false, // NOLINT 68 | __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE); 69 | } 70 | 71 | template 72 | static Int1 fetchAdd(Int1 &m, Int2 v, int memorder = __ATOMIC_ACQ_REL) { 73 | return __atomic_fetch_add(&m, v, memorder); 74 | } 75 | 76 | 77 | } // namespace ccbench 78 | -------------------------------------------------------------------------------- /tpcc_silo/include/clock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file clock.h 3 | * @brief functions about clock. 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace ccbench { 13 | 14 | [[maybe_unused]] static bool check_clock_span(uint64_t &start, // NOLINT 15 | uint64_t &stop, 16 | uint64_t threshold) { 17 | uint64_t diff{stop - start}; 18 | return diff > threshold; 19 | } 20 | 21 | #if 0 22 | [[maybe_unused]] static void sleepMs(size_t ms) { 23 | std::this_thread::sleep_for(std::chrono::milliseconds(ms)); 24 | } 25 | #endif 26 | 27 | 28 | template 29 | class StopWatch { 30 | using TimePoint = std::chrono::time_point; 31 | TimePoint tp[2]; 32 | public: 33 | StopWatch() { 34 | tp[0] = Clock::now(); 35 | tp[1] = tp[0]; 36 | } 37 | 38 | void mark() { 39 | TimePoint now = Clock::now(); 40 | tp[0] = tp[1]; 41 | tp[1] = now; 42 | } 43 | 44 | double period() const { 45 | std::chrono::duration ret = tp[1] - tp[0]; 46 | return ret.count(); 47 | } 48 | }; 49 | 50 | 51 | } // namespace ccbench 52 | -------------------------------------------------------------------------------- /tpcc_silo/include/common.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | //#include "tuple.hh" 9 | 10 | #include "../../include/cache_line_size.hh" 11 | #include "../../include/int64byte.hh" 12 | //#include "../../include/masstree_wrapper.hh" 13 | 14 | #include "gflags/gflags.h" 15 | #include "glog/logging.h" 16 | 17 | #ifdef GLOBAL_VALUE_DEFINE 18 | #define GLOBAL 19 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte GlobalEpoch(1); 20 | #if MASSTREE_USE 21 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 22 | #endif 23 | #else 24 | #define GLOBAL extern 25 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte GlobalEpoch; 26 | #if MASSTREE_USE 27 | alignas(CACHE_LINE_SIZE) GLOBAL MasstreeWrapper MT; 28 | #endif 29 | #endif 30 | 31 | #ifdef GLOBAL_VALUE_DEFINE 32 | DEFINE_uint64(thread_num, 1, "Total number of worker threads."); 33 | DEFINE_uint64(clocks_per_us, 2100, 34 | "CPU_MHz. Use this info for measuring time."); 35 | DEFINE_uint64(epoch_time, 40, "Epoch interval[msec]."); 36 | DEFINE_uint64(extime, 1, "Execution time[sec]."); 37 | 38 | DEFINE_uint32(num_wh, 1, "The number of warehouses"); 39 | DEFINE_uint64(perc_payment, 50, "The percentage of Payment transactions"); // 43.1 for full 40 | DEFINE_uint64(perc_order_status, 0, "The percentage of Order-Status transactions"); // 4.1 for full 41 | DEFINE_uint64(perc_delivery, 0, "The percentage of Delivery transactions"); // 4.2 for full 42 | DEFINE_uint64(perc_stock_level, 0, "The percentage of Stock-Level transactions"); // 4.1 for full 43 | DEFINE_bool(insert_exe, true, "Insert records according to the specification"); // TPC-C-NP (our) regulation choice. 44 | 45 | #else 46 | DECLARE_uint64(thread_num); 47 | DECLARE_uint64(clocks_per_us); 48 | DECLARE_uint64(epoch_time); 49 | DECLARE_uint64(extime); 50 | 51 | DECLARE_uint32(num_wh); 52 | DECLARE_uint64(perc_payment); 53 | DECLARE_uint64(perc_order_status); 54 | DECLARE_uint64(perc_delivery); 55 | DECLARE_uint64(perc_stock_level); 56 | DECLARE_bool(insert_exe); 57 | #endif 58 | 59 | constexpr std::size_t DIST_PER_WARE{10}; 60 | constexpr std::size_t MAX_ITEMS{100000}; 61 | constexpr std::size_t CUST_PER_DIST{3000}; 62 | 63 | 64 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte *ThLocalEpoch; 65 | alignas(CACHE_LINE_SIZE) GLOBAL uint64_t_64byte *CTIDW; 66 | 67 | //alignas(CACHE_LINE_SIZE) GLOBAL Tuple *Table; 68 | -------------------------------------------------------------------------------- /tpcc_silo/include/compiler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file compiler.h 3 | */ 4 | 5 | #pragma once 6 | 7 | namespace ccbench { 8 | 9 | #define likely(x) __builtin_expect(!!(x), 1) // NOLINT 10 | #define unlikely(x) __builtin_expect(!!(x), 0) // NOLINT 11 | 12 | #define STRING(macro) #macro // NOLINT 13 | #define MAC2STR(macro) STRING(macro) // NOLINT 14 | 15 | } // namespace ccbench 16 | -------------------------------------------------------------------------------- /tpcc_silo/include/cpu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file cpu.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "../../include/cache_line_size.hh" 18 | 19 | namespace ccbench { 20 | 21 | #ifdef CCBENCH_LINUX 22 | 23 | [[maybe_unused]] static void setThreadAffinity(const int my_id) { 24 | using namespace std; 25 | static std::atomic n_processors(-1); 26 | int local_n_processors = n_processors.load(memory_order_acquire); 27 | for (;;) { 28 | if (local_n_processors != -1) { 29 | break; 30 | } 31 | int desired = sysconf(_SC_NPROCESSORS_CONF); // NOLINT 32 | if (n_processors.compare_exchange_strong(local_n_processors, desired, 33 | memory_order_acq_rel, 34 | memory_order_acquire)) { 35 | break; 36 | } 37 | } 38 | 39 | pid_t pid = syscall(SYS_gettid); // NOLINT 40 | cpu_set_t cpu_set; 41 | 42 | CPU_ZERO(&cpu_set); 43 | CPU_SET(my_id % local_n_processors, &cpu_set); // NOLINT 44 | 45 | if (sched_setaffinity(pid, sizeof(cpu_set_t), &cpu_set) != 0) { 46 | std::cout << __FILE__ << " : " << __LINE__ << " : fatal error." 47 | << std::endl; 48 | std::abort(); 49 | } 50 | } 51 | 52 | [[maybe_unused]] static void setThreadAffinity(const cpu_set_t id) { 53 | pid_t pid = syscall(SYS_gettid); // NOLINT 54 | 55 | if (sched_setaffinity(pid, sizeof(cpu_set_t), &id) != 0) { 56 | std::cout << __FILE__ << " : " << __LINE__ << " : fatal error." 57 | << std::endl; 58 | std::abort(); 59 | } 60 | } 61 | 62 | [[maybe_unused]] static cpu_set_t getThreadAffinity() { // NOLINT 63 | pid_t pid = syscall(SYS_gettid); // NOLINT 64 | cpu_set_t result; 65 | 66 | if (sched_getaffinity(pid, sizeof(cpu_set_t), &result) != 0) { 67 | std::cout << __FILE__ << " : " << __LINE__ << " : fatal error." 68 | << std::endl; 69 | std::abort(); 70 | } 71 | 72 | return result; 73 | } 74 | 75 | 76 | inline int cached_sched_getcpu() 77 | { 78 | thread_local int value = ::sched_getcpu(); 79 | return value; 80 | } 81 | 82 | 83 | #endif // CCBENCH_LINUX 84 | 85 | } // namespace ccbench 86 | -------------------------------------------------------------------------------- /tpcc_silo/include/epoch.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file epoch.h 3 | * @brief header about epoch 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | #include "atomic_wrapper.h" 12 | #include "cpu.h" 13 | 14 | 15 | namespace ccbench::epoch { 16 | 17 | /** 18 | * @brief epoch_t 19 | * @details 20 | * tid_word is composed of union ... 21 | * 1bits : lock 22 | * 1bits : latest 23 | * 1bits : absent 24 | * 29bits : tid 25 | * 32 bits : epoch. 26 | * So epoch_t should be uint32_t. 27 | */ 28 | using epoch_t = std::uint32_t; 29 | 30 | [[maybe_unused]] alignas(CACHE_LINE_SIZE) inline epoch_t kGlobalEpoch; // NOLINT 31 | alignas(CACHE_LINE_SIZE) inline epoch_t kReclamationEpoch; // NOLINT 32 | 33 | // about epoch thread 34 | [[maybe_unused]] inline std::thread kEpochThread; // NOLINT 35 | inline std::atomic kEpochThreadEnd; // NOLINT 36 | 37 | [[maybe_unused]] extern uint32_t atomic_add_global_epoch(); 38 | 39 | [[maybe_unused]] extern bool check_epoch_loaded(); // NOLINT 40 | 41 | /** 42 | * @brief epoch thread 43 | * @pre this function is called by invoke_core_thread function. 44 | */ 45 | [[maybe_unused]] extern void epocher(); 46 | 47 | [[maybe_unused]] static epoch::epoch_t get_reclamation_epoch() { // NOLINT 48 | return loadAcquire(kReclamationEpoch); 49 | } 50 | 51 | /** 52 | * @brief invoke epocher thread. 53 | * @post invoke fin() to join this thread. 54 | */ 55 | [[maybe_unused]] static void invoke_epocher() { 56 | kEpochThreadEnd.store(false, std::memory_order_release); 57 | kEpochThread = std::thread(epocher); 58 | } 59 | 60 | [[maybe_unused]] static void join_epoch_thread() { kEpochThread.join(); } 61 | 62 | [[maybe_unused]] static std::uint32_t load_acquire_global_epoch() { // NOLINT 63 | return loadAcquire(epoch::kGlobalEpoch); 64 | } 65 | 66 | [[maybe_unused]] static void set_epoch_thread_end(bool tf) { 67 | kEpochThreadEnd.store(tf, std::memory_order_release); 68 | } 69 | 70 | 71 | alignas(CACHE_LINE_SIZE) inline time_t timestamp_; 72 | 73 | 74 | [[maybe_unused]] inline time_t get_lightweight_timestamp() 75 | { 76 | return loadAcquire(timestamp_); 77 | } 78 | 79 | 80 | } // namespace ccbench::epoch 81 | -------------------------------------------------------------------------------- /tpcc_silo/include/error.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file error.h 3 | * @brief error utilities. 4 | * @details This source is implemented by referring the source 5 | * https://github.com/starpos/oltp-cc-bench whose the author is Takashi Hoshino. 6 | * And Takayuki Tanabe revised. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace ccbench { 16 | 17 | class LibcError : public std::exception { 18 | private: 19 | std::string str_; 20 | 21 | static std::string generateMessage(int errnum, // NOLINT 22 | const std::string &msg) { 23 | std::string s(msg); 24 | constexpr std::size_t BUF_SIZE = 1024; 25 | std::array buf{}; 26 | ::snprintf(buf.data(), 1024, " %d ", errnum); // NOLINT 27 | s += buf.data(); 28 | if (::strerror_r(errnum, buf.data(), BUF_SIZE) != nullptr) { 29 | s += buf.data(); 30 | } 31 | return s; 32 | } 33 | 34 | public: 35 | explicit LibcError(int err_num = errno, // NOLINT 36 | const std::string &msg = "libc_error:") // NOLINT 37 | : str_(generateMessage(err_num, msg)) {} 38 | }; 39 | 40 | } // namespace ccbench 41 | -------------------------------------------------------------------------------- /tpcc_silo/include/fence.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file fence.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include "inline.h" 8 | 9 | namespace ccbench { 10 | 11 | INLINE void compilerFence() { asm volatile("":: : "memory"); } 12 | 13 | } // namespace ccbench 14 | 15 | -------------------------------------------------------------------------------- /tpcc_silo/include/garbage_collection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file garbage_collection.h 3 | * @brief about garbage collection 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "cpu.h" 15 | #include "epoch.h" 16 | #include "record.h" 17 | #include "heap_object.hpp" 18 | 19 | 20 | namespace ccbench::garbage_collection { 21 | 22 | using RecPtrContainer = std::deque; 23 | 24 | using ObjEpochInfo = std::pair; 25 | using ObjEpochContainer = std::deque; 26 | 27 | alignas(CACHE_LINE_SIZE) inline std::array< // NOLINT 28 | RecPtrContainer, KVS_NUMBER_OF_LOGICAL_CORES> kGarbageRecords; // NOLINT 29 | alignas(CACHE_LINE_SIZE) inline std::array< // NOLINT 30 | ObjEpochContainer, KVS_NUMBER_OF_LOGICAL_CORES> kGarbageValues; // NOLINT 31 | 32 | /** 33 | * @brief Delete RecPtrContainer kGarbageRecords at 34 | * ../gcollection.cc 35 | * @pre This function should be called at terminating db. 36 | * @return void 37 | */ 38 | extern void delete_all_garbage_records(); 39 | 40 | /** 41 | * @brief Delete first of ObjEpochContainer kGarbageValues at 42 | * ../gcollection.cc 43 | * @pre This function should be called at terminating db. 44 | * @return void 45 | */ 46 | extern void delete_all_garbage_values(); 47 | 48 | [[maybe_unused]] static RecPtrContainer &get_garbage_records_at(std::size_t index) { // NOLINT 49 | return kGarbageRecords.at(index); 50 | } 51 | 52 | [[maybe_unused]] static ObjEpochContainer &get_garbage_values_at(std::size_t index) { // NOLINT 53 | return kGarbageValues.at(index); 54 | } 55 | 56 | /** 57 | * @brief Release all heap objects in this system. 58 | * @details Do three functions: delete_all_garbage_values(), 59 | * delete_all_garbage_records(), and remove_all_leaf_from_mt_db_and_release(). 60 | * @pre This function should be called at terminating db. 61 | * @return void 62 | */ 63 | [[maybe_unused]] extern void release_all_heap_objects(); 64 | 65 | /** 66 | * @brief Remove all leaf nodes from MTDB and release those heap objects. 67 | * @pre This function should be called at terminating db. 68 | * @return void 69 | */ 70 | extern void remove_all_leaf_from_mt_db_and_release(); 71 | 72 | } // namespace ccbench::garbage_collection 73 | -------------------------------------------------------------------------------- /tpcc_silo/include/inline.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file inline.h 3 | */ 4 | 5 | #pragma once 6 | 7 | namespace ccbench { 8 | 9 | #define INLINE __attribute__((always_inline)) inline 10 | 11 | } // namespace ccbench 12 | -------------------------------------------------------------------------------- /tpcc_silo/include/memory.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file memory.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace ccbench { 14 | 15 | static void displayRusageRUMaxrss() { // NOLINT 16 | struct rusage r{}; 17 | if (getrusage(RUSAGE_SELF, &r) != 0) { 18 | std::cout << __FILE__ << " : " << __LINE__ << " : fatal error." 19 | << std::endl; 20 | std::abort(); 21 | } 22 | printf("maxrss:\t%ld kB\n", r.ru_maxrss); // NOLINT 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /tpcc_silo/include/record.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file record.h 3 | * @brief header about record 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "scheme_global.h" 9 | #include "tuple.h" 10 | #include "tid.h" 11 | 12 | namespace ccbench { 13 | 14 | class Record { // NOLINT 15 | public: 16 | Record() {} 17 | 18 | #if 0 // QQQQQ 19 | Record(std::string_view key, std::string_view val, std::align_val_t align) : tuple_(key, val, align) { 20 | init(); 21 | } 22 | #endif 23 | 24 | explicit Record(Tuple&& tuple) : tuple_(std::move(tuple)) { 25 | init(); 26 | } 27 | 28 | void init() { 29 | // init tidw 30 | tidw_.set_absent(true); 31 | tidw_.set_lock(true); 32 | } 33 | 34 | void set_for_load() { 35 | tidw_.set_absent(false); 36 | tidw_.set_lock(false); 37 | } 38 | 39 | Record(const Record &right) = default; 40 | 41 | Record(Record &&right) = default; 42 | 43 | Record &operator=(const Record &right) = default; // NOLINT 44 | Record &operator=(Record &&right) = default; // NOLINT 45 | 46 | tid_word &get_tidw() { return tidw_; } // NOLINT 47 | 48 | [[nodiscard]] const tid_word &get_tidw() const { return tidw_; } // NOLINT 49 | 50 | Tuple &get_tuple() { return tuple_; } // NOLINT 51 | 52 | [[nodiscard]] const Tuple &get_tuple() const { return tuple_; } // NOLINT 53 | 54 | void set_tidw(tid_word tidw) &{ tidw_.set_obj(tidw.get_obj()); } 55 | 56 | private: 57 | alignas(CACHE_LINE_SIZE) 58 | Tuple tuple_; 59 | tid_word tidw_; 60 | }; 61 | 62 | } // namespace ccbench 63 | -------------------------------------------------------------------------------- /tpcc_silo/include/result.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../../include/result.hh" 6 | 7 | extern std::vector SiloResult; 8 | 9 | extern void initResult(); 10 | -------------------------------------------------------------------------------- /tpcc_silo/include/session_info_table.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file session_info_table.h 3 | * @brief core work about shirakami. 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | #include "session_info.h" 11 | 12 | namespace ccbench { 13 | 14 | class session_info_table { 15 | public: 16 | /** 17 | * @brief Check wheter the session is already started. This function is not 18 | * thread safe. But this function can be used only after taking mutex. 19 | */ 20 | static Status decide_token(Token &token); // NOLINT 21 | 22 | /** 23 | * @brief fin work about kThreadTable 24 | */ 25 | static void fin_kThreadTable(); 26 | 27 | static std::array & 28 | get_thread_info_table() { // NOLINT 29 | return kThreadTable; 30 | } 31 | 32 | /** 33 | * @brief init work about kThreadTable 34 | */ 35 | static void init_kThreadTable(); 36 | 37 | private: 38 | static inline std::array // NOLINT 39 | kThreadTable; // NOLINT 40 | }; 41 | 42 | } // namespace ccbench 43 | -------------------------------------------------------------------------------- /tpcc_silo/include/tsc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file tsc.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | namespace ccbench { 10 | 11 | [[maybe_unused]] static uint64_t rdtsc() { // NOLINT 12 | uint64_t rax{}; 13 | uint64_t rdx{}; 14 | 15 | asm volatile("cpuid":: : "rax", "rbx", "rcx", "rdx"); // NOLINT 16 | asm volatile("rdtsc" : "=a"(rax), "=d"(rdx)); // NOLINT 17 | 18 | return (rdx << 32) | rax; // NOLINT 19 | } 20 | 21 | [[maybe_unused]] static uint64_t rdtscp() { // NOLINT 22 | uint64_t rax{}; 23 | uint64_t rdx{}; 24 | uint64_t aux{}; 25 | 26 | asm volatile("rdtscp" : "=a"(rax), "=d"(rdx), "=c"(aux)::); // NOLINT 27 | 28 | return (rdx << 32) | rax; // NOLINT 29 | } 30 | 31 | } // namespace ccbench 32 | -------------------------------------------------------------------------------- /tpcc_silo/include/util.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern void chkArg(); 4 | 5 | extern bool chkEpochLoaded(); 6 | 7 | extern void displayDB(); 8 | 9 | extern void displayParameter(); 10 | 11 | extern void genLogFile(std::string &logpath, const int thid); 12 | 13 | extern void leaderWork(uint64_t &epoch_timer_start, uint64_t &epoch_timer_stop); 14 | 15 | extern void makeDB(); 16 | 17 | extern void partTableInit([[maybe_unused]] size_t thid, uint64_t start, 18 | uint64_t end); 19 | 20 | extern void ShowOptParameters(); 21 | -------------------------------------------------------------------------------- /tpcc_silo/index/masstree_beta/masstree_beta_wrapper.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file masstree_wrapper.cc 3 | * @brief implement about masstree_wrapper 4 | */ 5 | 6 | #include 7 | 8 | #include "cpu.h" 9 | #include "masstree_beta_wrapper.h" 10 | #include "scheme_global.h" 11 | 12 | volatile mrcu_epoch_type active_epoch = 1; // NOLINT 13 | volatile uint64_t globalepoch = 1; // NOLINT 14 | [[maybe_unused]] volatile bool recovering = false; // NOLINT 15 | 16 | namespace ccbench { 17 | 18 | Status kohler_masstree::insert_record(Storage st, std::string_view key, Record *record) { 19 | masstree_wrapper::thread_init(cached_sched_getcpu()); 20 | Status insert_result(get_mtdb(st).insert_value(key, record)); 21 | return insert_result; 22 | } 23 | 24 | void * 25 | kohler_masstree::find_record(Storage st, std::string_view key) { 26 | masstree_wrapper::thread_init(cached_sched_getcpu()); 27 | return get_mtdb(st).get_value(key.data(), key.size()); 28 | } 29 | 30 | } // namespace shirakami 31 | -------------------------------------------------------------------------------- /tpcc_silo/interface/interface_delete.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file interface_delete.cpp 3 | * @brief implement about transaction 4 | */ 5 | 6 | #include 7 | 8 | #include "atomic_wrapper.h" 9 | #include "garbage_collection.h" 10 | #include "interface_helper.h" 11 | #include "index/masstree_beta/include/masstree_beta_wrapper.h" 12 | 13 | namespace ccbench { 14 | 15 | [[maybe_unused]] Status delete_all_records() { // NOLINT 16 | /** 17 | * INDEX_KOHLER_MASSTREE case 18 | * Since the destructor of the stored value is also called by the destructor 19 | * of kohler masstree, there is no need to do anything with 20 | * INDEX_KOHLER_MASSTREE. 21 | */ 22 | return Status::OK; 23 | } 24 | 25 | Status delete_record(Token token, Storage st, std::string_view key) { 26 | auto *ti = static_cast(token); 27 | if (!ti->get_txbegan()) tx_begin(token); 28 | Status check = ti->check_delete_after_write(st, key); 29 | 30 | masstree_wrapper::thread_init(cached_sched_getcpu()); 31 | Record *rec_ptr{ 32 | static_cast(kohler_masstree::get_mtdb(st).get_value(key))}; 33 | if (rec_ptr == nullptr) { 34 | return Status::WARN_NOT_FOUND; 35 | } 36 | tid_word check_tid(loadAcquire(rec_ptr->get_tidw().get_obj())); 37 | if (check_tid.get_absent()) { 38 | // The second condition checks 39 | // whether the record you want to read should not be read by parallel 40 | // insert / delete. 41 | return Status::WARN_NOT_FOUND; 42 | } 43 | 44 | ti->get_write_set().emplace_back(OP_TYPE::DELETE, st, rec_ptr); 45 | return check; 46 | } 47 | 48 | } // namespace ccbench 49 | -------------------------------------------------------------------------------- /tpcc_silo/interface/interface_helper.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file interface_helper.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include "session_info.h" 8 | 9 | namespace ccbench { 10 | 11 | /** 12 | * @brief read record by using dest given by caller and store read info to res 13 | * given by caller. 14 | * @pre the dest wasn't already read by itself. 15 | * @param [out] res it is stored read info. 16 | * @param [in] dest read record pointed by this dest. 17 | * @return WARN_CONCURRENT_DELETE No corresponding record in masstree. If you 18 | * have problem by WARN_NOT_FOUND, you should do abort. 19 | * @return Status::OK, it was ended correctly. 20 | * but it isn't committed yet. 21 | */ 22 | Status read_record(Record &res, const Record *dest); // NOLINT 23 | 24 | /** 25 | * @brief Transaction begins. 26 | * @details Get an epoch accessible to this transaction. 27 | * @return void 28 | */ 29 | void tx_begin(Token token); 30 | 31 | void write_phase(session_info *ti, const tid_word &max_r_set, 32 | const tid_word &max_w_set); 33 | 34 | } // namespace ccbench 35 | -------------------------------------------------------------------------------- /tpcc_silo/interface/interface_search.cpp: -------------------------------------------------------------------------------- 1 | #include "interface_helper.h" 2 | #include "session_info_table.h" 3 | #include "index/masstree_beta/include/masstree_beta_wrapper.h" 4 | #include "interface.h" // NOLINT 5 | 6 | namespace ccbench { 7 | 8 | 9 | Status search_key_local_set(session_info *ti, Storage storage, std::string_view key, Tuple **tuple) 10 | { 11 | write_set_obj *inws = ti->search_write_set(storage, key); 12 | if (inws != nullptr) { 13 | if (inws->get_op() == OP_TYPE::DELETE) { 14 | return Status::WARN_ALREADY_DELETE; 15 | } 16 | *tuple = &inws->get_tuple(inws->get_op()); 17 | return Status::WARN_READ_FROM_OWN_OPERATION; 18 | } 19 | 20 | read_set_obj *inrs = ti->search_read_set(storage, key); 21 | if (inrs != nullptr) { 22 | *tuple = &inrs->get_rec_read().get_tuple(); 23 | return Status::WARN_READ_FROM_OWN_OPERATION; 24 | } 25 | return Status::OK; 26 | } 27 | 28 | 29 | Status search_key(Token token, Storage storage, // NOLINT 30 | std::string_view key, Tuple **tuple) { 31 | auto *ti = static_cast(token); 32 | if (!ti->get_txbegan()) tx_begin(token); 33 | 34 | masstree_wrapper::thread_init(cached_sched_getcpu()); 35 | 36 | Status sta = search_key_local_set(ti, storage, key, tuple); 37 | if (sta != Status::OK) return sta; 38 | 39 | Record *rec_ptr{kohler_masstree::get_mtdb(storage).get_value(key.data(), key.size())}; 40 | if (rec_ptr == nullptr) { 41 | *tuple = nullptr; 42 | return Status::WARN_NOT_FOUND; 43 | } 44 | tid_word chk_tid(loadAcquire(rec_ptr->get_tidw().get_obj())); 45 | if (chk_tid.get_absent()) { 46 | // The second condition checks 47 | // whether the record you want to read should not be read by parallel 48 | // insert / delete. 49 | *tuple = nullptr; 50 | return Status::WARN_NOT_FOUND; 51 | } 52 | 53 | read_set_obj rs_ob(storage, rec_ptr); 54 | Status rr = read_record(rs_ob.get_rec_read(), rec_ptr); 55 | if (rr == Status::OK) { 56 | ti->get_read_set().emplace_back(std::move(rs_ob)); 57 | *tuple = &ti->get_read_set().back().get_rec_read().get_tuple(); 58 | } 59 | return rr; 60 | } 61 | 62 | } // namespace ccbench 63 | -------------------------------------------------------------------------------- /tpcc_silo/result.cpp: -------------------------------------------------------------------------------- 1 | #include "include/result.hh" 2 | #include "include/common.hh" 3 | 4 | #include "../include/cache_line_size.hh" 5 | #include "../include/result.hh" 6 | 7 | using namespace std; 8 | 9 | alignas(CACHE_LINE_SIZE) std::vector SiloResult; 10 | 11 | void initResult() { SiloResult.resize(FLAGS_thread_num); } 12 | -------------------------------------------------------------------------------- /tpcc_silo/scheme.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file scheme.cpp 3 | * @brief about scheme 4 | */ 5 | 6 | #include "garbage_collection.h" 7 | #include "session_info.h" 8 | 9 | namespace ccbench { 10 | 11 | bool write_set_obj::operator<(const write_set_obj &right) const { // NOLINT 12 | Storage lhs_st = get_st(); 13 | Storage rhs_st = right.get_st(); 14 | if (lhs_st != rhs_st) return lhs_st < rhs_st; 15 | 16 | std::string_view lhs_key = get_tuple().get_key(); 17 | std::string_view rhs_key = right.get_tuple().get_key(); 18 | return lhs_key < rhs_key; 19 | } 20 | 21 | } // namespace ccbench 22 | -------------------------------------------------------------------------------- /tpcc_silo/session_info_table.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file session_info_table.cpp 3 | * @brief about entire shirakami. 4 | */ 5 | 6 | #include "session_info_table.h" 7 | 8 | #include "garbage_collection.h" 9 | 10 | namespace ccbench { 11 | 12 | Status session_info_table::decide_token(Token &token) { // NOLINT 13 | for (auto &&itr : kThreadTable) { 14 | if (!itr.get_visible()) { 15 | bool expected(false); 16 | bool desired(true); 17 | if (itr.cas_visible(expected, desired)) { 18 | token = static_cast(&(itr)); 19 | break; 20 | } 21 | } 22 | if (&itr == kThreadTable.end() - 1) return Status::ERR_SESSION_LIMIT; 23 | } 24 | 25 | return Status::OK; 26 | } 27 | 28 | void session_info_table::init_kThreadTable() { 29 | uint64_t ctr(0); 30 | for (auto &&itr : kThreadTable) { 31 | itr.set_visible(false); 32 | itr.set_tx_began(false); 33 | 34 | /** 35 | * about garbage collection. 36 | * note : the length of kGarbageRecords is KVS_NUMBER_OF_LOGICAL_CORES. 37 | * So it needs surplus operation. 38 | */ 39 | std::size_t gc_index = ctr % KVS_NUMBER_OF_LOGICAL_CORES; 40 | itr.set_gc_container_index(gc_index); 41 | itr.set_gc_record_container( 42 | &garbage_collection::get_garbage_records_at(gc_index)); 43 | itr.set_gc_value_container( 44 | &garbage_collection::get_garbage_values_at(gc_index)); 45 | 46 | /** 47 | * about logging. 48 | */ 49 | #ifdef WAL 50 | itr->log_dir_.assign(kLogDirectory); 51 | itr->log_dir_.append("/log"); 52 | itr->log_dir_.append(std::to_string(ctr)); 53 | if (!itr->log_file_.open(itr->log_dir_, O_CREAT | O_TRUNC | O_WRONLY, 54 | 0644)) { 55 | ERR; 56 | } 57 | // itr->log_file_.ftruncate(10^9); // if it want to be high performance in 58 | // experiments, this line is used. 59 | #endif 60 | ++ctr; 61 | } 62 | } 63 | 64 | void session_info_table::fin_kThreadTable() { 65 | for (auto &&itr : kThreadTable) { 66 | /** 67 | * about holding operation info. 68 | */ 69 | itr.clean_up_ops_set(); 70 | 71 | /** 72 | * about scan operation 73 | */ 74 | itr.clean_up_scan_caches(); 75 | 76 | /** 77 | * about logging 78 | */ 79 | itr.get_log_set().clear(); 80 | #ifdef WAL 81 | itr->log_file_.close(); 82 | #endif 83 | } 84 | } 85 | 86 | } // namespace ccbench 87 | -------------------------------------------------------------------------------- /tpcc_silo/test/aligned_allocator_test.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thawk on 2020/08/12. 3 | // 4 | 5 | #include "gtest/gtest.h" 6 | #include "aligned_allocator.h" 7 | 8 | namespace ccbench::testing { 9 | 10 | using namespace ccbench; 11 | 12 | class aligned_allocator_test : public ::testing::Test { 13 | }; 14 | 15 | TEST_F(aligned_allocator_test, alignment_test) { // NOLINT 16 | ASSERT_EQ(true, true); 17 | constexpr std::size_t align = 64; 18 | std::unique_ptr, aligned_allocator>> str( 19 | new std::basic_string, aligned_allocator>()); 20 | str->assign("00000000000000000000"); 21 | ASSERT_EQ(reinterpret_cast(reinterpret_cast(str.get()->data())) % align, 22 | static_cast(0)); 23 | } 24 | 25 | } // namespace ccbench::testing -------------------------------------------------------------------------------- /tpcc_silo/test/scheme_global_test.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thawk on 2020/08/12. 3 | // 4 | 5 | #include "gtest/gtest.h" 6 | #include "scheme_global.h" 7 | 8 | namespace ccbench::testing { 9 | 10 | using namespace ccbench; 11 | 12 | class scheme_global_test : public ::testing::Test { 13 | }; 14 | 15 | TEST_F(scheme_global_test, storage_test) { // NOLINT 16 | ASSERT_EQ(static_cast(Storage::CUSTOMER), 0); 17 | ASSERT_EQ(static_cast(Storage::DISTRICT), 1); 18 | ASSERT_EQ(static_cast(Storage::HISTORY), 2); 19 | ASSERT_EQ(static_cast(Storage::ITEM), 3); 20 | ASSERT_EQ(static_cast(Storage::NEWORDER), 4); 21 | ASSERT_EQ(static_cast(Storage::ORDER), 5); 22 | ASSERT_EQ(static_cast(Storage::ORDERLINE), 6); 23 | ASSERT_EQ(static_cast(Storage::STOCK), 7); 24 | ASSERT_EQ(static_cast(Storage::WAREHOUSE), 8); 25 | ASSERT_EQ(static_cast(Storage::SECONDARY), 9); 26 | } 27 | 28 | } // namespace ccbench::testing -------------------------------------------------------------------------------- /tpcc_silo/test/tpcc_initializer_test.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thawk on 2020/08/12. 3 | // 4 | 5 | #define GLOBAL_VALUE_DEFINE 6 | #include "common.hh" 7 | #include "gtest/gtest.h" 8 | #include "tpcc/tpcc_initializer.hpp" 9 | 10 | namespace ccbench::testing { 11 | 12 | using namespace ccbench; 13 | using namespace TPCC::Initializer; 14 | 15 | class tpcc_initializer_test : public ::testing::Test { 16 | }; 17 | 18 | TEST_F(tpcc_initializer_test, db_insert_test) { // NOLINT 19 | std::string key{"key"}; 20 | std::string val{"val"}; 21 | HeapObject obj; 22 | obj.allocate(val.size()); 23 | ::memcpy(obj.data(), &val[0], val.size()); 24 | db_insert_raw(Storage::STOCK, key, std::move(obj)); 25 | void *ret_ptr = kohler_masstree::find_record(Storage::STOCK, key); 26 | ASSERT_NE(ret_ptr, nullptr); 27 | std::string_view ret_val_view = static_cast(ret_ptr)->get_tuple().get_val(); 28 | ASSERT_EQ(memcmp(val.data(), ret_val_view.data(), val.size()), 0); 29 | } 30 | 31 | } // namespace ccbench::testing 32 | -------------------------------------------------------------------------------- /tpcc_silo/test/tpcc_tables_test.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thawk on 2020/08/12. 3 | // 4 | 5 | #include "gtest/gtest.h" 6 | #include "tpcc/tpcc_tables.hpp" 7 | 8 | namespace ccbench::testing { 9 | 10 | using namespace ccbench; 11 | using namespace TPCC; 12 | 13 | class tpcc_tables_test : public ::testing::Test { 14 | }; 15 | 16 | TEST_F(tpcc_tables_test, tpcc_table) { // NOLINT 17 | // TODO 18 | ASSERT_EQ(true, true); 19 | } 20 | 21 | } // namespace ccbench::testing 22 | -------------------------------------------------------------------------------- /tpcc_silo/test/tpcc_util_test.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by thawk on 2020/08/12. 3 | // 4 | 5 | #include "gtest/gtest.h" 6 | #include "tpcc/tpcc_util.hpp" 7 | 8 | namespace ccbench::testing { 9 | 10 | using namespace ccbench; 11 | using namespace TPCC; 12 | 13 | class tpcc_util_test : public ::testing::Test { 14 | }; 15 | 16 | TEST_F(tpcc_util_test, random_number_test) { // NOLINT 17 | for (std::size_t i = 0; i < 100; ++i) { 18 | std::uint64_t a = random_64bits(); 19 | std::uint64_t b = random_64bits(); 20 | std::uint64_t max_num = std::max(a, b); 21 | std::uint64_t min_num = std::min(a, b); 22 | std::uint64_t c = random_int(min_num, max_num); 23 | ASSERT_EQ(min_num <= c, true); 24 | ASSERT_EQ(c <= max_num, true); 25 | } 26 | } 27 | 28 | } // namespace ccbench::testing 29 | -------------------------------------------------------------------------------- /tpcc_silo/tid.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file tid.cpp 3 | * @details implement about tid. 4 | */ 5 | 6 | #include "tid.h" 7 | 8 | #include 9 | #include 10 | 11 | namespace ccbench { 12 | 13 | void tid_word::display() { 14 | std::cout << "obj_ : " << std::bitset(obj_) // NOLINT 15 | << std::endl; // NOLINT 16 | std::cout << "lock_ : " << lock_ << std::endl; // NOLINT 17 | std::cout << "latest_ : " << latest_ << std::endl; // NOLINT 18 | std::cout << "absent_ : " << absent_ << std::endl; // NOLINT 19 | std::cout << "tid_ : " << tid_ << std::endl; // NOLINT 20 | std::cout << "epoch_ : " << epoch_ << std::endl; // NOLINT 21 | } 22 | 23 | } // namespace ccbench 24 | -------------------------------------------------------------------------------- /tpcc_silo/tpcc/tpcc_txn.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file tpcc_txn.hpp 3 | */ 4 | 5 | #pragma once 6 | 7 | namespace TPCC { 8 | bool run_new_order(query::NewOrder *query, Token &token); 9 | 10 | bool run_payment(query::Payment *query, HistoryKeyGenerator *hkg, Token &token); 11 | } 12 | -------------------------------------------------------------------------------- /tpcc_silo/util.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include // syscall(SYS_gettid), 3 | 4 | #include 5 | #include 6 | 7 | #include "include/atomic_tool.hh" 8 | #include "include/util.hh" 9 | 10 | #include "../include/debug.hh" 11 | #include "../include/util.hh" 12 | 13 | void chkArg() { 14 | displayParameter(); 15 | 16 | if (FLAGS_perc_payment > 100) { 17 | cout << "FLAGS_perc_payment must be 0..100 ..." << endl; 18 | ERR; 19 | } 20 | if (FLAGS_perc_order_status > 100) { 21 | cout << "FLAGS_perc_order_status must be 0..100 ..." << endl; 22 | ERR; 23 | } 24 | if (FLAGS_perc_delivery > 100) { 25 | cout << "FLAGS_perc_delivery must be 0..100 ..." << endl; 26 | ERR; 27 | } 28 | if (FLAGS_perc_stock_level > 100) { 29 | cout << "FLAGS_perc_stock_level must be 0..100 ..." << endl; 30 | ERR; 31 | } 32 | if (FLAGS_perc_payment + FLAGS_perc_order_status 33 | + FLAGS_perc_delivery + FLAGS_perc_stock_level > 100) { 34 | cout << "sum of FLAGS_perc_[payment,order_status,delivery,stock_level] must be 0..100 ..." << endl; 35 | ERR; 36 | } 37 | if (posix_memalign((void **) &ThLocalEpoch, CACHE_LINE_SIZE, 38 | FLAGS_thread_num * sizeof(uint64_t_64byte)) != 0) 39 | ERR; 40 | if (posix_memalign((void **) &CTIDW, CACHE_LINE_SIZE, 41 | FLAGS_thread_num * sizeof(uint64_t_64byte)) != 0) 42 | ERR; 43 | 44 | // init 45 | for (unsigned int i = 0; i < FLAGS_thread_num; ++i) { 46 | ThLocalEpoch[i].obj_ = 0; 47 | CTIDW[i].obj_ = 0; 48 | } 49 | } 50 | 51 | void displayParameter() { 52 | cout << "#FLAGS_thread_num:\t" << FLAGS_thread_num << endl; 53 | cout << "#FLAGS_clocks_per_us:\t" << FLAGS_clocks_per_us << endl; 54 | cout << "#FLAGS_epoch_time:\t" << FLAGS_epoch_time << endl; 55 | cout << "#FLAGS_extime:\t\t" << FLAGS_extime << endl; 56 | cout << "#FLAGS_num_wh:\t\t" << FLAGS_num_wh << endl; 57 | cout << "#FLAGS_perc_payment:\t\t" << FLAGS_perc_payment << endl; 58 | cout << "#FLAGS_perc_order_status:\t" << FLAGS_perc_order_status << endl; 59 | cout << "#FLAGS_perc_delivery:\t\t" << FLAGS_perc_delivery << endl; 60 | cout << "#FLAGS_perc_stock_level:\t" << FLAGS_perc_stock_level << endl; 61 | cout << "#FLAGS_insert_exe:\t" << FLAGS_insert_exe << endl; 62 | } 63 | 64 | void genLogFile([[maybe_unused]] std::string &logpath, [[maybe_unused]]const int thid) { 65 | /* 66 | genLogFileName(logpath, thid); 67 | createEmptyFile(logpath); 68 | */ 69 | } 70 | --------------------------------------------------------------------------------