├── LICENSE
├── README.md
└── src
├── CMakeLists.txt
├── allocators
├── glib_allocator.h
├── intel.h
├── jemalloc_allocator.h
└── super_malloc_allocator.h
├── bench
├── action_generator.h
├── allocators.cpp
├── allocators.h
├── arg_parsing.cpp
├── arg_parsing.h
├── benchmark_config.cpp
├── benchmark_config.h
├── benchmark_results.h
├── benchmark_summary.cpp
├── benchmark_summary.h
├── benchmark_table.h
├── random.cpp
├── random.h
├── table.cpp
├── table.h
├── thread_papi_wrapper.cpp
├── thread_papi_wrapper.h
├── thread_pinner.h
├── utils.cpp
└── utils.h
├── cmake
└── FindPAPI.cmake
├── hash-tables
├── common.h
├── hs_locked.h
├── hs_serial.h
├── hs_trans.h
├── hsbm_lf.h
├── hsbm_locked.h
├── main.cpp
├── ph_qp.h
└── table_init.h
├── mem-reclaimer
├── leaky.h
├── reclaimer.cpp
└── reclaimer.h
├── primitives
├── backoff.cpp
├── backoff.h
├── barrier.h
├── brown_kcas.h
├── brown_original_kcas.h
├── cache_utils.h
├── harris_kcas.h
├── locks.cpp
├── locks.h
└── marked_pointers.h
└── random
├── lcg.h
├── pcg_extras.h
├── pcg_random.h
├── pcg_uint128.h
└── xorshift.h
/README.md:
--------------------------------------------------------------------------------
1 | # Lock-Free Hopscotch Hashing
2 |
3 | ## Tables present
4 | 1. Lock-Free Hopscotch Hashing
5 | 2. Locked Hopscotch (Bit-map variant)
6 | 3. Locked Hopscotch (Relative offset variant)
7 | 4. Purcell-Harris lock-free quadratic programming.
8 |
9 | ## Build instruction
10 | These benchmarks require a number of dependencies.
11 | * [A CPU topology library for smart thread pinning](https://github.com/Maratyszcza/cpuinfo)
12 | * [JeMalloc](https://github.com/jemalloc/jemalloc)
13 | * CMake (Installed via system package manager)
14 | * PAPI (Installed via system package manager)
15 | * Boost (Installed via system package manager)
16 |
17 | Our code was tested and ran on Ubuntu 14.04, 16.04, and 18.04. The code itself uses the CMake build system. When testing make sure to compile the code in release! Or at least *our code*...
18 |
19 | ## Run instructions
20 | Once built the binary takes a number of arguments at command-line parameters and through standard input.
21 |
22 | Brief explanation of the command.
23 | * -T ==> Number of threads
24 | * -L ==> Load factor 1.0 is full, 0.0 is empty, 0.4 is 40% full, etc.
25 | * -S ==> Table size as a power of 2.
26 | * -D ==> Number of seconds to run the benchmark procedure for.
27 | * -U ==> Percentage updates
28 | * -B ==> Table to benchmark
29 | * -M ==> Memory reclaimer
30 | * -A ==> What allocator to use.
31 | * -P ==> Whether PAPI is turned on.
32 | * -R ==> Choice of random number generator
33 |
34 | Here are some example commands. All parameters have default values if none are provided.
35 |
36 | * ./concurrent_hash_tables -T 1 -L 0.6 -S 23 -D 10 -U 10 -P true -M leaky -A je -R xor_shift_64 -B hsbm_lf_set
37 | * ./concurrent_hash_tables -T 4 -L 0.6 -S 23 -D 10 -U 30 -P true -M leaky -A je -R xor_shift_64 -B hsbm_locked_set
38 | * ./concurrent_hash_tables -T 8 -L 0.8 -S 23 -D 10 -U 40 -P true -M leaky -A je -R xor_shift_64 -B ph_qp_set
39 |
40 | The results are put into two csv files, one containing the keys and the other containing the specific info.
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | project(concurrent_data_structures)
2 | cmake_minimum_required(VERSION 3.1)
3 |
4 |
5 | include_directories(.)
6 |
7 | find_package(Boost COMPONENTS system filesystem REQUIRED)
8 | FILE(GLOB_RECURSE HeaderCFiles "*.h")
9 |
10 |
11 | aux_source_directory(allocators COMMON_LIST)
12 | aux_source_directory(bench COMMON_LIST)
13 | aux_source_directory(mem-reclaimer COMMON_LIST)
14 | aux_source_directory(primitives COMMON_LIST)
15 | aux_source_directory(sets HASH_TABLE)
16 | aux_source_directory(random RANDOM_GENERATORS)
17 |
18 |
19 |
20 | set(HASH_TABLE_EXE "concurrent_hash_tables")
21 |
22 | set(LIBS
23 | ${Boost_FILESYSTEM_LIBRARY}
24 | ${Boost_SYSTEM_LIBRARY}
25 | -latomic
26 | -lpapi
27 | -ljemalloc
28 | -lsupermalloc
29 | -lrt
30 | -lcpuinfo
31 | -ltbb
32 | -ltbbmalloc
33 | -lpthread)
34 |
35 | add_executable(${HASH_TABLE_EXE} hash-tables/main.cpp ${COMMON_LIST} ${HeaderCFiles})
36 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -mrtm -Wall -fno-omit-frame-pointer -flto")
37 |
38 |
39 | TARGET_LINK_LIBRARIES(${HASH_TABLE_EXE} ${LIBS})
40 |
--------------------------------------------------------------------------------
/src/allocators/glib_allocator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 | Simple wrapper around standard malloc.
5 | Copyright (C) 2018 Robert Kelly
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | #include
22 | #include
23 |
24 | struct GlibcAllocator {
25 | static void *malloc(size_t size) { return std::malloc(size); }
26 | static void *aligned_alloc(size_t alignment, size_t size) {
27 | return ::aligned_alloc(alignment, size);
28 | }
29 | static void free(void *ptr) { std::free(ptr); }
30 | static size_t malloc_usable_size(void *ptr) {
31 | return ::malloc_usable_size(ptr);
32 | }
33 | };
34 |
--------------------------------------------------------------------------------
/src/allocators/intel.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 | Simple wrapper around Intel scalable allocator.
5 | Copyright (C) 2018 Robert Kelly
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | #include
22 |
23 | struct IntelAllocator {
24 | static void *malloc(size_t size) { return scalable_malloc(size); }
25 | static void *aligned_alloc(size_t alignment, size_t size) {
26 | return scalable_aligned_malloc(alignment, size);
27 | }
28 | static void free(void *ptr) { scalable_free(ptr); }
29 | static size_t malloc_usable_size(void *ptr) { return scalable_msize(ptr); }
30 | };
31 |
--------------------------------------------------------------------------------
/src/allocators/jemalloc_allocator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 | Simple wrapper around the mangled JeMalloc allocator.
5 | Copyright (C) 2018 Robert Kelly
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | #include
22 |
23 | struct JeMallocAllocator {
24 | static void *malloc(size_t size) { return je_malloc(size); }
25 | static void *aligned_alloc(size_t alignment, size_t size) {
26 | return je_aligned_alloc(alignment, size);
27 | }
28 | static void free(void *ptr) { je_free(ptr); }
29 | static size_t malloc_usable_size(void *ptr) {
30 | return je_malloc_usable_size(ptr);
31 | }
32 | };
33 |
--------------------------------------------------------------------------------
/src/allocators/super_malloc_allocator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 | Simple wrapper around the mangled SuperMalloc allocator.
5 | Copyright (C) 2018 Robert Kelly
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | #include
22 |
23 | extern "C" void *__super_malloc(size_t);
24 | extern "C" void *__super_aligned_alloc(size_t, size_t);
25 | extern "C" void __super_free(void *);
26 | extern "C" size_t __super_malloc_usable_size(void *);
27 |
28 | struct SuperMallocAllocator {
29 | static void *malloc(size_t size) { return __super_malloc(size); }
30 | static void *aligned_alloc(size_t alignment, size_t size) {
31 | return __super_aligned_alloc(alignment, size);
32 | }
33 | static void free(void *ptr) { return __super_free(ptr); }
34 | static size_t malloc_usable_size(void *ptr) {
35 | return __super_malloc_usable_size(ptr);
36 | }
37 | };
38 |
--------------------------------------------------------------------------------
/src/bench/action_generator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 | Generates random actions for benchmarking tools.
5 | Copyright (C) 2018 Robert Kelly
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | #include "benchmark_config.h"
22 | #include "random/lcg.h"
23 | #include "random/pcg_random.h"
24 | #include "random/xorshift.h"
25 | #include
26 | #include
27 |
28 | namespace concurrent_data_structures {
29 |
30 | enum class SetAction {
31 | Contains,
32 | Add,
33 | Remove,
34 | };
35 |
36 | template class SetActionGenerator {
37 | private:
38 | Random m_action_generator;
39 | Random m_key_generator;
40 | const std::uintptr_t m_key_mask;
41 | const std::uintptr_t m_read_limit, m_add_limit;
42 |
43 | public:
44 | SetActionGenerator(const SetBenchmarkConfig &config)
45 | : m_action_generator(std::random_device{}()),
46 | m_key_generator(std::random_device{}()),
47 | m_key_mask((config.table_size) - 1),
48 | m_read_limit((m_key_mask) -
49 | (static_cast(m_key_mask) *
50 | static_cast(config.updates) / 100.0)),
51 | m_add_limit(m_read_limit +
52 | (static_cast(m_key_mask) *
53 | static_cast(config.updates) / 200.0)) {}
54 | SetAction generate_action() {
55 | const std::uintptr_t action = m_action_generator.next_rand() & m_key_mask;
56 | if (action <= m_read_limit) {
57 | return SetAction::Contains;
58 | } else if (action <= m_add_limit) {
59 | return SetAction::Add;
60 | } else {
61 | return SetAction::Remove;
62 | }
63 | }
64 | Key generate_key() {
65 | const Key key = m_key_generator.next_rand() & m_key_mask;
66 | return key;
67 | }
68 | };
69 | }
70 |
--------------------------------------------------------------------------------
/src/bench/allocators.cpp:
--------------------------------------------------------------------------------
1 | #include "allocators.h"
2 |
3 | /*
4 | Maps allocators to human strings.
5 | Copyright (C) 2018 Robert Kelly
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | #include