From ff70913f8b9bfe7fdeed1d533f90ec7e1289e996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Mon, 2 Feb 2026 18:44:20 +0100 Subject: [PATCH 01/16] Move queues into data_structures folder --- .gitmodules | 4 ++-- {queues => data_structures/queues}/array_queue/Cargo.toml | 0 {queues => data_structures/queues}/array_queue/src/lib.rs | 0 {queues => data_structures/queues}/array_queue/src/main.rs | 0 {queues => data_structures/queues}/atomic_queue/Cargo.toml | 0 {queues => data_structures/queues}/atomic_queue/src/lib.rs | 0 {queues => data_structures/queues}/atomic_queue/src/main.rs | 0 {queues => data_structures/queues}/basic_queue/Cargo.toml | 0 {queues => data_structures/queues}/basic_queue/src/lib.rs | 0 {queues => data_structures/queues}/basic_queue/src/main.rs | 0 {queues => data_structures/queues}/bbq/Cargo.toml | 0 {queues => data_structures/queues}/bbq/src/lib.rs | 0 {queues => data_structures/queues}/bbq/src/main.rs | 0 {queues => data_structures/queues}/boost_queue_cpp/Cargo.toml | 0 {queues => data_structures/queues}/boost_queue_cpp/build.rs | 0 .../queues}/boost_queue_cpp/cpp_src/boost_wrapper.cpp | 0 .../queues}/boost_queue_cpp/cpp_src/boost_wrapper.hpp | 0 {queues => data_structures/queues}/boost_queue_cpp/src/lib.rs | 0 .../queues}/boost_queue_cpp/src/main.rs | 0 .../queues}/bounded_concurrent_queue/Cargo.toml | 0 .../queues}/bounded_concurrent_queue/src/lib.rs | 0 .../queues}/bounded_concurrent_queue/src/main.rs | 0 .../queues}/bounded_ringbuffer/Cargo.toml | 0 .../queues}/bounded_ringbuffer/src/lib.rs | 0 .../queues}/bounded_ringbuffer/src/main.rs | 0 {queues => data_structures/queues}/faaa_queue/Cargo.toml | 0 {queues => data_structures/queues}/faaa_queue/src/lib.rs | 0 {queues => data_structures/queues}/faaa_queue/src/main.rs | 0 {queues => data_structures/queues}/faaa_queue_cpp/Cargo.toml | 0 {queues => data_structures/queues}/faaa_queue_cpp/build.rs | 0 .../faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp | 0 .../faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp | 0 .../queues}/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp | 0 .../queues}/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp | 0 {queues => data_structures/queues}/faaa_queue_cpp/src/lib.rs | 0 {queues => data_structures/queues}/faaa_queue_cpp/src/main.rs | 0 {queues => data_structures/queues}/lcrq/Cargo.toml | 0 {queues => data_structures/queues}/lcrq/src/lib.rs | 0 {queues => data_structures/queues}/lcrq/src/main.rs | 0 {queues => data_structures/queues}/lcrq_cpp/Cargo.toml | 0 {queues => data_structures/queues}/lcrq_cpp/build.rs | 0 .../queues}/lcrq_cpp/cpp_src/HazardPointers.hpp | 0 .../queues}/lcrq_cpp/cpp_src/LCRQueue.hpp | 0 .../queues}/lcrq_cpp/cpp_src/lcrq_wrapper.cpp | 0 .../queues}/lcrq_cpp/cpp_src/lcrq_wrapper.hpp | 0 {queues => data_structures/queues}/lcrq_cpp/src/lib.rs | 0 {queues => data_structures/queues}/lcrq_cpp/src/main.rs | 0 {queues => data_structures/queues}/lf_queue/Cargo.toml | 0 {queues => data_structures/queues}/lf_queue/src/lib.rs | 0 {queues => data_structures/queues}/lf_queue/src/main.rs | 0 {queues => data_structures/queues}/lockfree_queue/Cargo.toml | 0 {queues => data_structures/queues}/lockfree_queue/src/lib.rs | 0 {queues => data_structures/queues}/lockfree_queue/src/main.rs | 0 {queues => data_structures/queues}/lprq/Cargo.toml | 0 {queues => data_structures/queues}/lprq/src/lib.rs | 0 {queues => data_structures/queues}/lprq/src/lprq_rs.rs | 0 {queues => data_structures/queues}/lprq/src/main.rs | 0 {queues => data_structures/queues}/lprq_cpp/Cargo.toml | 0 {queues => data_structures/queues}/lprq_cpp/build.rs | 0 .../lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore | 0 .../lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore | 0 .../lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake | 0 .../lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt | 0 .../lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile | 0 .../lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake | 0 .../queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE | 0 .../lprq_cpp/cpp_src/cpp-ring-queues-research/README.md | 0 .../cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp | 0 .../cpp_src/cpp-ring-queues-research/include/Forked.hpp | 0 .../cpp-ring-queues-research/include/HazardPointers.hpp | 0 .../cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp | 0 .../cpp-ring-queues-research/include/LinkedRingQueue.hpp | 0 .../cpp-ring-queues-research/include/MetaprogrammingUtils.hpp | 0 .../cpp_src/cpp-ring-queues-research/include/Metrics.hpp | 0 .../cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp | 0 .../cpp_src/cpp-ring-queues-research/include/RQCell.hpp | 0 .../cpp_src/cpp-ring-queues-research/include/Stats.hpp | 0 .../cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp | 0 .../cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp | 0 .../queues}/lprq_cpp/cpp_src/lprq_wrapper.cpp | 0 .../queues}/lprq_cpp/cpp_src/lprq_wrapper.hpp | 0 {queues => data_structures/queues}/lprq_cpp/src/lib.rs | 0 {queues => data_structures/queues}/lprq_cpp/src/main.rs | 0 {queues => data_structures/queues}/moodycamel_cpp/Cargo.toml | 0 {queues => data_structures/queues}/moodycamel_cpp/build.rs | 0 .../queues}/moodycamel_cpp/cpp_src/concurrentqueue | 0 .../queues}/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp | 0 .../queues}/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp | 0 {queues => data_structures/queues}/moodycamel_cpp/src/lib.rs | 0 {queues => data_structures/queues}/moodycamel_cpp/src/main.rs | 0 {queues => data_structures/queues}/ms_queue/Cargo.toml | 0 {queues => data_structures/queues}/ms_queue/src/lib.rs | 0 {queues => data_structures/queues}/ms_queue/src/main.rs | 0 {queues => data_structures/queues}/scc2_queue/Cargo.toml | 0 {queues => data_structures/queues}/scc2_queue/src/lib.rs | 0 {queues => data_structures/queues}/scc2_queue/src/main.rs | 0 {queues => data_structures/queues}/scc_queue/Cargo.toml | 0 {queues => data_structures/queues}/scc_queue/src/lib.rs | 0 {queues => data_structures/queues}/scc_queue/src/main.rs | 0 {queues => data_structures/queues}/seg_queue/Cargo.toml | 0 {queues => data_structures/queues}/seg_queue/src/lib.rs | 0 {queues => data_structures/queues}/seg_queue/src/main.rs | 0 {queues => data_structures/queues}/tz_queue_hp/Cargo.toml | 0 {queues => data_structures/queues}/tz_queue_hp/src/lib.rs | 0 {queues => data_structures/queues}/tz_queue_hp/src/main.rs | 0 {queues => data_structures/queues}/tz_queue_leak/Cargo.toml | 0 {queues => data_structures/queues}/tz_queue_leak/src/lib.rs | 0 {queues => data_structures/queues}/tz_queue_leak/src/main.rs | 0 .../queues}/unbounded_concurrent_queue/Cargo.toml | 0 .../queues}/unbounded_concurrent_queue/src/lib.rs | 0 .../queues}/unbounded_concurrent_queue/src/main.rs | 0 {queues => data_structures/queues}/wf_queue/Cargo.toml | 0 {queues => data_structures/queues}/wf_queue/src/lib.rs | 0 {queues => data_structures/queues}/wf_queue/src/main.rs | 0 114 files changed, 2 insertions(+), 2 deletions(-) rename {queues => data_structures/queues}/array_queue/Cargo.toml (100%) rename {queues => data_structures/queues}/array_queue/src/lib.rs (100%) rename {queues => data_structures/queues}/array_queue/src/main.rs (100%) rename {queues => data_structures/queues}/atomic_queue/Cargo.toml (100%) rename {queues => data_structures/queues}/atomic_queue/src/lib.rs (100%) rename {queues => data_structures/queues}/atomic_queue/src/main.rs (100%) rename {queues => data_structures/queues}/basic_queue/Cargo.toml (100%) rename {queues => data_structures/queues}/basic_queue/src/lib.rs (100%) rename {queues => data_structures/queues}/basic_queue/src/main.rs (100%) rename {queues => data_structures/queues}/bbq/Cargo.toml (100%) rename {queues => data_structures/queues}/bbq/src/lib.rs (100%) rename {queues => data_structures/queues}/bbq/src/main.rs (100%) rename {queues => data_structures/queues}/boost_queue_cpp/Cargo.toml (100%) rename {queues => data_structures/queues}/boost_queue_cpp/build.rs (100%) rename {queues => data_structures/queues}/boost_queue_cpp/cpp_src/boost_wrapper.cpp (100%) rename {queues => data_structures/queues}/boost_queue_cpp/cpp_src/boost_wrapper.hpp (100%) rename {queues => data_structures/queues}/boost_queue_cpp/src/lib.rs (100%) rename {queues => data_structures/queues}/boost_queue_cpp/src/main.rs (100%) rename {queues => data_structures/queues}/bounded_concurrent_queue/Cargo.toml (100%) rename {queues => data_structures/queues}/bounded_concurrent_queue/src/lib.rs (100%) rename {queues => data_structures/queues}/bounded_concurrent_queue/src/main.rs (100%) rename {queues => data_structures/queues}/bounded_ringbuffer/Cargo.toml (100%) rename {queues => data_structures/queues}/bounded_ringbuffer/src/lib.rs (100%) rename {queues => data_structures/queues}/bounded_ringbuffer/src/main.rs (100%) rename {queues => data_structures/queues}/faaa_queue/Cargo.toml (100%) rename {queues => data_structures/queues}/faaa_queue/src/lib.rs (100%) rename {queues => data_structures/queues}/faaa_queue/src/main.rs (100%) rename {queues => data_structures/queues}/faaa_queue_cpp/Cargo.toml (100%) rename {queues => data_structures/queues}/faaa_queue_cpp/build.rs (100%) rename {queues => data_structures/queues}/faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp (100%) rename {queues => data_structures/queues}/faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp (100%) rename {queues => data_structures/queues}/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp (100%) rename {queues => data_structures/queues}/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp (100%) rename {queues => data_structures/queues}/faaa_queue_cpp/src/lib.rs (100%) rename {queues => data_structures/queues}/faaa_queue_cpp/src/main.rs (100%) rename {queues => data_structures/queues}/lcrq/Cargo.toml (100%) rename {queues => data_structures/queues}/lcrq/src/lib.rs (100%) rename {queues => data_structures/queues}/lcrq/src/main.rs (100%) rename {queues => data_structures/queues}/lcrq_cpp/Cargo.toml (100%) rename {queues => data_structures/queues}/lcrq_cpp/build.rs (100%) rename {queues => data_structures/queues}/lcrq_cpp/cpp_src/HazardPointers.hpp (100%) rename {queues => data_structures/queues}/lcrq_cpp/cpp_src/LCRQueue.hpp (100%) rename {queues => data_structures/queues}/lcrq_cpp/cpp_src/lcrq_wrapper.cpp (100%) rename {queues => data_structures/queues}/lcrq_cpp/cpp_src/lcrq_wrapper.hpp (100%) rename {queues => data_structures/queues}/lcrq_cpp/src/lib.rs (100%) rename {queues => data_structures/queues}/lcrq_cpp/src/main.rs (100%) rename {queues => data_structures/queues}/lf_queue/Cargo.toml (100%) rename {queues => data_structures/queues}/lf_queue/src/lib.rs (100%) rename {queues => data_structures/queues}/lf_queue/src/main.rs (100%) rename {queues => data_structures/queues}/lockfree_queue/Cargo.toml (100%) rename {queues => data_structures/queues}/lockfree_queue/src/lib.rs (100%) rename {queues => data_structures/queues}/lockfree_queue/src/main.rs (100%) rename {queues => data_structures/queues}/lprq/Cargo.toml (100%) rename {queues => data_structures/queues}/lprq/src/lib.rs (100%) rename {queues => data_structures/queues}/lprq/src/lprq_rs.rs (100%) rename {queues => data_structures/queues}/lprq/src/main.rs (100%) rename {queues => data_structures/queues}/lprq_cpp/Cargo.toml (100%) rename {queues => data_structures/queues}/lprq_cpp/build.rs (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/README.md (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Forked.hpp (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/HazardPointers.hpp (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LinkedRingQueue.hpp (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/MetaprogrammingUtils.hpp (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Metrics.hpp (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/RQCell.hpp (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Stats.hpp (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/lprq_wrapper.cpp (100%) rename {queues => data_structures/queues}/lprq_cpp/cpp_src/lprq_wrapper.hpp (100%) rename {queues => data_structures/queues}/lprq_cpp/src/lib.rs (100%) rename {queues => data_structures/queues}/lprq_cpp/src/main.rs (100%) rename {queues => data_structures/queues}/moodycamel_cpp/Cargo.toml (100%) rename {queues => data_structures/queues}/moodycamel_cpp/build.rs (100%) rename {queues => data_structures/queues}/moodycamel_cpp/cpp_src/concurrentqueue (100%) rename {queues => data_structures/queues}/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp (100%) rename {queues => data_structures/queues}/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp (100%) rename {queues => data_structures/queues}/moodycamel_cpp/src/lib.rs (100%) rename {queues => data_structures/queues}/moodycamel_cpp/src/main.rs (100%) rename {queues => data_structures/queues}/ms_queue/Cargo.toml (100%) rename {queues => data_structures/queues}/ms_queue/src/lib.rs (100%) rename {queues => data_structures/queues}/ms_queue/src/main.rs (100%) rename {queues => data_structures/queues}/scc2_queue/Cargo.toml (100%) rename {queues => data_structures/queues}/scc2_queue/src/lib.rs (100%) rename {queues => data_structures/queues}/scc2_queue/src/main.rs (100%) rename {queues => data_structures/queues}/scc_queue/Cargo.toml (100%) rename {queues => data_structures/queues}/scc_queue/src/lib.rs (100%) rename {queues => data_structures/queues}/scc_queue/src/main.rs (100%) rename {queues => data_structures/queues}/seg_queue/Cargo.toml (100%) rename {queues => data_structures/queues}/seg_queue/src/lib.rs (100%) rename {queues => data_structures/queues}/seg_queue/src/main.rs (100%) rename {queues => data_structures/queues}/tz_queue_hp/Cargo.toml (100%) rename {queues => data_structures/queues}/tz_queue_hp/src/lib.rs (100%) rename {queues => data_structures/queues}/tz_queue_hp/src/main.rs (100%) rename {queues => data_structures/queues}/tz_queue_leak/Cargo.toml (100%) rename {queues => data_structures/queues}/tz_queue_leak/src/lib.rs (100%) rename {queues => data_structures/queues}/tz_queue_leak/src/main.rs (100%) rename {queues => data_structures/queues}/unbounded_concurrent_queue/Cargo.toml (100%) rename {queues => data_structures/queues}/unbounded_concurrent_queue/src/lib.rs (100%) rename {queues => data_structures/queues}/unbounded_concurrent_queue/src/main.rs (100%) rename {queues => data_structures/queues}/wf_queue/Cargo.toml (100%) rename {queues => data_structures/queues}/wf_queue/src/lib.rs (100%) rename {queues => data_structures/queues}/wf_queue/src/main.rs (100%) diff --git a/.gitmodules b/.gitmodules index fe0feb3..9f39963 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "queues/moodycamel_cpp/cpp_src/concurrentqueue"] - path = queues/moodycamel_cpp/cpp_src/concurrentqueue +[submodule "data_structures/queues/moodycamel_cpp/cpp_src/concurrentqueue"] + path = data_structures/queues/moodycamel_cpp/cpp_src/concurrentqueue url = https://github.com/cameron314/concurrentqueue.git diff --git a/queues/array_queue/Cargo.toml b/data_structures/queues/array_queue/Cargo.toml similarity index 100% rename from queues/array_queue/Cargo.toml rename to data_structures/queues/array_queue/Cargo.toml diff --git a/queues/array_queue/src/lib.rs b/data_structures/queues/array_queue/src/lib.rs similarity index 100% rename from queues/array_queue/src/lib.rs rename to data_structures/queues/array_queue/src/lib.rs diff --git a/queues/array_queue/src/main.rs b/data_structures/queues/array_queue/src/main.rs similarity index 100% rename from queues/array_queue/src/main.rs rename to data_structures/queues/array_queue/src/main.rs diff --git a/queues/atomic_queue/Cargo.toml b/data_structures/queues/atomic_queue/Cargo.toml similarity index 100% rename from queues/atomic_queue/Cargo.toml rename to data_structures/queues/atomic_queue/Cargo.toml diff --git a/queues/atomic_queue/src/lib.rs b/data_structures/queues/atomic_queue/src/lib.rs similarity index 100% rename from queues/atomic_queue/src/lib.rs rename to data_structures/queues/atomic_queue/src/lib.rs diff --git a/queues/atomic_queue/src/main.rs b/data_structures/queues/atomic_queue/src/main.rs similarity index 100% rename from queues/atomic_queue/src/main.rs rename to data_structures/queues/atomic_queue/src/main.rs diff --git a/queues/basic_queue/Cargo.toml b/data_structures/queues/basic_queue/Cargo.toml similarity index 100% rename from queues/basic_queue/Cargo.toml rename to data_structures/queues/basic_queue/Cargo.toml diff --git a/queues/basic_queue/src/lib.rs b/data_structures/queues/basic_queue/src/lib.rs similarity index 100% rename from queues/basic_queue/src/lib.rs rename to data_structures/queues/basic_queue/src/lib.rs diff --git a/queues/basic_queue/src/main.rs b/data_structures/queues/basic_queue/src/main.rs similarity index 100% rename from queues/basic_queue/src/main.rs rename to data_structures/queues/basic_queue/src/main.rs diff --git a/queues/bbq/Cargo.toml b/data_structures/queues/bbq/Cargo.toml similarity index 100% rename from queues/bbq/Cargo.toml rename to data_structures/queues/bbq/Cargo.toml diff --git a/queues/bbq/src/lib.rs b/data_structures/queues/bbq/src/lib.rs similarity index 100% rename from queues/bbq/src/lib.rs rename to data_structures/queues/bbq/src/lib.rs diff --git a/queues/bbq/src/main.rs b/data_structures/queues/bbq/src/main.rs similarity index 100% rename from queues/bbq/src/main.rs rename to data_structures/queues/bbq/src/main.rs diff --git a/queues/boost_queue_cpp/Cargo.toml b/data_structures/queues/boost_queue_cpp/Cargo.toml similarity index 100% rename from queues/boost_queue_cpp/Cargo.toml rename to data_structures/queues/boost_queue_cpp/Cargo.toml diff --git a/queues/boost_queue_cpp/build.rs b/data_structures/queues/boost_queue_cpp/build.rs similarity index 100% rename from queues/boost_queue_cpp/build.rs rename to data_structures/queues/boost_queue_cpp/build.rs diff --git a/queues/boost_queue_cpp/cpp_src/boost_wrapper.cpp b/data_structures/queues/boost_queue_cpp/cpp_src/boost_wrapper.cpp similarity index 100% rename from queues/boost_queue_cpp/cpp_src/boost_wrapper.cpp rename to data_structures/queues/boost_queue_cpp/cpp_src/boost_wrapper.cpp diff --git a/queues/boost_queue_cpp/cpp_src/boost_wrapper.hpp b/data_structures/queues/boost_queue_cpp/cpp_src/boost_wrapper.hpp similarity index 100% rename from queues/boost_queue_cpp/cpp_src/boost_wrapper.hpp rename to data_structures/queues/boost_queue_cpp/cpp_src/boost_wrapper.hpp diff --git a/queues/boost_queue_cpp/src/lib.rs b/data_structures/queues/boost_queue_cpp/src/lib.rs similarity index 100% rename from queues/boost_queue_cpp/src/lib.rs rename to data_structures/queues/boost_queue_cpp/src/lib.rs diff --git a/queues/boost_queue_cpp/src/main.rs b/data_structures/queues/boost_queue_cpp/src/main.rs similarity index 100% rename from queues/boost_queue_cpp/src/main.rs rename to data_structures/queues/boost_queue_cpp/src/main.rs diff --git a/queues/bounded_concurrent_queue/Cargo.toml b/data_structures/queues/bounded_concurrent_queue/Cargo.toml similarity index 100% rename from queues/bounded_concurrent_queue/Cargo.toml rename to data_structures/queues/bounded_concurrent_queue/Cargo.toml diff --git a/queues/bounded_concurrent_queue/src/lib.rs b/data_structures/queues/bounded_concurrent_queue/src/lib.rs similarity index 100% rename from queues/bounded_concurrent_queue/src/lib.rs rename to data_structures/queues/bounded_concurrent_queue/src/lib.rs diff --git a/queues/bounded_concurrent_queue/src/main.rs b/data_structures/queues/bounded_concurrent_queue/src/main.rs similarity index 100% rename from queues/bounded_concurrent_queue/src/main.rs rename to data_structures/queues/bounded_concurrent_queue/src/main.rs diff --git a/queues/bounded_ringbuffer/Cargo.toml b/data_structures/queues/bounded_ringbuffer/Cargo.toml similarity index 100% rename from queues/bounded_ringbuffer/Cargo.toml rename to data_structures/queues/bounded_ringbuffer/Cargo.toml diff --git a/queues/bounded_ringbuffer/src/lib.rs b/data_structures/queues/bounded_ringbuffer/src/lib.rs similarity index 100% rename from queues/bounded_ringbuffer/src/lib.rs rename to data_structures/queues/bounded_ringbuffer/src/lib.rs diff --git a/queues/bounded_ringbuffer/src/main.rs b/data_structures/queues/bounded_ringbuffer/src/main.rs similarity index 100% rename from queues/bounded_ringbuffer/src/main.rs rename to data_structures/queues/bounded_ringbuffer/src/main.rs diff --git a/queues/faaa_queue/Cargo.toml b/data_structures/queues/faaa_queue/Cargo.toml similarity index 100% rename from queues/faaa_queue/Cargo.toml rename to data_structures/queues/faaa_queue/Cargo.toml diff --git a/queues/faaa_queue/src/lib.rs b/data_structures/queues/faaa_queue/src/lib.rs similarity index 100% rename from queues/faaa_queue/src/lib.rs rename to data_structures/queues/faaa_queue/src/lib.rs diff --git a/queues/faaa_queue/src/main.rs b/data_structures/queues/faaa_queue/src/main.rs similarity index 100% rename from queues/faaa_queue/src/main.rs rename to data_structures/queues/faaa_queue/src/main.rs diff --git a/queues/faaa_queue_cpp/Cargo.toml b/data_structures/queues/faaa_queue_cpp/Cargo.toml similarity index 100% rename from queues/faaa_queue_cpp/Cargo.toml rename to data_structures/queues/faaa_queue_cpp/Cargo.toml diff --git a/queues/faaa_queue_cpp/build.rs b/data_structures/queues/faaa_queue_cpp/build.rs similarity index 100% rename from queues/faaa_queue_cpp/build.rs rename to data_structures/queues/faaa_queue_cpp/build.rs diff --git a/queues/faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp b/data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp similarity index 100% rename from queues/faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp rename to data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp diff --git a/queues/faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp b/data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp similarity index 100% rename from queues/faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp rename to data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp diff --git a/queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp b/data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp similarity index 100% rename from queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp rename to data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp diff --git a/queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp b/data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp similarity index 100% rename from queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp rename to data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp diff --git a/queues/faaa_queue_cpp/src/lib.rs b/data_structures/queues/faaa_queue_cpp/src/lib.rs similarity index 100% rename from queues/faaa_queue_cpp/src/lib.rs rename to data_structures/queues/faaa_queue_cpp/src/lib.rs diff --git a/queues/faaa_queue_cpp/src/main.rs b/data_structures/queues/faaa_queue_cpp/src/main.rs similarity index 100% rename from queues/faaa_queue_cpp/src/main.rs rename to data_structures/queues/faaa_queue_cpp/src/main.rs diff --git a/queues/lcrq/Cargo.toml b/data_structures/queues/lcrq/Cargo.toml similarity index 100% rename from queues/lcrq/Cargo.toml rename to data_structures/queues/lcrq/Cargo.toml diff --git a/queues/lcrq/src/lib.rs b/data_structures/queues/lcrq/src/lib.rs similarity index 100% rename from queues/lcrq/src/lib.rs rename to data_structures/queues/lcrq/src/lib.rs diff --git a/queues/lcrq/src/main.rs b/data_structures/queues/lcrq/src/main.rs similarity index 100% rename from queues/lcrq/src/main.rs rename to data_structures/queues/lcrq/src/main.rs diff --git a/queues/lcrq_cpp/Cargo.toml b/data_structures/queues/lcrq_cpp/Cargo.toml similarity index 100% rename from queues/lcrq_cpp/Cargo.toml rename to data_structures/queues/lcrq_cpp/Cargo.toml diff --git a/queues/lcrq_cpp/build.rs b/data_structures/queues/lcrq_cpp/build.rs similarity index 100% rename from queues/lcrq_cpp/build.rs rename to data_structures/queues/lcrq_cpp/build.rs diff --git a/queues/lcrq_cpp/cpp_src/HazardPointers.hpp b/data_structures/queues/lcrq_cpp/cpp_src/HazardPointers.hpp similarity index 100% rename from queues/lcrq_cpp/cpp_src/HazardPointers.hpp rename to data_structures/queues/lcrq_cpp/cpp_src/HazardPointers.hpp diff --git a/queues/lcrq_cpp/cpp_src/LCRQueue.hpp b/data_structures/queues/lcrq_cpp/cpp_src/LCRQueue.hpp similarity index 100% rename from queues/lcrq_cpp/cpp_src/LCRQueue.hpp rename to data_structures/queues/lcrq_cpp/cpp_src/LCRQueue.hpp diff --git a/queues/lcrq_cpp/cpp_src/lcrq_wrapper.cpp b/data_structures/queues/lcrq_cpp/cpp_src/lcrq_wrapper.cpp similarity index 100% rename from queues/lcrq_cpp/cpp_src/lcrq_wrapper.cpp rename to data_structures/queues/lcrq_cpp/cpp_src/lcrq_wrapper.cpp diff --git a/queues/lcrq_cpp/cpp_src/lcrq_wrapper.hpp b/data_structures/queues/lcrq_cpp/cpp_src/lcrq_wrapper.hpp similarity index 100% rename from queues/lcrq_cpp/cpp_src/lcrq_wrapper.hpp rename to data_structures/queues/lcrq_cpp/cpp_src/lcrq_wrapper.hpp diff --git a/queues/lcrq_cpp/src/lib.rs b/data_structures/queues/lcrq_cpp/src/lib.rs similarity index 100% rename from queues/lcrq_cpp/src/lib.rs rename to data_structures/queues/lcrq_cpp/src/lib.rs diff --git a/queues/lcrq_cpp/src/main.rs b/data_structures/queues/lcrq_cpp/src/main.rs similarity index 100% rename from queues/lcrq_cpp/src/main.rs rename to data_structures/queues/lcrq_cpp/src/main.rs diff --git a/queues/lf_queue/Cargo.toml b/data_structures/queues/lf_queue/Cargo.toml similarity index 100% rename from queues/lf_queue/Cargo.toml rename to data_structures/queues/lf_queue/Cargo.toml diff --git a/queues/lf_queue/src/lib.rs b/data_structures/queues/lf_queue/src/lib.rs similarity index 100% rename from queues/lf_queue/src/lib.rs rename to data_structures/queues/lf_queue/src/lib.rs diff --git a/queues/lf_queue/src/main.rs b/data_structures/queues/lf_queue/src/main.rs similarity index 100% rename from queues/lf_queue/src/main.rs rename to data_structures/queues/lf_queue/src/main.rs diff --git a/queues/lockfree_queue/Cargo.toml b/data_structures/queues/lockfree_queue/Cargo.toml similarity index 100% rename from queues/lockfree_queue/Cargo.toml rename to data_structures/queues/lockfree_queue/Cargo.toml diff --git a/queues/lockfree_queue/src/lib.rs b/data_structures/queues/lockfree_queue/src/lib.rs similarity index 100% rename from queues/lockfree_queue/src/lib.rs rename to data_structures/queues/lockfree_queue/src/lib.rs diff --git a/queues/lockfree_queue/src/main.rs b/data_structures/queues/lockfree_queue/src/main.rs similarity index 100% rename from queues/lockfree_queue/src/main.rs rename to data_structures/queues/lockfree_queue/src/main.rs diff --git a/queues/lprq/Cargo.toml b/data_structures/queues/lprq/Cargo.toml similarity index 100% rename from queues/lprq/Cargo.toml rename to data_structures/queues/lprq/Cargo.toml diff --git a/queues/lprq/src/lib.rs b/data_structures/queues/lprq/src/lib.rs similarity index 100% rename from queues/lprq/src/lib.rs rename to data_structures/queues/lprq/src/lib.rs diff --git a/queues/lprq/src/lprq_rs.rs b/data_structures/queues/lprq/src/lprq_rs.rs similarity index 100% rename from queues/lprq/src/lprq_rs.rs rename to data_structures/queues/lprq/src/lprq_rs.rs diff --git a/queues/lprq/src/main.rs b/data_structures/queues/lprq/src/main.rs similarity index 100% rename from queues/lprq/src/main.rs rename to data_structures/queues/lprq/src/main.rs diff --git a/queues/lprq_cpp/Cargo.toml b/data_structures/queues/lprq_cpp/Cargo.toml similarity index 100% rename from queues/lprq_cpp/Cargo.toml rename to data_structures/queues/lprq_cpp/Cargo.toml diff --git a/queues/lprq_cpp/build.rs b/data_structures/queues/lprq_cpp/build.rs similarity index 100% rename from queues/lprq_cpp/build.rs rename to data_structures/queues/lprq_cpp/build.rs diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/README.md b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/README.md similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/README.md rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/README.md diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Forked.hpp b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Forked.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Forked.hpp rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Forked.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/HazardPointers.hpp b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/HazardPointers.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/HazardPointers.hpp rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/HazardPointers.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LinkedRingQueue.hpp b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LinkedRingQueue.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LinkedRingQueue.hpp rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LinkedRingQueue.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/MetaprogrammingUtils.hpp b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/MetaprogrammingUtils.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/MetaprogrammingUtils.hpp rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/MetaprogrammingUtils.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Metrics.hpp b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Metrics.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Metrics.hpp rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Metrics.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/RQCell.hpp b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/RQCell.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/RQCell.hpp rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/RQCell.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Stats.hpp b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Stats.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Stats.hpp rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Stats.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp b/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp rename to data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp diff --git a/queues/lprq_cpp/cpp_src/lprq_wrapper.cpp b/data_structures/queues/lprq_cpp/cpp_src/lprq_wrapper.cpp similarity index 100% rename from queues/lprq_cpp/cpp_src/lprq_wrapper.cpp rename to data_structures/queues/lprq_cpp/cpp_src/lprq_wrapper.cpp diff --git a/queues/lprq_cpp/cpp_src/lprq_wrapper.hpp b/data_structures/queues/lprq_cpp/cpp_src/lprq_wrapper.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/lprq_wrapper.hpp rename to data_structures/queues/lprq_cpp/cpp_src/lprq_wrapper.hpp diff --git a/queues/lprq_cpp/src/lib.rs b/data_structures/queues/lprq_cpp/src/lib.rs similarity index 100% rename from queues/lprq_cpp/src/lib.rs rename to data_structures/queues/lprq_cpp/src/lib.rs diff --git a/queues/lprq_cpp/src/main.rs b/data_structures/queues/lprq_cpp/src/main.rs similarity index 100% rename from queues/lprq_cpp/src/main.rs rename to data_structures/queues/lprq_cpp/src/main.rs diff --git a/queues/moodycamel_cpp/Cargo.toml b/data_structures/queues/moodycamel_cpp/Cargo.toml similarity index 100% rename from queues/moodycamel_cpp/Cargo.toml rename to data_structures/queues/moodycamel_cpp/Cargo.toml diff --git a/queues/moodycamel_cpp/build.rs b/data_structures/queues/moodycamel_cpp/build.rs similarity index 100% rename from queues/moodycamel_cpp/build.rs rename to data_structures/queues/moodycamel_cpp/build.rs diff --git a/queues/moodycamel_cpp/cpp_src/concurrentqueue b/data_structures/queues/moodycamel_cpp/cpp_src/concurrentqueue similarity index 100% rename from queues/moodycamel_cpp/cpp_src/concurrentqueue rename to data_structures/queues/moodycamel_cpp/cpp_src/concurrentqueue diff --git a/queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp b/data_structures/queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp similarity index 100% rename from queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp rename to data_structures/queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp diff --git a/queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp b/data_structures/queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp similarity index 100% rename from queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp rename to data_structures/queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp diff --git a/queues/moodycamel_cpp/src/lib.rs b/data_structures/queues/moodycamel_cpp/src/lib.rs similarity index 100% rename from queues/moodycamel_cpp/src/lib.rs rename to data_structures/queues/moodycamel_cpp/src/lib.rs diff --git a/queues/moodycamel_cpp/src/main.rs b/data_structures/queues/moodycamel_cpp/src/main.rs similarity index 100% rename from queues/moodycamel_cpp/src/main.rs rename to data_structures/queues/moodycamel_cpp/src/main.rs diff --git a/queues/ms_queue/Cargo.toml b/data_structures/queues/ms_queue/Cargo.toml similarity index 100% rename from queues/ms_queue/Cargo.toml rename to data_structures/queues/ms_queue/Cargo.toml diff --git a/queues/ms_queue/src/lib.rs b/data_structures/queues/ms_queue/src/lib.rs similarity index 100% rename from queues/ms_queue/src/lib.rs rename to data_structures/queues/ms_queue/src/lib.rs diff --git a/queues/ms_queue/src/main.rs b/data_structures/queues/ms_queue/src/main.rs similarity index 100% rename from queues/ms_queue/src/main.rs rename to data_structures/queues/ms_queue/src/main.rs diff --git a/queues/scc2_queue/Cargo.toml b/data_structures/queues/scc2_queue/Cargo.toml similarity index 100% rename from queues/scc2_queue/Cargo.toml rename to data_structures/queues/scc2_queue/Cargo.toml diff --git a/queues/scc2_queue/src/lib.rs b/data_structures/queues/scc2_queue/src/lib.rs similarity index 100% rename from queues/scc2_queue/src/lib.rs rename to data_structures/queues/scc2_queue/src/lib.rs diff --git a/queues/scc2_queue/src/main.rs b/data_structures/queues/scc2_queue/src/main.rs similarity index 100% rename from queues/scc2_queue/src/main.rs rename to data_structures/queues/scc2_queue/src/main.rs diff --git a/queues/scc_queue/Cargo.toml b/data_structures/queues/scc_queue/Cargo.toml similarity index 100% rename from queues/scc_queue/Cargo.toml rename to data_structures/queues/scc_queue/Cargo.toml diff --git a/queues/scc_queue/src/lib.rs b/data_structures/queues/scc_queue/src/lib.rs similarity index 100% rename from queues/scc_queue/src/lib.rs rename to data_structures/queues/scc_queue/src/lib.rs diff --git a/queues/scc_queue/src/main.rs b/data_structures/queues/scc_queue/src/main.rs similarity index 100% rename from queues/scc_queue/src/main.rs rename to data_structures/queues/scc_queue/src/main.rs diff --git a/queues/seg_queue/Cargo.toml b/data_structures/queues/seg_queue/Cargo.toml similarity index 100% rename from queues/seg_queue/Cargo.toml rename to data_structures/queues/seg_queue/Cargo.toml diff --git a/queues/seg_queue/src/lib.rs b/data_structures/queues/seg_queue/src/lib.rs similarity index 100% rename from queues/seg_queue/src/lib.rs rename to data_structures/queues/seg_queue/src/lib.rs diff --git a/queues/seg_queue/src/main.rs b/data_structures/queues/seg_queue/src/main.rs similarity index 100% rename from queues/seg_queue/src/main.rs rename to data_structures/queues/seg_queue/src/main.rs diff --git a/queues/tz_queue_hp/Cargo.toml b/data_structures/queues/tz_queue_hp/Cargo.toml similarity index 100% rename from queues/tz_queue_hp/Cargo.toml rename to data_structures/queues/tz_queue_hp/Cargo.toml diff --git a/queues/tz_queue_hp/src/lib.rs b/data_structures/queues/tz_queue_hp/src/lib.rs similarity index 100% rename from queues/tz_queue_hp/src/lib.rs rename to data_structures/queues/tz_queue_hp/src/lib.rs diff --git a/queues/tz_queue_hp/src/main.rs b/data_structures/queues/tz_queue_hp/src/main.rs similarity index 100% rename from queues/tz_queue_hp/src/main.rs rename to data_structures/queues/tz_queue_hp/src/main.rs diff --git a/queues/tz_queue_leak/Cargo.toml b/data_structures/queues/tz_queue_leak/Cargo.toml similarity index 100% rename from queues/tz_queue_leak/Cargo.toml rename to data_structures/queues/tz_queue_leak/Cargo.toml diff --git a/queues/tz_queue_leak/src/lib.rs b/data_structures/queues/tz_queue_leak/src/lib.rs similarity index 100% rename from queues/tz_queue_leak/src/lib.rs rename to data_structures/queues/tz_queue_leak/src/lib.rs diff --git a/queues/tz_queue_leak/src/main.rs b/data_structures/queues/tz_queue_leak/src/main.rs similarity index 100% rename from queues/tz_queue_leak/src/main.rs rename to data_structures/queues/tz_queue_leak/src/main.rs diff --git a/queues/unbounded_concurrent_queue/Cargo.toml b/data_structures/queues/unbounded_concurrent_queue/Cargo.toml similarity index 100% rename from queues/unbounded_concurrent_queue/Cargo.toml rename to data_structures/queues/unbounded_concurrent_queue/Cargo.toml diff --git a/queues/unbounded_concurrent_queue/src/lib.rs b/data_structures/queues/unbounded_concurrent_queue/src/lib.rs similarity index 100% rename from queues/unbounded_concurrent_queue/src/lib.rs rename to data_structures/queues/unbounded_concurrent_queue/src/lib.rs diff --git a/queues/unbounded_concurrent_queue/src/main.rs b/data_structures/queues/unbounded_concurrent_queue/src/main.rs similarity index 100% rename from queues/unbounded_concurrent_queue/src/main.rs rename to data_structures/queues/unbounded_concurrent_queue/src/main.rs diff --git a/queues/wf_queue/Cargo.toml b/data_structures/queues/wf_queue/Cargo.toml similarity index 100% rename from queues/wf_queue/Cargo.toml rename to data_structures/queues/wf_queue/Cargo.toml diff --git a/queues/wf_queue/src/lib.rs b/data_structures/queues/wf_queue/src/lib.rs similarity index 100% rename from queues/wf_queue/src/lib.rs rename to data_structures/queues/wf_queue/src/lib.rs diff --git a/queues/wf_queue/src/main.rs b/data_structures/queues/wf_queue/src/main.rs similarity index 100% rename from queues/wf_queue/src/main.rs rename to data_structures/queues/wf_queue/src/main.rs From 81dfc6235ac9810afdd51e31ec8347af058abdcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Mon, 2 Feb 2026 18:45:38 +0100 Subject: [PATCH 02/16] Move stacks into data_structures folder --- {stacks => data_structures/stacks}/lockfree_stack/Cargo.toml | 0 {stacks => data_structures/stacks}/lockfree_stack/src/lib.rs | 0 {stacks => data_structures/stacks}/lockfree_stack/src/main.rs | 0 {stacks => data_structures/stacks}/scc2_stack/Cargo.toml | 0 {stacks => data_structures/stacks}/scc2_stack/src/lib.rs | 0 {stacks => data_structures/stacks}/scc2_stack/src/main.rs | 0 {stacks => data_structures/stacks}/scc_stack/Cargo.toml | 0 {stacks => data_structures/stacks}/scc_stack/src/lib.rs | 0 {stacks => data_structures/stacks}/scc_stack/src/main.rs | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename {stacks => data_structures/stacks}/lockfree_stack/Cargo.toml (100%) rename {stacks => data_structures/stacks}/lockfree_stack/src/lib.rs (100%) rename {stacks => data_structures/stacks}/lockfree_stack/src/main.rs (100%) rename {stacks => data_structures/stacks}/scc2_stack/Cargo.toml (100%) rename {stacks => data_structures/stacks}/scc2_stack/src/lib.rs (100%) rename {stacks => data_structures/stacks}/scc2_stack/src/main.rs (100%) rename {stacks => data_structures/stacks}/scc_stack/Cargo.toml (100%) rename {stacks => data_structures/stacks}/scc_stack/src/lib.rs (100%) rename {stacks => data_structures/stacks}/scc_stack/src/main.rs (100%) diff --git a/stacks/lockfree_stack/Cargo.toml b/data_structures/stacks/lockfree_stack/Cargo.toml similarity index 100% rename from stacks/lockfree_stack/Cargo.toml rename to data_structures/stacks/lockfree_stack/Cargo.toml diff --git a/stacks/lockfree_stack/src/lib.rs b/data_structures/stacks/lockfree_stack/src/lib.rs similarity index 100% rename from stacks/lockfree_stack/src/lib.rs rename to data_structures/stacks/lockfree_stack/src/lib.rs diff --git a/stacks/lockfree_stack/src/main.rs b/data_structures/stacks/lockfree_stack/src/main.rs similarity index 100% rename from stacks/lockfree_stack/src/main.rs rename to data_structures/stacks/lockfree_stack/src/main.rs diff --git a/stacks/scc2_stack/Cargo.toml b/data_structures/stacks/scc2_stack/Cargo.toml similarity index 100% rename from stacks/scc2_stack/Cargo.toml rename to data_structures/stacks/scc2_stack/Cargo.toml diff --git a/stacks/scc2_stack/src/lib.rs b/data_structures/stacks/scc2_stack/src/lib.rs similarity index 100% rename from stacks/scc2_stack/src/lib.rs rename to data_structures/stacks/scc2_stack/src/lib.rs diff --git a/stacks/scc2_stack/src/main.rs b/data_structures/stacks/scc2_stack/src/main.rs similarity index 100% rename from stacks/scc2_stack/src/main.rs rename to data_structures/stacks/scc2_stack/src/main.rs diff --git a/stacks/scc_stack/Cargo.toml b/data_structures/stacks/scc_stack/Cargo.toml similarity index 100% rename from stacks/scc_stack/Cargo.toml rename to data_structures/stacks/scc_stack/Cargo.toml diff --git a/stacks/scc_stack/src/lib.rs b/data_structures/stacks/scc_stack/src/lib.rs similarity index 100% rename from stacks/scc_stack/src/lib.rs rename to data_structures/stacks/scc_stack/src/lib.rs diff --git a/stacks/scc_stack/src/main.rs b/data_structures/stacks/scc_stack/src/main.rs similarity index 100% rename from stacks/scc_stack/src/main.rs rename to data_structures/stacks/scc_stack/src/main.rs From f6c2a74669f731f9f6b8ad6036667c7618d2f773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Tue, 3 Feb 2026 11:34:11 +0100 Subject: [PATCH 03/16] Restructure queue benchmarks in benchmark_core directory --- benchmark_core/src/benchmarks.rs | 401 +----------------- .../src/benchmarks/benchmark_helpers.rs | 154 +++++++ .../benchmarks/priority_queue_benchmarks.rs | 0 .../src/benchmarks/queue_benchmarks.rs | 148 +++++++ .../benchmarks/{ => queue_benchmarks}/bfs.rs | 0 .../{ => queue_benchmarks}/enq_deq.rs | 46 ++ .../{ => queue_benchmarks}/enq_deq_pairs.rs | 28 ++ .../{ => queue_benchmarks}/prod_con.rs | 51 +++ benchmark_core/src/benchmarks/test_helpers.rs | 42 ++ benchmark_core/src/lib.rs | 78 ---- 10 files changed, 473 insertions(+), 475 deletions(-) create mode 100644 benchmark_core/src/benchmarks/benchmark_helpers.rs create mode 100644 benchmark_core/src/benchmarks/priority_queue_benchmarks.rs create mode 100644 benchmark_core/src/benchmarks/queue_benchmarks.rs rename benchmark_core/src/benchmarks/{ => queue_benchmarks}/bfs.rs (100%) rename benchmark_core/src/benchmarks/{ => queue_benchmarks}/enq_deq.rs (83%) rename benchmark_core/src/benchmarks/{ => queue_benchmarks}/enq_deq_pairs.rs (87%) rename benchmark_core/src/benchmarks/{ => queue_benchmarks}/prod_con.rs (85%) create mode 100644 benchmark_core/src/benchmarks/test_helpers.rs diff --git a/benchmark_core/src/benchmarks.rs b/benchmark_core/src/benchmarks.rs index 2a1369c..7bc919e 100644 --- a/benchmark_core/src/benchmarks.rs +++ b/benchmark_core/src/benchmarks.rs @@ -1,397 +1,4 @@ -#[cfg(feature = "memory_tracking")] -use jemalloc_ctl::{epoch, stats}; -use log::{debug, error, trace}; -#[allow(unused_imports)] -use crate::arguments::{Args, Benchmarks}; -#[allow(unused_imports)] -use crate::traits::ConcurrentQueue; -use std::fs::OpenOptions; -use std::io::Write; -#[allow(unused_imports)] -use std::sync::atomic::AtomicBool; -use sysinfo::System; - -pub mod prod_con; -pub mod enq_deq; -pub mod enq_deq_pairs; -pub mod bfs; - -/// Benchmark config struct -/// Needs to be fully filled for benchmarks to be able to run. -pub struct BenchConfig { - pub args: Args, - pub date_time: String, - pub benchmark_id: String, - pub output_filename: String, -} - -/// Create the queue, and run the selected benchmark a set of times -pub fn benchmark_queue(bench_conf: &BenchConfig, queue_name: &str) -> Result<(), std::io::Error> -where - Q: ConcurrentQueue + Send, - for<'a> &'a Q: Send -{ - // Create a runner lambda for the different benchmarks, mainly needed for eg. BFS to load graph and so on - let mut runner: Box Result<(), std::io::Error>> = match &bench_conf.args.benchmark { - Benchmarks::ProdCon(_) => Box::new(move |q, bench_conf| prod_con::benchmark_prod_con(q, bench_conf)), - Benchmarks::EnqDeq(_) => Box::new(move |q, bench_conf| enq_deq::benchmark_enq_deq(q, bench_conf)), - Benchmarks::EnqDeqPairs(_) => Box::new(move |q, bench_conf| enq_deq_pairs::benchmark_enq_deq_pairs(q, bench_conf)), - Benchmarks::BFS(args) => { - let (graph, seq_ret_vec, start_node) = - bfs::pre_bfs_work( - Q::new(bench_conf.args.queue_size as usize), - args, - ); - Box::new(move |q, _conf| bfs::benchmark_bfs( - q, - &graph, - bench_conf, - &seq_ret_vec, - start_node - ) - ) - }, - }; - - for _current_iteration in 0..bench_conf.args.iterations { - // Create the queue. - let test_q: Q = Q::new(bench_conf.args.queue_size as usize); - - // Start memory tracking (if enabled) - #[cfg(feature = "memory_tracking")] - let (done, mem_thread_handle) = { - let done = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); - let handle = create_mem_tracking_thread( - bench_conf, - _current_iteration, - &test_q, - &done - )?; - (done, handle) - }; - - // Execute the benchmark - runner(test_q, bench_conf)?; - - // Join the thread again - debug!("Queue should have been dropped now."); - - // Stop memory tracking (if enabled) - #[cfg(feature = "memory_tracking")] - { - use std::sync::atomic::Ordering; - debug!("Joining memory thread."); - done.store(true, Ordering::Relaxed); - if let Err(e) = mem_thread_handle.join().unwrap() { - log::error!("Couldn't join memory tracking thread: {}", e); - } - } - } - - if bench_conf.args.print_info { - print_info(queue_name.to_string(), bench_conf)?; - } - - Ok(()) -} - - -#[cfg(feature = "memory_tracking")] -pub fn create_mem_tracking_thread( - bench_conf: &BenchConfig, - _current_iteration: u32, - test_q: &Q, - _done: &std::sync::Arc) --> Result>, std::io::Error> -where - Q: ConcurrentQueue -{ - - use std::sync::atomic::Ordering; - // TODO: Check if core stuff is possible here as well. - // let mut core : CoreId = core_iter.next().unwrap(); - // if is_one_socket is true, make all thread ids even - // (this was used for our testing enviroment to get one socket) - // if *is_one_socket { - // core = core_iter.next().unwrap(); - // } - let _done = std::sync::Arc::clone(_done); - let benchmark_id = bench_conf.benchmark_id.clone(); - let bench_type = format!("{}", bench_conf.args.benchmark); - let to_stdout = bench_conf.args.write_to_stdout; - let queue_type = test_q.get_id(); - - // Create file if printing to stdout is disabled - let top_line = "Memory Allocated,Queuetype,Benchmark,Test ID,Iteration"; - let mut memfile = if !to_stdout { - let output_filename = format!("{}/mem{}", bench_conf.args.path_output, bench_conf.date_time); - let mut file = OpenOptions::new() - .append(true) - .create(true) - .open(&output_filename)?; - if _current_iteration == 0 { - writeln!(file, "{}", top_line)?; - } - Some(file) - } else { - if _current_iteration == 0 { - println!("{}", top_line); - } - None - }; - - // Spawn thread to check total memory allocated every 50ms - let interval = bench_conf.args.memory_tracking_interval; - debug!("Spawning memory thread."); - Ok(std::thread::spawn(move|| -> Result<(), std::io::Error>{ - while !_done.load(Ordering::Relaxed) { - // Update stats - if let Err(e) = epoch::advance() { - eprintln!("Error occured while advancing epoch: {}", e); - } - // Get allocated bytes - let allocated = stats::allocated::read().unwrap(); - - let output = format!("{},{},{},{},{}", allocated, queue_type, bench_type, &benchmark_id, _current_iteration); - - match &mut memfile { - Some(file) => writeln!(file, "{}", output)?, - None => println!("{}", output), - } - - std::thread::sleep(std::time::Duration::from_millis(interval)); - } - Ok(()) - })) - -} - -/// Calculates the fairness based on paper: -/// [A Study of the Behavior of Synchronization Methods in Commonly Used Languages and Systems](https://ieeexplore.ieee.org/document/6569906). -pub fn calc_fairness(ops_per_thread: Vec) -> f64 { - debug!("Calculating fairness"); - let sum: usize = ops_per_thread.iter().sum(); - - let length: f64 = ops_per_thread.len() as f64; - debug!("The vector {:?}", ops_per_thread); - debug!("Sum: {}, Length: {}",sum, length); - - // The thread that does the least amount of ops - let minop: f64 = match ops_per_thread.iter().min() { - Some(&val) => val as f64, - None => { - error!("No record of operations: {:?}", ops_per_thread); - panic!(); - } - }; - trace!("Minop fairness: {}", minop); - - // The thread that does the most amount of ops - let maxop: f64 = match ops_per_thread.iter().max() { - Some(&val) => val as f64, - None => { - error!("No record of operations: {:?}", ops_per_thread); - panic!(); - } - }; - trace!("Maxop fairness: {}", maxop); - - let fairness: f64 = f64::min((length * minop) / sum as f64, sum as f64 / (length * maxop)); - - debug!("Calculated fairness: {}", fairness); - fairness -} - - - -/// Function to print the specifications of the hardware used and the benchmnark configs that ran -pub fn print_info(queue: String, bench_conf: &BenchConfig) -> Result<(), std::io::Error>{ - // Create file if printing to stdout is disabled - if bench_conf.args.write_to_stdout { - return Ok(()); - } - let memfile = { - let output_filename = format!("{}/info{}.txt", bench_conf.args.path_output, bench_conf.benchmark_id); - let file = OpenOptions::new() - .append(true) - .create(true) - .open(&output_filename)?; - Some(file) - }; - let num: u64 = 1000; - let sys = System::new_all(); - if let Some(mut file) = memfile { - writeln!(file, "Benchmark done: {}", bench_conf.args.benchmark)?; - writeln!(file, "With queue: {}", queue)?; - - writeln!(file, "Arguments used in test:")?; - writeln!(file, "\n{}\n", bench_conf.args)?; - - writeln!(file, "Test ran on hardware specs:")?; - writeln!(file, "System name: {}", System::name().unwrap())?; - writeln!(file, "System kernel version: {}", System::kernel_version().unwrap())?; - writeln!(file, "System OS version: {}", System::os_version().unwrap())?; - writeln!(file, "Total RAM (in GB): {:?}", sys.total_memory()/(num.pow(3)))?; - - } - else { - eprintln!("Error producing info file") - } - Ok(()) -} - - -#[cfg(test)] -mod tests { - use crate::arguments::{EnqDeqArgs, EnqDeqPairsArgs}; - use crate::benchmarks::enq_deq_pairs::benchmark_enq_deq_pairs; - use crate::benchmarks::{ - prod_con::benchmark_prod_con, - enq_deq::benchmark_enq_deq - }; - - use super::*; - - /// A very simple ConcurrentQueue implementation for testing - mod test_queue { - use crate::traits::{ConcurrentQueue, Handle}; - use std::{collections::VecDeque, sync::Mutex}; - - pub struct TestQueue { - queue: Mutex>, - } - - pub struct TestQueueHandle<'a, T> { - queue: &'a TestQueue, - } - - impl Handle for TestQueueHandle<'_, T> { - fn push(&mut self, item: T) -> Result<(), T>{ - self.queue.queue.lock().unwrap().push_back(item); - Ok(()) - } - - fn pop(&mut self) -> Option { - self.queue.queue.lock().unwrap().pop_front() - } - } - - impl ConcurrentQueue for TestQueue { - fn register(&self) -> impl Handle { - TestQueueHandle { - queue: self, - } - } - - fn get_id(&self) -> String { - "test_queue".to_string() - } - - fn new(_size: usize) -> Self { - TestQueue { - queue: Mutex::new(VecDeque::new()) - } - } - } - } - use test_queue::TestQueue; - - #[test] - fn run_basic() { - let args = Args::default(); - let bench_conf = BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test1".to_string(), - output_filename: "".to_string() - }; - let queue: TestQueue = TestQueue::new(0); - if benchmark_prod_con(queue, &bench_conf).is_err() { - panic!(); - } - } - - #[test] - fn run_pingpong() { - let args = Args { - benchmark: Benchmarks::EnqDeq(EnqDeqArgs { thread_count: 10, spread: 0.5 }), - ..Default::default() - }; - let bench_conf = BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test2".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_enq_deq(queue, &bench_conf).is_err() { - panic!(); - } - } - - #[test] - fn run_basic_with_string() { - let args = Args::default(); - let bench_conf = BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test1".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_prod_con(queue, &bench_conf).is_err() { - panic!(); - } - } - - #[test] - fn run_pingpong_with_bool() { - let args = Args { - benchmark: Benchmarks::EnqDeq(EnqDeqArgs { thread_count: 10, spread: 0.5 }), - ..Default::default() - }; - let bench_conf = BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test2".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_enq_deq(queue, &bench_conf).is_err() { - panic!(); - } - } - - #[test] - fn run_basic_with_struct() { - let args = Args::default(); - let bench_conf = BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test1".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_prod_con(queue, &bench_conf).is_err() { - panic!(); - } - } - - #[test] - fn run_enqdeq_pairs_with_struct() { - let args = Args { - benchmark: Benchmarks::EnqDeqPairs(EnqDeqPairsArgs { thread_count: 10 }), - ..Default::default() - }; - let bench_conf = BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test2".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_enq_deq_pairs(queue, &bench_conf).is_err() { - panic!(); - } - } -} +pub mod queue_benchmarks; +pub mod priority_queue_benchmarks; +pub mod benchmark_helpers; +pub(crate) mod test_helpers; diff --git a/benchmark_core/src/benchmarks/benchmark_helpers.rs b/benchmark_core/src/benchmarks/benchmark_helpers.rs new file mode 100644 index 0000000..a13ad03 --- /dev/null +++ b/benchmark_core/src/benchmarks/benchmark_helpers.rs @@ -0,0 +1,154 @@ +#[cfg(feature = "memory_tracking")] +use jemalloc_ctl::{epoch, stats}; +use log::{debug, error, trace}; +use sysinfo::System; + +/// Benchmark config struct +/// Needs to be fully filled for benchmarks to be able to run. +pub struct BenchConfig { + pub args: Args, + pub date_time: String, + pub benchmark_id: String, + pub output_filename: String, +} + +#[cfg(feature = "memory_tracking")] +pub fn create_mem_tracking_thread( + bench_conf: &BenchConfig, + _current_iteration: u32, + test_q: &Q, + _done: &std::sync::Arc) +-> Result>, std::io::Error> +where + Q: ConcurrentQueue +{ + + use std::sync::atomic::Ordering; + // TODO: Check if core stuff is possible here as well. + // let mut core : CoreId = core_iter.next().unwrap(); + // if is_one_socket is true, make all thread ids even + // (this was used for our testing enviroment to get one socket) + // if *is_one_socket { + // core = core_iter.next().unwrap(); + // } + let _done = std::sync::Arc::clone(_done); + let benchmark_id = bench_conf.benchmark_id.clone(); + let bench_type = format!("{}", bench_conf.args.benchmark); + let to_stdout = bench_conf.args.write_to_stdout; + let queue_type = test_q.get_id(); + + // Create file if printing to stdout is disabled + let top_line = "Memory Allocated,Queuetype,Benchmark,Test ID,Iteration"; + let mut memfile = if !to_stdout { + let output_filename = format!("{}/mem{}", bench_conf.args.path_output, bench_conf.date_time); + let mut file = OpenOptions::new() + .append(true) + .create(true) + .open(&output_filename)?; + if _current_iteration == 0 { + writeln!(file, "{}", top_line)?; + } + Some(file) + } else { + if _current_iteration == 0 { + println!("{}", top_line); + } + None + }; + + // Spawn thread to check total memory allocated every 50ms + let interval = bench_conf.args.memory_tracking_interval; + debug!("Spawning memory thread."); + Ok(std::thread::spawn(move|| -> Result<(), std::io::Error>{ + while !_done.load(Ordering::Relaxed) { + // Update stats + if let Err(e) = epoch::advance() { + eprintln!("Error occured while advancing epoch: {}", e); + } + // Get allocated bytes + let allocated = stats::allocated::read().unwrap(); + + let output = format!("{},{},{},{},{}", allocated, queue_type, bench_type, &benchmark_id, _current_iteration); + + match &mut memfile { + Some(file) => writeln!(file, "{}", output)?, + None => println!("{}", output), + } + + std::thread::sleep(std::time::Duration::from_millis(interval)); + } + Ok(()) + })) +} + +/// Calculates the fairness based on paper: +/// [A Study of the Behavior of Synchronization Methods in Commonly Used Languages and Systems](https://ieeexplore.ieee.org/document/6569906). +pub fn calc_fairness(ops_per_thread: Vec) -> f64 { + debug!("Calculating fairness"); + let sum: usize = ops_per_thread.iter().sum(); + + let length: f64 = ops_per_thread.len() as f64; + debug!("The vector {:?}", ops_per_thread); + debug!("Sum: {}, Length: {}",sum, length); + + // The thread that does the least amount of ops + let minop: f64 = match ops_per_thread.iter().min() { + Some(&val) => val as f64, + None => { + error!("No record of operations: {:?}", ops_per_thread); + panic!(); + } + }; + trace!("Minop fairness: {}", minop); + + // The thread that does the most amount of ops + let maxop: f64 = match ops_per_thread.iter().max() { + Some(&val) => val as f64, + None => { + error!("No record of operations: {:?}", ops_per_thread); + panic!(); + } + }; + trace!("Maxop fairness: {}", maxop); + + let fairness: f64 = f64::min((length * minop) / sum as f64, sum as f64 / (length * maxop)); + + debug!("Calculated fairness: {}", fairness); + fairness +} + +/// Function to print the specifications of the hardware used and the benchmnark configs that ran +pub fn print_info(queue: String, bench_conf: &BenchConfig) -> Result<(), std::io::Error>{ + // Create file if printing to stdout is disabled + if bench_conf.args.write_to_stdout { + return Ok(()); + } + let memfile = { + let output_filename = format!("{}/info{}.txt", bench_conf.args.path_output, bench_conf.benchmark_id); + let file = OpenOptions::new() + .append(true) + .create(true) + .open(&output_filename)?; + Some(file) + }; + let num: u64 = 1000; + let sys = System::new_all(); + if let Some(mut file) = memfile { + writeln!(file, "Benchmark done: {}", bench_conf.args.benchmark)?; + writeln!(file, "With queue: {}", queue)?; + + writeln!(file, "Arguments used in test:")?; + writeln!(file, "\n{}\n", bench_conf.args)?; + + writeln!(file, "Test ran on hardware specs:")?; + writeln!(file, "System name: {}", System::name().unwrap())?; + writeln!(file, "System kernel version: {}", System::kernel_version().unwrap())?; + writeln!(file, "System OS version: {}", System::os_version().unwrap())?; + writeln!(file, "Total RAM (in GB): {:?}", sys.total_memory()/(num.pow(3)))?; + + } + else { + eprintln!("Error producing info file") + } + Ok(()) +} diff --git a/benchmark_core/src/benchmarks/priority_queue_benchmarks.rs b/benchmark_core/src/benchmarks/priority_queue_benchmarks.rs new file mode 100644 index 0000000..e69de29 diff --git a/benchmark_core/src/benchmarks/queue_benchmarks.rs b/benchmark_core/src/benchmarks/queue_benchmarks.rs new file mode 100644 index 0000000..a50f4f7 --- /dev/null +++ b/benchmark_core/src/benchmarks/queue_benchmarks.rs @@ -0,0 +1,148 @@ +use chrono::Local; +use clap::Parser; +#[allow(unused_imports)] +use crate::arguments::{Args, Benchmarks}; +#[allow(unused_imports)] +use crate::traits::{ConcurrentQueue, Handle}; +#[allow(unused_imports)] +use log::{self, debug, error, info}; +use std::collections::hash_map::DefaultHasher; +use std::fs::OpenOptions; +use std::hash::{Hash, Hasher}; +use std::io::Write; +#[allow(unused_imports)] +use std::sync::atomic::AtomicBool; + +pub mod prod_con; +pub mod enq_deq; +pub mod enq_deq_pairs; +pub mod bfs; + +/// Create the queue, and run the selected benchmark a set of times +pub fn benchmark_queue(queue_name: &str) -> Result<(), std::io::Error> +where + Q: ConcurrentQueue + Send, + for<'a> &'a Q: Send +{ + // Setup output and parse arguments + let SetupResult { bench_conf, .. } = setup_benchmark()?; + + // Create a runner lambda for the different benchmarks, mainly needed for eg. BFS to load graph and so on + let mut runner: Box Result<(), std::io::Error>> = match &bench_conf.args.benchmark { + Benchmarks::ProdCon(_) => Box::new(move |q, bench_conf| prod_con::benchmark_prod_con(q, bench_conf)), + Benchmarks::EnqDeq(_) => Box::new(move |q, bench_conf| enq_deq::benchmark_enq_deq(q, bench_conf)), + Benchmarks::EnqDeqPairs(_) => Box::new(move |q, bench_conf| enq_deq_pairs::benchmark_enq_deq_pairs(q, bench_conf)), + Benchmarks::BFS(args) => { + let (graph, seq_ret_vec, start_node) = + bfs::pre_bfs_work( + Q::new(bench_conf.args.queue_size as usize), + args, + ); + Box::new(move |q, _conf| bfs::benchmark_bfs( + q, + &graph, + bench_conf, + &seq_ret_vec, + start_node + ) + ) + }, + }; + + for _current_iteration in 0..bench_conf.args.iterations { + // Create the queue. + let test_q: Q = Q::new(bench_conf.args.queue_size as usize); + + // Start memory tracking (if enabled) + #[cfg(feature = "memory_tracking")] + let (done, mem_thread_handle) = { + let done = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); + let handle = create_mem_tracking_thread( + bench_conf, + _current_iteration, + &test_q, + &done + )?; + (done, handle) + }; + + // Execute the benchmark + runner(test_q, bench_conf)?; + + // Join the thread again + debug!("Queue should have been dropped now."); + + // Stop memory tracking (if enabled) + #[cfg(feature = "memory_tracking")] + { + use std::sync::atomic::Ordering; + debug!("Joining memory thread."); + done.store(true, Ordering::Relaxed); + if let Err(e) = mem_thread_handle.join().unwrap() { + log::error!("Couldn't join memory tracking thread: {}", e); + } + } + } + + if bench_conf.args.print_info { + print_info(queue_name.to_string(), bench_conf)?; + } + + Ok(()) +} + +pub struct SetupResult { + pub bench_conf: benchmarks::BenchConfig, + pub columns: String, // Optional, but alreadyy written (TODO: have a stream of some sort here) +} + +/// Set up the actual benchmark. +/// +/// All work unrelated to the chosen benchmark is done here. +pub fn setup_benchmark() -> Result { + let args = crate::arguments::Args::parse(); + let date_time = Local::now().format("%Y%m%d%H%M%S").to_string(); + // Create benchmark hashed id + let benchmark_id = { + let mut hasher = DefaultHasher::new(); + date_time.hash(&mut hasher); + format!("{:x}", hasher.finish()) + }; + + debug!("Benchmark ID: {}", benchmark_id); + debug!("Arguments: {:?}", args); + + // Create dir if it doesnt already exist. + if !std::path::Path::new(&args.path_output).exists() { + std::fs::create_dir(&args.path_output)?; + } + + let output_filename = format!("{}/{}", args.path_output, date_time); + let bench_conf = benchmarks::BenchConfig { + args, + date_time, + benchmark_id, + output_filename, + }; + + let columns = match bench_conf.args.benchmark { + arguments::Benchmarks::BFS(_) => { + "Milliseconds,Queuetype,Thread Count,Test ID" + }, + _ => { + "Throughput,Enqueues,Dequeues,Consumers,Producers,Thread Count,Queuetype,Benchmark,Test ID,Fairness,Spread,Queue Size" + } + }; + + if bench_conf.args.write_to_stdout { + println!("{columns}") + } else { + let mut file = OpenOptions::new() + .append(true) + .create(true) + .open(&bench_conf.output_filename)?; + writeln!(file, "{columns}")?; + } + + Ok(SetupResult{bench_conf, columns: columns.to_string()}) +} diff --git a/benchmark_core/src/benchmarks/bfs.rs b/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs similarity index 100% rename from benchmark_core/src/benchmarks/bfs.rs rename to benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs diff --git a/benchmark_core/src/benchmarks/enq_deq.rs b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs similarity index 83% rename from benchmark_core/src/benchmarks/enq_deq.rs rename to benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs index c244889..5bfde59 100644 --- a/benchmark_core/src/benchmarks/enq_deq.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs @@ -168,3 +168,49 @@ T: Default, } Ok(()) } + +#[cfg(test)] +mod tests { + use crate::arguments::EnqDeqArgs; + use crate::benchmarks::enq_deq::benchmark_enq_deq; + + use super::*; + + use crate::benchmarks::test_helpers::test_queue::TestQueue; + + #[test] + fn run_pingpong() { + let args = Args { + benchmark: Benchmarks::EnqDeq(EnqDeqArgs { thread_count: 10, spread: 0.5 }), + ..Default::default() + }; + let bench_conf = BenchConfig { + args, + date_time: "".to_string(), + benchmark_id: "test2".to_string(), + output_filename: "".to_string() + }; + let queue = TestQueue::::new(0); + if benchmark_enq_deq(queue, &bench_conf).is_err() { + panic!(); + } + } + + #[test] + fn run_pingpong_with_bool() { + let args = Args { + benchmark: Benchmarks::EnqDeq(EnqDeqArgs { thread_count: 10, spread: 0.5 }), + ..Default::default() + }; + let bench_conf = BenchConfig { + args, + date_time: "".to_string(), + benchmark_id: "test2".to_string(), + output_filename: "".to_string() + }; + let queue = TestQueue::::new(0); + if benchmark_enq_deq(queue, &bench_conf).is_err() { + panic!(); + } + } +} diff --git a/benchmark_core/src/benchmarks/enq_deq_pairs.rs b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs similarity index 87% rename from benchmark_core/src/benchmarks/enq_deq_pairs.rs rename to benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs index 18938a5..5aca3a9 100644 --- a/benchmark_core/src/benchmarks/enq_deq_pairs.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs @@ -151,3 +151,31 @@ T: Default, } Ok(()) } + +#[cfg(test)] +mod tests { + use crate::arguments::EnqDeqPairsArgs; + use crate::benchmarks::enq_deq_pairs::benchmark_enq_deq_pairs; + + use super::*; + + use crate::benchmarks::test_helpers::test_queue::TestQueue; + + #[test] + fn run_enqdeq_pairs_with_struct() { + let args = Args { + benchmark: Benchmarks::EnqDeqPairs(EnqDeqPairsArgs { thread_count: 10 }), + ..Default::default() + }; + let bench_conf = BenchConfig { + args, + date_time: "".to_string(), + benchmark_id: "test2".to_string(), + output_filename: "".to_string() + }; + let queue = TestQueue::::new(0); + if benchmark_enq_deq_pairs(queue, &bench_conf).is_err() { + panic!(); + } + } +} diff --git a/benchmark_core/src/benchmarks/prod_con.rs b/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs similarity index 85% rename from benchmark_core/src/benchmarks/prod_con.rs rename to benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs index 96ae4b5..d28873d 100644 --- a/benchmark_core/src/benchmarks/prod_con.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs @@ -206,3 +206,54 @@ where } +#[cfg(test)] +mod tests { + use super::*; + + use crate::benchmarks::test_helpers::test_queue::TestQueue; + + #[test] + fn run_basic_prod_con() { + let args = Args::default(); + let bench_conf = BenchConfig { + args, + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + let queue: TestQueue = TestQueue::new(0); + if benchmark_prod_con(queue, &bench_conf).is_err() { + panic!(); + } + } + + #[test] + fn run_basic_with_string() { + let args = Args::default(); + let bench_conf = BenchConfig { + args, + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + let queue = TestQueue::::new(0); + if benchmark_prod_con(queue, &bench_conf).is_err() { + panic!(); + } + } + + #[test] + fn run_basic_with_struct() { + let args = Args::default(); + let bench_conf = BenchConfig { + args, + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + let queue = TestQueue::::new(0); + if benchmark_prod_con(queue, &bench_conf).is_err() { + panic!(); + } + } +} diff --git a/benchmark_core/src/benchmarks/test_helpers.rs b/benchmark_core/src/benchmarks/test_helpers.rs new file mode 100644 index 0000000..5766ee8 --- /dev/null +++ b/benchmark_core/src/benchmarks/test_helpers.rs @@ -0,0 +1,42 @@ +use crate::traits::{ConcurrentQueue, Handle}; +use std::{collections::VecDeque, sync::Mutex}; + +/// A very simple ConcurrentQueue implementation for testing +mod test_queue { + pub struct TestQueue { + queue: Mutex>, + } + + pub struct TestQueueHandle<'a, T> { + queue: &'a TestQueue, + } + + impl Handle for TestQueueHandle<'_, T> { + fn push(&mut self, item: T) -> Result<(), T>{ + self.queue.queue.lock().unwrap().push_back(item); + Ok(()) + } + + fn pop(&mut self) -> Option { + self.queue.queue.lock().unwrap().pop_front() + } + } + + impl ConcurrentQueue for TestQueue { + fn register(&self) -> impl Handle { + TestQueueHandle { + queue: self, + } + } + + fn get_id(&self) -> String { + "test_queue".to_string() + } + + fn new(_size: usize) -> Self { + TestQueue { + queue: Mutex::new(VecDeque::new()) + } + } + } +} diff --git a/benchmark_core/src/lib.rs b/benchmark_core/src/lib.rs index 3c16748..d00b13c 100644 --- a/benchmark_core/src/lib.rs +++ b/benchmark_core/src/lib.rs @@ -5,85 +5,7 @@ use jemallocator::Jemalloc; #[global_allocator] static GLOBAL: Jemalloc = Jemalloc; -use chrono::Local; -#[allow(unused_imports)] -use log::{self, debug, error, info}; -use clap::Parser; -use std::collections::hash_map::DefaultHasher; -use std::fs::OpenOptions; -use std::hash::{Hash, Hasher}; -use std::io::Write; -#[allow(unused_imports)] -use crate::traits::{ConcurrentQueue, Handle}; - pub mod benchmarks; pub mod order; pub mod arguments; pub mod traits; - - -pub struct SetupResult { - pub bench_conf: benchmarks::BenchConfig, - pub columns: String, // Optional, but alreadyy written (TODO: have a stream of some sort here) -} - -pub fn benchmark_target_queue(queue_name: &str) -> Result<(), std::io::Error> -where - Q: ConcurrentQueue + Send, - for<'a> &'a Q: Send -{ - let SetupResult { bench_conf, .. } = setup_benchmark()?; - benchmarks::benchmark_queue::(&bench_conf, queue_name) -} - - -/// Set up the actual benchmark. -/// -/// All work unrelated to the chosen benchmark is done here. -pub fn setup_benchmark() -> Result { - let args = crate::arguments::Args::parse(); - let date_time = Local::now().format("%Y%m%d%H%M%S").to_string(); - // Create benchmark hashed id - let benchmark_id = { - let mut hasher = DefaultHasher::new(); - date_time.hash(&mut hasher); - format!("{:x}", hasher.finish()) - }; - - debug!("Benchmark ID: {}", benchmark_id); - debug!("Arguments: {:?}", args); - - // Create dir if it doesnt already exist. - if !std::path::Path::new(&args.path_output).exists() { - std::fs::create_dir(&args.path_output)?; - } - - let output_filename = format!("{}/{}", args.path_output, date_time); - let bench_conf = benchmarks::BenchConfig { - args, - date_time, - benchmark_id, - output_filename, - }; - - let columns = match bench_conf.args.benchmark { - arguments::Benchmarks::BFS(_) => { - "Milliseconds,Queuetype,Thread Count,Test ID" - }, - _ => { - "Throughput,Enqueues,Dequeues,Consumers,Producers,Thread Count,Queuetype,Benchmark,Test ID,Fairness,Spread,Queue Size" - } - }; - - if bench_conf.args.write_to_stdout { - println!("{columns}") - } else { - let mut file = OpenOptions::new() - .append(true) - .create(true) - .open(&bench_conf.output_filename)?; - writeln!(file, "{columns}")?; - } - - Ok(SetupResult{bench_conf, columns: columns.to_string()}) -} From 7609f4126c69cab8186987b7b83e6de8e342edb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Tue, 3 Feb 2026 13:26:18 +0100 Subject: [PATCH 04/16] Adapt Cargo.toml files for all parts of the framework --- Cargo.toml | 54 +++++++++---------- data_structures/queues/array_queue/Cargo.toml | 2 +- .../queues/atomic_queue/Cargo.toml | 2 +- data_structures/queues/basic_queue/Cargo.toml | 2 +- data_structures/queues/bbq/Cargo.toml | 2 +- .../queues/boost_queue_cpp/Cargo.toml | 2 +- .../bounded_concurrent_queue/Cargo.toml | 2 +- .../queues/bounded_ringbuffer/Cargo.toml | 2 +- data_structures/queues/faaa_queue/Cargo.toml | 2 +- .../queues/faaa_queue_cpp/Cargo.toml | 2 +- data_structures/queues/lcrq/Cargo.toml | 2 +- data_structures/queues/lcrq_cpp/Cargo.toml | 2 +- data_structures/queues/lf_queue/Cargo.toml | 2 +- .../queues/lockfree_queue/Cargo.toml | 2 +- data_structures/queues/lprq/Cargo.toml | 2 +- data_structures/queues/lprq_cpp/Cargo.toml | 2 +- .../queues/moodycamel_cpp/Cargo.toml | 2 +- data_structures/queues/ms_queue/Cargo.toml | 2 +- data_structures/queues/scc2_queue/Cargo.toml | 2 +- data_structures/queues/scc_queue/Cargo.toml | 2 +- data_structures/queues/seg_queue/Cargo.toml | 2 +- data_structures/queues/tz_queue_hp/Cargo.toml | 2 +- .../queues/tz_queue_leak/Cargo.toml | 2 +- .../unbounded_concurrent_queue/Cargo.toml | 2 +- data_structures/queues/wf_queue/Cargo.toml | 2 +- .../stacks/lockfree_stack/Cargo.toml | 2 +- data_structures/stacks/scc2_stack/Cargo.toml | 2 +- data_structures/stacks/scc_stack/Cargo.toml | 2 +- 28 files changed, 54 insertions(+), 54 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 857f03d..701926c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,33 +2,33 @@ resolver = "2" members = [ "benchmark_core", - "queues/array_queue", - "queues/atomic_queue", - "queues/basic_queue", - "queues/bbq", - "queues/boost_queue_cpp", - "queues/bounded_concurrent_queue", - "queues/unbounded_concurrent_queue", - "queues/bounded_ringbuffer", - "queues/faaa_queue", - "queues/faaa_queue_cpp", - "queues/lcrq_cpp", - "queues/lcrq", - "queues/lprq_cpp", - "queues/lprq", - "queues/lf_queue", - "queues/lockfree_queue", - "stacks/lockfree_stack", - "queues/moodycamel_cpp", - "queues/ms_queue", - "queues/scc_queue", - "stacks/scc_stack", - "queues/scc2_queue", - "stacks/scc2_stack", - "queues/seg_queue", - "queues/tz_queue_leak", - "queues/tz_queue_hp", - "queues/wf_queue", + "data_structures/queues/array_queue", + "data_structures/queues/atomic_queue", + "data_structures/queues/basic_queue", + "data_structures/queues/bbq", + "data_structures/queues/boost_queue_cpp", + "data_structures/queues/bounded_concurrent_queue", + "data_structures/queues/unbounded_concurrent_queue", + "data_structures/queues/bounded_ringbuffer", + "data_structures/queues/faaa_queue", + "data_structures/queues/faaa_queue_cpp", + "data_structures/queues/lcrq_cpp", + "data_structures/queues/lcrq", + "data_structures/queues/lprq_cpp", + "data_structures/queues/lprq", + "data_structures/queues/lf_queue", + "data_structures/queues/lockfree_queue", + "data_structures/stacks/lockfree_stack", + "data_structures/queues/moodycamel_cpp", + "data_structures/queues/ms_queue", + "data_structures/queues/scc_queue", + "data_structures/stacks/scc_stack", + "data_structures/queues/scc2_queue", + "data_structures/stacks/scc2_stack", + "data_structures/queues/seg_queue", + "data_structures/queues/tz_queue_leak", + "data_structures/queues/tz_queue_hp", + "data_structures/queues/wf_queue", ] [workspace.dependencies] diff --git a/data_structures/queues/array_queue/Cargo.toml b/data_structures/queues/array_queue/Cargo.toml index e0ced3a..e89cf1b 100644 --- a/data_structures/queues/array_queue/Cargo.toml +++ b/data_structures/queues/array_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } crossbeam = { workspace = true } diff --git a/data_structures/queues/atomic_queue/Cargo.toml b/data_structures/queues/atomic_queue/Cargo.toml index 0f086cd..77275fe 100644 --- a/data_structures/queues/atomic_queue/Cargo.toml +++ b/data_structures/queues/atomic_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } atomic_queue_upstream = { package = "atomic-queue", version = "2.2.0" } diff --git a/data_structures/queues/basic_queue/Cargo.toml b/data_structures/queues/basic_queue/Cargo.toml index 625dbb2..85794d1 100644 --- a/data_structures/queues/basic_queue/Cargo.toml +++ b/data_structures/queues/basic_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/data_structures/queues/bbq/Cargo.toml b/data_structures/queues/bbq/Cargo.toml index 2c6a9f5..f6042e9 100644 --- a/data_structures/queues/bbq/Cargo.toml +++ b/data_structures/queues/bbq/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } bbq_upstream = { package = "bbq-rs", git = "https://github.com/WilleBerg/bbq", branch = "main" } diff --git a/data_structures/queues/boost_queue_cpp/Cargo.toml b/data_structures/queues/boost_queue_cpp/Cargo.toml index b577c25..a7ce2de 100644 --- a/data_structures/queues/boost_queue_cpp/Cargo.toml +++ b/data_structures/queues/boost_queue_cpp/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/data_structures/queues/bounded_concurrent_queue/Cargo.toml b/data_structures/queues/bounded_concurrent_queue/Cargo.toml index 8697eda..a87a01f 100644 --- a/data_structures/queues/bounded_concurrent_queue/Cargo.toml +++ b/data_structures/queues/bounded_concurrent_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } concurrent-queue = { version = "2.5.0" } diff --git a/data_structures/queues/bounded_ringbuffer/Cargo.toml b/data_structures/queues/bounded_ringbuffer/Cargo.toml index a7b179f..1cefc07 100644 --- a/data_structures/queues/bounded_ringbuffer/Cargo.toml +++ b/data_structures/queues/bounded_ringbuffer/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/data_structures/queues/faaa_queue/Cargo.toml b/data_structures/queues/faaa_queue/Cargo.toml index dfab814..dc5fd45 100644 --- a/data_structures/queues/faaa_queue/Cargo.toml +++ b/data_structures/queues/faaa_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } crossbeam = { workspace = true } diff --git a/data_structures/queues/faaa_queue_cpp/Cargo.toml b/data_structures/queues/faaa_queue_cpp/Cargo.toml index e96e631..eeb17af 100644 --- a/data_structures/queues/faaa_queue_cpp/Cargo.toml +++ b/data_structures/queues/faaa_queue_cpp/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/data_structures/queues/lcrq/Cargo.toml b/data_structures/queues/lcrq/Cargo.toml index 052bf4e..7160a82 100644 --- a/data_structures/queues/lcrq/Cargo.toml +++ b/data_structures/queues/lcrq/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } crossbeam = { workspace = true } diff --git a/data_structures/queues/lcrq_cpp/Cargo.toml b/data_structures/queues/lcrq_cpp/Cargo.toml index 46dd354..0c458b2 100644 --- a/data_structures/queues/lcrq_cpp/Cargo.toml +++ b/data_structures/queues/lcrq_cpp/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/data_structures/queues/lf_queue/Cargo.toml b/data_structures/queues/lf_queue/Cargo.toml index 6d39105..e161234 100644 --- a/data_structures/queues/lf_queue/Cargo.toml +++ b/data_structures/queues/lf_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } lf-queue-upstream = { package = "lf-queue", version = "0.1.0" } diff --git a/data_structures/queues/lockfree_queue/Cargo.toml b/data_structures/queues/lockfree_queue/Cargo.toml index 5248041..43f118e 100644 --- a/data_structures/queues/lockfree_queue/Cargo.toml +++ b/data_structures/queues/lockfree_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } lockfree = { version = "0.5.1" } diff --git a/data_structures/queues/lprq/Cargo.toml b/data_structures/queues/lprq/Cargo.toml index b02f81c..47d27fa 100644 --- a/data_structures/queues/lprq/Cargo.toml +++ b/data_structures/queues/lprq/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } haphazard = { workspace = true } diff --git a/data_structures/queues/lprq_cpp/Cargo.toml b/data_structures/queues/lprq_cpp/Cargo.toml index 71a56fd..cd556b7 100644 --- a/data_structures/queues/lprq_cpp/Cargo.toml +++ b/data_structures/queues/lprq_cpp/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/data_structures/queues/moodycamel_cpp/Cargo.toml b/data_structures/queues/moodycamel_cpp/Cargo.toml index edbd362..4a09f8c 100644 --- a/data_structures/queues/moodycamel_cpp/Cargo.toml +++ b/data_structures/queues/moodycamel_cpp/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/data_structures/queues/ms_queue/Cargo.toml b/data_structures/queues/ms_queue/Cargo.toml index d410ab4..553cfd4 100644 --- a/data_structures/queues/ms_queue/Cargo.toml +++ b/data_structures/queues/ms_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } haphazard = { workspace = true } diff --git a/data_structures/queues/scc2_queue/Cargo.toml b/data_structures/queues/scc2_queue/Cargo.toml index ea1f73c..e77db06 100644 --- a/data_structures/queues/scc2_queue/Cargo.toml +++ b/data_structures/queues/scc2_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } scc2 = { version = "2.4.1" } diff --git a/data_structures/queues/scc_queue/Cargo.toml b/data_structures/queues/scc_queue/Cargo.toml index cbfd923..731f792 100644 --- a/data_structures/queues/scc_queue/Cargo.toml +++ b/data_structures/queues/scc_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } scc = { version = "2.3.3" } diff --git a/data_structures/queues/seg_queue/Cargo.toml b/data_structures/queues/seg_queue/Cargo.toml index ea291bf..b3bb992 100644 --- a/data_structures/queues/seg_queue/Cargo.toml +++ b/data_structures/queues/seg_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } crossbeam = { workspace = true } diff --git a/data_structures/queues/tz_queue_hp/Cargo.toml b/data_structures/queues/tz_queue_hp/Cargo.toml index 921b7ab..9cac851 100644 --- a/data_structures/queues/tz_queue_hp/Cargo.toml +++ b/data_structures/queues/tz_queue_hp/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } haphazard = { workspace = true } diff --git a/data_structures/queues/tz_queue_leak/Cargo.toml b/data_structures/queues/tz_queue_leak/Cargo.toml index ca3181b..5abb362 100644 --- a/data_structures/queues/tz_queue_leak/Cargo.toml +++ b/data_structures/queues/tz_queue_leak/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/data_structures/queues/unbounded_concurrent_queue/Cargo.toml b/data_structures/queues/unbounded_concurrent_queue/Cargo.toml index 9905d50..2927d1a 100644 --- a/data_structures/queues/unbounded_concurrent_queue/Cargo.toml +++ b/data_structures/queues/unbounded_concurrent_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } concurrent-queue = { version = "2.5.0" } diff --git a/data_structures/queues/wf_queue/Cargo.toml b/data_structures/queues/wf_queue/Cargo.toml index b06c6bd..f07bc5f 100644 --- a/data_structures/queues/wf_queue/Cargo.toml +++ b/data_structures/queues/wf_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } wfqueue_upstream = { package = "wfqueue", git = "https://github.com/WilleBerg/wfqueue", branch = "master" } diff --git a/data_structures/stacks/lockfree_stack/Cargo.toml b/data_structures/stacks/lockfree_stack/Cargo.toml index 64dbee3..5462c07 100644 --- a/data_structures/stacks/lockfree_stack/Cargo.toml +++ b/data_structures/stacks/lockfree_stack/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } lockfree = { version = "0.5.1" } diff --git a/data_structures/stacks/scc2_stack/Cargo.toml b/data_structures/stacks/scc2_stack/Cargo.toml index d25c19b..f9ab854 100644 --- a/data_structures/stacks/scc2_stack/Cargo.toml +++ b/data_structures/stacks/scc2_stack/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } scc2 = { version = "2.4.1" } diff --git a/data_structures/stacks/scc_stack/Cargo.toml b/data_structures/stacks/scc_stack/Cargo.toml index c19a2d0..5ac252f 100644 --- a/data_structures/stacks/scc_stack/Cargo.toml +++ b/data_structures/stacks/scc_stack/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } scc = { version = "2.3.3" } From ef6614486a28aaf9984947e29f6bca6cff6c7454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Tue, 3 Feb 2026 15:44:07 +0100 Subject: [PATCH 05/16] Fix build errors for queues --- benchmark_core/src/arguments.rs | 16 ++++++------ .../src/benchmarks/benchmark_helpers.rs | 7 +++++ .../src/benchmarks/queue_benchmarks.rs | 26 ++++++++++--------- .../src/benchmarks/queue_benchmarks/bfs.rs | 12 +++++---- .../benchmarks/queue_benchmarks/enq_deq.rs | 23 +++++++++------- .../queue_benchmarks/enq_deq_pairs.rs | 17 +++++++----- .../benchmarks/queue_benchmarks/prod_con.rs | 18 +++++++------ benchmark_core/src/benchmarks/test_helpers.rs | 17 ++++++------ .../queues/array_queue/src/main.rs | 3 ++- .../queues/atomic_queue/src/main.rs | 3 ++- .../queues/basic_queue/src/main.rs | 3 ++- data_structures/queues/bbq/src/main.rs | 3 ++- .../queues/boost_queue_cpp/src/main.rs | 3 ++- .../bounded_concurrent_queue/src/main.rs | 3 ++- .../queues/bounded_ringbuffer/src/main.rs | 3 ++- data_structures/queues/faaa_queue/src/main.rs | 3 ++- .../queues/faaa_queue_cpp/src/main.rs | 3 ++- data_structures/queues/lcrq/src/main.rs | 3 ++- data_structures/queues/lcrq_cpp/src/main.rs | 3 ++- data_structures/queues/lf_queue/src/main.rs | 3 ++- .../queues/lockfree_queue/src/main.rs | 3 ++- data_structures/queues/lprq/src/main.rs | 3 ++- data_structures/queues/lprq_cpp/src/main.rs | 3 ++- .../queues/moodycamel_cpp/src/main.rs | 3 ++- data_structures/queues/ms_queue/src/main.rs | 3 ++- data_structures/queues/scc2_queue/src/main.rs | 3 ++- data_structures/queues/scc_queue/src/main.rs | 3 ++- data_structures/queues/seg_queue/src/main.rs | 3 ++- .../queues/tz_queue_hp/src/main.rs | 3 ++- .../queues/tz_queue_leak/src/main.rs | 3 ++- .../unbounded_concurrent_queue/src/main.rs | 3 ++- data_structures/queues/wf_queue/src/main.rs | 3 ++- .../stacks/lockfree_stack/src/main.rs | 3 ++- data_structures/stacks/scc2_stack/src/main.rs | 3 ++- data_structures/stacks/scc_stack/src/main.rs | 3 ++- 35 files changed, 131 insertions(+), 86 deletions(-) diff --git a/benchmark_core/src/arguments.rs b/benchmark_core/src/arguments.rs index 738b4ec..15f5ac2 100644 --- a/benchmark_core/src/arguments.rs +++ b/benchmark_core/src/arguments.rs @@ -27,7 +27,7 @@ pub struct Args { pub path_output: String, /// Choose which benchmark to run. #[command(subcommand)] - pub benchmark: Benchmarks, + pub benchmark: QueueBenchmarks, /// If set to true, benchmark will output to stdout instead of to files. #[arg(long = "write-stdout", default_value_t = false)] pub write_to_stdout: bool, @@ -45,7 +45,7 @@ pub struct Args { /// Possible benchmark types. #[derive(Subcommand, Debug)] -pub enum Benchmarks { +pub enum QueueBenchmarks { /// ProdCon throughput test. Decide amount of producers and consumers using flags. ProdCon(ProdConArgs), /// A test where each thread performs both consume and produce based on a random floating point @@ -91,14 +91,14 @@ pub struct BFSArgs { } /// This is used to write the benchmark type to the output. /// That is why the arguments are discarded. -impl Display for Benchmarks { +impl Display for QueueBenchmarks { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Benchmarks::ProdCon(_) => write!(f, "ProdCon"), - Benchmarks::EnqDeq(_) => write!(f, "EnqDeq"), - Benchmarks::EnqDeqPairs(_) => write!(f, "EnqDeqPairs"), + QueueBenchmarks::ProdCon(_) => write!(f, "ProdCon"), + QueueBenchmarks::EnqDeq(_) => write!(f, "EnqDeq"), + QueueBenchmarks::EnqDeqPairs(_) => write!(f, "EnqDeqPairs"), // #[cfg(feature = "bfs")] - Benchmarks::BFS(_) => write!(f, "BFS"), + QueueBenchmarks::BFS(_) => write!(f, "BFS"), } } } @@ -130,7 +130,7 @@ impl Default for Args { queue_size: 10000, delay: 10, path_output: "".to_string(), - benchmark: Benchmarks::ProdCon(ProdConArgs { + benchmark: QueueBenchmarks::ProdCon(ProdConArgs { producers: 5, consumers: 5, }), diff --git a/benchmark_core/src/benchmarks/benchmark_helpers.rs b/benchmark_core/src/benchmarks/benchmark_helpers.rs index a13ad03..224089e 100644 --- a/benchmark_core/src/benchmarks/benchmark_helpers.rs +++ b/benchmark_core/src/benchmarks/benchmark_helpers.rs @@ -1,6 +1,13 @@ #[cfg(feature = "memory_tracking")] use jemalloc_ctl::{epoch, stats}; +use crate::arguments::Args; +#[cfg(feature = "memory_tracking")] +use crate::traits::ConcurrentQueue; use log::{debug, error, trace}; +use std::fs::OpenOptions; +use std::io::Write; +#[cfg(feature = "memory_tracking")] +use std::sync::atomic::AtomicBool; use sysinfo::System; /// Benchmark config struct diff --git a/benchmark_core/src/benchmarks/queue_benchmarks.rs b/benchmark_core/src/benchmarks/queue_benchmarks.rs index a50f4f7..906e00d 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks.rs @@ -1,7 +1,8 @@ use chrono::Local; use clap::Parser; #[allow(unused_imports)] -use crate::arguments::{Args, Benchmarks}; +use crate::arguments::{Args, QueueBenchmarks}; +use crate::benchmarks::benchmark_helpers; #[allow(unused_imports)] use crate::traits::{ConcurrentQueue, Handle}; #[allow(unused_imports)] @@ -26,17 +27,18 @@ where { // Setup output and parse arguments let SetupResult { bench_conf, .. } = setup_benchmark()?; + let bench_conf = &bench_conf; // Create a runner lambda for the different benchmarks, mainly needed for eg. BFS to load graph and so on - let mut runner: Box Result<(), std::io::Error>> = match &bench_conf.args.benchmark { - Benchmarks::ProdCon(_) => Box::new(move |q, bench_conf| prod_con::benchmark_prod_con(q, bench_conf)), - Benchmarks::EnqDeq(_) => Box::new(move |q, bench_conf| enq_deq::benchmark_enq_deq(q, bench_conf)), - Benchmarks::EnqDeqPairs(_) => Box::new(move |q, bench_conf| enq_deq_pairs::benchmark_enq_deq_pairs(q, bench_conf)), - Benchmarks::BFS(args) => { + let mut runner: Box Result<(), std::io::Error>> = match &bench_conf.args.benchmark { + QueueBenchmarks::ProdCon(_) => Box::new(move |q, bench_conf| prod_con::benchmark_prod_con(q, bench_conf)), + QueueBenchmarks::EnqDeq(_) => Box::new(move |q, bench_conf| enq_deq::benchmark_enq_deq(q, bench_conf)), + QueueBenchmarks::EnqDeqPairs(_) => Box::new(move |q, bench_conf| enq_deq_pairs::benchmark_enq_deq_pairs(q, bench_conf)), + QueueBenchmarks::BFS(args) => { let (graph, seq_ret_vec, start_node) = bfs::pre_bfs_work( Q::new(bench_conf.args.queue_size as usize), - args, + &args, ); Box::new(move |q, _conf| bfs::benchmark_bfs( q, @@ -57,7 +59,7 @@ where #[cfg(feature = "memory_tracking")] let (done, mem_thread_handle) = { let done = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); - let handle = create_mem_tracking_thread( + let handle = benchmark_helpers::create_mem_tracking_thread( bench_conf, _current_iteration, &test_q, @@ -85,14 +87,14 @@ where } if bench_conf.args.print_info { - print_info(queue_name.to_string(), bench_conf)?; + benchmark_helpers::print_info(queue_name.to_string(), bench_conf)?; } Ok(()) } pub struct SetupResult { - pub bench_conf: benchmarks::BenchConfig, + pub bench_conf: benchmark_helpers::BenchConfig, pub columns: String, // Optional, but alreadyy written (TODO: have a stream of some sort here) } @@ -118,7 +120,7 @@ pub fn setup_benchmark() -> Result { } let output_filename = format!("{}/{}", args.path_output, date_time); - let bench_conf = benchmarks::BenchConfig { + let bench_conf = benchmark_helpers::BenchConfig { args, date_time, benchmark_id, @@ -126,7 +128,7 @@ pub fn setup_benchmark() -> Result { }; let columns = match bench_conf.args.benchmark { - arguments::Benchmarks::BFS(_) => { + QueueBenchmarks::BFS(_) => { "Milliseconds,Queuetype,Thread Count,Test ID" }, _ => { diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs b/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs index fc16819..9064371 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs @@ -1,4 +1,6 @@ -use crate::{arguments::{BFSArgs, Benchmarks}, benchmarks::BenchConfig, traits::{ConcurrentQueue, Handle}}; +use crate::arguments::{BFSArgs, QueueBenchmarks}; +use crate::traits::{ConcurrentQueue, Handle}; +use crate::benchmarks::benchmark_helpers; use std::{fs::OpenOptions, sync::{atomic::{AtomicUsize, Ordering}, Barrier}}; use core_affinity::CoreId; use log::{debug, error, info, trace}; @@ -57,7 +59,7 @@ dist_to_start_node pub fn benchmark_bfs ( cqueue: C, graph: &[Vec], - bench_conf: &BenchConfig, + bench_conf: &benchmark_helpers::BenchConfig, seq_ret_vec: &[usize], start_node: usize, ) -> Result<(), std::io::Error> @@ -65,9 +67,9 @@ where C: ConcurrentQueue, for<'a> &'a C: Send { - assert!(matches!(bench_conf.args.benchmark, Benchmarks::BFS(_))); + assert!(matches!(bench_conf.args.benchmark, QueueBenchmarks::BFS(_))); let args = match &bench_conf.args.benchmark { - crate::arguments::Benchmarks::BFS(a) => a, + QueueBenchmarks::BFS(a) => a, _ => panic!(), }; let thread_count = args.thread_count; @@ -111,7 +113,7 @@ fn parallell_bfs ( graph: &[Vec], start_node: usize, thread_count: usize, - bench_conf: &BenchConfig) + bench_conf: &benchmark_helpers::BenchConfig) -> (std::time::Duration, Vec) where C: ConcurrentQueue, diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs index 5bfde59..9b41a64 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs @@ -1,10 +1,11 @@ use core_affinity::CoreId; use log::{debug, error, info, trace}; use rand::Rng; -use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; -use crate::{traits::{ConcurrentQueue, Handle}, benchmarks::{calc_fairness, BenchConfig}}; +use crate::traits::{ConcurrentQueue, Handle}; +use crate::benchmarks::benchmark_helpers; use std::fs::OpenOptions; use std::io::Write; +use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; use std::sync::{mpsc, Arc}; /// # Explanation: @@ -14,14 +15,14 @@ use std::sync::{mpsc, Arc}; /// * --spread Set the spread of consumers/producers, value between 0 - 1. Ex. --spread 0.3, gives 30% consume, 70% produce /// * --thread-count Set the amount of threads to run in the benchmark #[allow(dead_code)] -pub fn benchmark_enq_deq (cqueue: C, bench_conf: &BenchConfig) -> Result<(), std::io::Error> +pub fn benchmark_enq_deq (cqueue: C, bench_conf: &benchmark_helpers::BenchConfig) -> Result<(), std::io::Error> where C: ConcurrentQueue, T: Default, for<'a> &'a C: Send { let args = match &bench_conf.args.benchmark { - crate::arguments::Benchmarks::EnqDeq(a) => a, + crate::arguments::QueueBenchmarks::EnqDeq(a) => a, _ => panic!(), }; { @@ -128,7 +129,7 @@ T: Default, } vals }; - let fairness = calc_fairness(ops_per_thread); + let fairness = benchmark_helpers::calc_fairness(ops_per_thread); // If a thread crashed, pad the results with zero-values let formatted = if thread_failed.load(Ordering::Relaxed) { @@ -171,8 +172,10 @@ T: Default, #[cfg(test)] mod tests { + use crate::arguments::Args; + use crate::arguments::QueueBenchmarks; use crate::arguments::EnqDeqArgs; - use crate::benchmarks::enq_deq::benchmark_enq_deq; + use crate::benchmarks::queue_benchmarks::enq_deq::benchmark_enq_deq; use super::*; @@ -181,10 +184,10 @@ mod tests { #[test] fn run_pingpong() { let args = Args { - benchmark: Benchmarks::EnqDeq(EnqDeqArgs { thread_count: 10, spread: 0.5 }), + benchmark: QueueBenchmarks::EnqDeq(EnqDeqArgs { thread_count: 10, spread: 0.5 }), ..Default::default() }; - let bench_conf = BenchConfig { + let bench_conf = benchmark_helpers::BenchConfig { args, date_time: "".to_string(), benchmark_id: "test2".to_string(), @@ -199,10 +202,10 @@ mod tests { #[test] fn run_pingpong_with_bool() { let args = Args { - benchmark: Benchmarks::EnqDeq(EnqDeqArgs { thread_count: 10, spread: 0.5 }), + benchmark: QueueBenchmarks::EnqDeq(EnqDeqArgs { thread_count: 10, spread: 0.5 }), ..Default::default() }; - let bench_conf = BenchConfig { + let bench_conf = benchmark_helpers::BenchConfig { args, date_time: "".to_string(), benchmark_id: "test2".to_string(), diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs index 5aca3a9..05ee7d3 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs @@ -2,21 +2,22 @@ use core_affinity::CoreId; use log::{debug, error, info, trace}; use rand::Rng; use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; -use crate::{traits::{ConcurrentQueue, Handle}, benchmarks::{calc_fairness, BenchConfig}}; +use crate::traits::{ConcurrentQueue, Handle}; +use crate::benchmarks::benchmark_helpers; use std::fs::OpenOptions; use std::io::Write; use std::sync::{mpsc, Arc}; /// # Explanation: #[allow(dead_code)] -pub fn benchmark_enq_deq_pairs (cqueue: C, bench_conf: &BenchConfig) -> Result<(), std::io::Error> +pub fn benchmark_enq_deq_pairs (cqueue: C, bench_conf: &benchmark_helpers::BenchConfig) -> Result<(), std::io::Error> where C: ConcurrentQueue, T: Default, for<'a> &'a C: Send { let args = match &bench_conf.args.benchmark { - crate::arguments::Benchmarks::EnqDeqPairs(a) => a, + crate::arguments::QueueBenchmarks::EnqDeqPairs(a) => a, _ => panic!(), }; { @@ -111,7 +112,7 @@ T: Default, } vals }; - let fairness = calc_fairness(ops_per_thread); + let fairness = benchmark_helpers::calc_fairness(ops_per_thread); // If a thread crashed, pad the results with zero-values let formatted = if thread_failed.load(Ordering::Relaxed) { @@ -154,8 +155,10 @@ T: Default, #[cfg(test)] mod tests { + use crate::arguments::Args; use crate::arguments::EnqDeqPairsArgs; - use crate::benchmarks::enq_deq_pairs::benchmark_enq_deq_pairs; + use crate::arguments::QueueBenchmarks; + use crate::benchmarks::queue_benchmarks::enq_deq_pairs::benchmark_enq_deq_pairs; use super::*; @@ -164,10 +167,10 @@ mod tests { #[test] fn run_enqdeq_pairs_with_struct() { let args = Args { - benchmark: Benchmarks::EnqDeqPairs(EnqDeqPairsArgs { thread_count: 10 }), + benchmark: QueueBenchmarks::EnqDeqPairs(EnqDeqPairsArgs { thread_count: 10 }), ..Default::default() }; - let bench_conf = BenchConfig { + let bench_conf = benchmark_helpers::BenchConfig { args, date_time: "".to_string(), benchmark_id: "test2".to_string(), diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs b/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs index d28873d..517142a 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs @@ -1,10 +1,11 @@ use core_affinity::CoreId; use log::{debug, error, info, trace}; use rand::Rng; -use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; -use crate::{traits::{ConcurrentQueue, Handle}, benchmarks::BenchConfig}; +use crate::traits::{ConcurrentQueue, Handle}; +use crate::benchmarks::benchmark_helpers; use std::fs::OpenOptions; use std::io::Write; +use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; use std::sync::{mpsc, Arc}; /// # Explanation: @@ -15,14 +16,14 @@ use std::sync::{mpsc, Arc}; /// * -p Set specified amount of producers /// * -c Set specified amount of consumers #[allow(dead_code)] -pub fn benchmark_prod_con(cqueue: C, bench_conf: &BenchConfig) -> Result<(), std::io::Error> +pub fn benchmark_prod_con(cqueue: C, bench_conf: &benchmark_helpers::BenchConfig) -> Result<(), std::io::Error> where C: ConcurrentQueue, T: Default, for<'a> &'a C: Send { let args = match &bench_conf.args.benchmark { - crate::arguments::Benchmarks::ProdCon(a) => a, + crate::arguments::QueueBenchmarks::ProdCon(a) => a, _ => panic!(), }; { @@ -175,7 +176,7 @@ where format!("0,0,0,{},{},-1,{},{},{},0,-1,{}", producers, consumers, cqueue.get_id(), bench_conf.args.benchmark, bench_conf.benchmark_id, bench_conf.args.queue_size) } else { - let fairness = crate::benchmarks::calc_fairness(ops_per_thread); + let fairness = benchmark_helpers::calc_fairness(ops_per_thread); format!("{},{},{},{},{},{},{},{},{},{},{},{}", (pushes + pops) as f64 / time_limit as f64, pushes, @@ -210,12 +211,13 @@ where mod tests { use super::*; + use crate::arguments::Args; use crate::benchmarks::test_helpers::test_queue::TestQueue; #[test] fn run_basic_prod_con() { let args = Args::default(); - let bench_conf = BenchConfig { + let bench_conf = benchmark_helpers::BenchConfig { args, date_time: "".to_string(), benchmark_id: "test1".to_string(), @@ -230,7 +232,7 @@ mod tests { #[test] fn run_basic_with_string() { let args = Args::default(); - let bench_conf = BenchConfig { + let bench_conf = benchmark_helpers::BenchConfig { args, date_time: "".to_string(), benchmark_id: "test1".to_string(), @@ -245,7 +247,7 @@ mod tests { #[test] fn run_basic_with_struct() { let args = Args::default(); - let bench_conf = BenchConfig { + let bench_conf = benchmark_helpers::BenchConfig { args, date_time: "".to_string(), benchmark_id: "test1".to_string(), diff --git a/benchmark_core/src/benchmarks/test_helpers.rs b/benchmark_core/src/benchmarks/test_helpers.rs index 5766ee8..f80d896 100644 --- a/benchmark_core/src/benchmarks/test_helpers.rs +++ b/benchmark_core/src/benchmarks/test_helpers.rs @@ -1,8 +1,9 @@ -use crate::traits::{ConcurrentQueue, Handle}; -use std::{collections::VecDeque, sync::Mutex}; - /// A very simple ConcurrentQueue implementation for testing -mod test_queue { +pub(crate) mod test_queue { + use crate::traits::{ConcurrentQueue, Handle}; + use std::collections::VecDeque; + use std::sync::Mutex; + pub struct TestQueue { queue: Mutex>, } @@ -12,7 +13,7 @@ mod test_queue { } impl Handle for TestQueueHandle<'_, T> { - fn push(&mut self, item: T) -> Result<(), T>{ + fn push(&mut self, item: T) -> Result<(), T> { self.queue.queue.lock().unwrap().push_back(item); Ok(()) } @@ -24,9 +25,7 @@ mod test_queue { impl ConcurrentQueue for TestQueue { fn register(&self) -> impl Handle { - TestQueueHandle { - queue: self, - } + TestQueueHandle { queue: self } } fn get_id(&self) -> String { @@ -35,7 +34,7 @@ mod test_queue { fn new(_size: usize) -> Self { TestQueue { - queue: Mutex::new(VecDeque::new()) + queue: Mutex::new(VecDeque::new()), } } } diff --git a/data_structures/queues/array_queue/src/main.rs b/data_structures/queues/array_queue/src/main.rs index 43a4e90..e3b0f62 100644 --- a/data_structures/queues/array_queue/src/main.rs +++ b/data_structures/queues/array_queue/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("array_queue") { + match benchmark_queue::>("array_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/atomic_queue/src/main.rs b/data_structures/queues/atomic_queue/src/main.rs index 881527b..7c83935 100644 --- a/data_structures/queues/atomic_queue/src/main.rs +++ b/data_structures/queues/atomic_queue/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("atomic_queue") { + match benchmark_queue::>("atomic_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/basic_queue/src/main.rs b/data_structures/queues/basic_queue/src/main.rs index 64a1878..a1b6bfc 100644 --- a/data_structures/queues/basic_queue/src/main.rs +++ b/data_structures/queues/basic_queue/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("basic_queue") { + match benchmark_queue::>("basic_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/bbq/src/main.rs b/data_structures/queues/bbq/src/main.rs index eb7ee1c..31e515c 100644 --- a/data_structures/queues/bbq/src/main.rs +++ b/data_structures/queues/bbq/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("BBQ") { + match benchmark_queue::>("BBQ") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/boost_queue_cpp/src/main.rs b/data_structures/queues/boost_queue_cpp/src/main.rs index 16c0533..caec141 100644 --- a/data_structures/queues/boost_queue_cpp/src/main.rs +++ b/data_structures/queues/boost_queue_cpp/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("boost_queue_cpp") { + match benchmark_queue::>("boost_queue_cpp") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/bounded_concurrent_queue/src/main.rs b/data_structures/queues/bounded_concurrent_queue/src/main.rs index a13889d..0685032 100644 --- a/data_structures/queues/bounded_concurrent_queue/src/main.rs +++ b/data_structures/queues/bounded_concurrent_queue/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("bounded_concurrent_queue") { + match benchmark_queue::>("bounded_concurrent_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/bounded_ringbuffer/src/main.rs b/data_structures/queues/bounded_ringbuffer/src/main.rs index c311094..5fdad37 100644 --- a/data_structures/queues/bounded_ringbuffer/src/main.rs +++ b/data_structures/queues/bounded_ringbuffer/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("bounded_ringbuffer") { + match benchmark_queue::>("bounded_ringbuffer") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/faaa_queue/src/main.rs b/data_structures/queues/faaa_queue/src/main.rs index 0d39ba8..002fcb4 100644 --- a/data_structures/queues/faaa_queue/src/main.rs +++ b/data_structures/queues/faaa_queue/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("faa_array_queue") { + match benchmark_queue::>("faa_array_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/faaa_queue_cpp/src/main.rs b/data_structures/queues/faaa_queue_cpp/src/main.rs index 9dcc863..8cc8635 100644 --- a/data_structures/queues/faaa_queue_cpp/src/main.rs +++ b/data_structures/queues/faaa_queue_cpp/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("faaa_queue_cpp") { + match benchmark_queue::>("faaa_queue_cpp") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/lcrq/src/main.rs b/data_structures/queues/lcrq/src/main.rs index 7796b9b..4496b41 100644 --- a/data_structures/queues/lcrq/src/main.rs +++ b/data_structures/queues/lcrq/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("array_queue") { + match benchmark_queue::>("array_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/lcrq_cpp/src/main.rs b/data_structures/queues/lcrq_cpp/src/main.rs index ee5b37e..f4b9f01 100644 --- a/data_structures/queues/lcrq_cpp/src/main.rs +++ b/data_structures/queues/lcrq_cpp/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("lcrq_cpp") { + match benchmark_queue::>("lcrq_cpp") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/lf_queue/src/main.rs b/data_structures/queues/lf_queue/src/main.rs index 335d4fa..2203205 100644 --- a/data_structures/queues/lf_queue/src/main.rs +++ b/data_structures/queues/lf_queue/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("lf_queue") { + match benchmark_queue::>("lf_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/lockfree_queue/src/main.rs b/data_structures/queues/lockfree_queue/src/main.rs index d4d9470..26a7a9d 100644 --- a/data_structures/queues/lockfree_queue/src/main.rs +++ b/data_structures/queues/lockfree_queue/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("lockfree_queue") { + match benchmark_queue::>("lockfree_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/lprq/src/main.rs b/data_structures/queues/lprq/src/main.rs index 3b76232..8a75d9c 100644 --- a/data_structures/queues/lprq/src/main.rs +++ b/data_structures/queues/lprq/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("LPRQ") { + match benchmark_queue::>("LPRQ") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/lprq_cpp/src/main.rs b/data_structures/queues/lprq_cpp/src/main.rs index 5ac4ebf..88fe413 100644 --- a/data_structures/queues/lprq_cpp/src/main.rs +++ b/data_structures/queues/lprq_cpp/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("lprq_queue_cpp") { + match benchmark_queue::>("lprq_queue_cpp") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/moodycamel_cpp/src/main.rs b/data_structures/queues/moodycamel_cpp/src/main.rs index 69814d7..517c214 100644 --- a/data_structures/queues/moodycamel_cpp/src/main.rs +++ b/data_structures/queues/moodycamel_cpp/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("moodycamel_cpp") { + match benchmark_queue::>("moodycamel_cpp") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/ms_queue/src/main.rs b/data_structures/queues/ms_queue/src/main.rs index e8888f3..62e6691 100644 --- a/data_structures/queues/ms_queue/src/main.rs +++ b/data_structures/queues/ms_queue/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("ms_queue") { + match benchmark_queue::>("ms_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/scc2_queue/src/main.rs b/data_structures/queues/scc2_queue/src/main.rs index 79af830..7d6f899 100644 --- a/data_structures/queues/scc2_queue/src/main.rs +++ b/data_structures/queues/scc2_queue/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("scc2_queue") { + match benchmark_queue::>("scc2_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/scc_queue/src/main.rs b/data_structures/queues/scc_queue/src/main.rs index 9ed41de..40200ed 100644 --- a/data_structures/queues/scc_queue/src/main.rs +++ b/data_structures/queues/scc_queue/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("scc_queue") { + match benchmark_queue::>("scc_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/seg_queue/src/main.rs b/data_structures/queues/seg_queue/src/main.rs index 47f72b3..ec2a416 100644 --- a/data_structures/queues/seg_queue/src/main.rs +++ b/data_structures/queues/seg_queue/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("seg_queue") { + match benchmark_queue::>("seg_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/tz_queue_hp/src/main.rs b/data_structures/queues/tz_queue_hp/src/main.rs index 53c8ab6..0560b5e 100644 --- a/data_structures/queues/tz_queue_hp/src/main.rs +++ b/data_structures/queues/tz_queue_hp/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("tz_queue_hp") { + match benchmark_queue::>("tz_queue_hp") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/tz_queue_leak/src/main.rs b/data_structures/queues/tz_queue_leak/src/main.rs index 584d4df..5e25d93 100644 --- a/data_structures/queues/tz_queue_leak/src/main.rs +++ b/data_structures/queues/tz_queue_leak/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("tz_queue_leak") { + match benchmark_queue::>("tz_queue_leak") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/unbounded_concurrent_queue/src/main.rs b/data_structures/queues/unbounded_concurrent_queue/src/main.rs index 7c6d20a..e6b426d 100644 --- a/data_structures/queues/unbounded_concurrent_queue/src/main.rs +++ b/data_structures/queues/unbounded_concurrent_queue/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("unbounded_concurrent_queue") { + match benchmark_queue::>("unbounded_concurrent_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/wf_queue/src/main.rs b/data_structures/queues/wf_queue/src/main.rs index 476a494..24a522e 100644 --- a/data_structures/queues/wf_queue/src/main.rs +++ b/data_structures/queues/wf_queue/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("wf_queue") { + match benchmark_queue::>("wf_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/stacks/lockfree_stack/src/main.rs b/data_structures/stacks/lockfree_stack/src/main.rs index 620bbb9..f8b6481 100644 --- a/data_structures/stacks/lockfree_stack/src/main.rs +++ b/data_structures/stacks/lockfree_stack/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("lockfree_stack") { + match benchmark_queue::>("lockfree_stack") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/stacks/scc2_stack/src/main.rs b/data_structures/stacks/scc2_stack/src/main.rs index 2a90dbe..4fa2fd8 100644 --- a/data_structures/stacks/scc2_stack/src/main.rs +++ b/data_structures/stacks/scc2_stack/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("scc2_stack") { + match benchmark_queue::>("scc2_stack") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/stacks/scc_stack/src/main.rs b/data_structures/stacks/scc_stack/src/main.rs index 0f30f6a..b6d7907 100644 --- a/data_structures/stacks/scc_stack/src/main.rs +++ b/data_structures/stacks/scc_stack/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("scc_stack") { + match benchmark_queue::>("scc_stack") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); From 29f16a332aa3aa922dcffd0c94154fd03c38cf1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Tue, 3 Feb 2026 15:44:22 +0100 Subject: [PATCH 06/16] Add entry for output directory in scripts/ --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index efd9c17..5ed9274 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /target /output +/scripts/output Cargo.lock /venv src/cpp-ring-queues-research/benchmarks.sh From 86b46ee840e9d8c6555fb230007892ee5e22a50e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Tue, 3 Feb 2026 15:44:51 +0100 Subject: [PATCH 07/16] Change run_benchmark script to valid invocations --- scripts/run_benchmark.sh | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/scripts/run_benchmark.sh b/scripts/run_benchmark.sh index 394e1d8..6f28882 100755 --- a/scripts/run_benchmark.sh +++ b/scripts/run_benchmark.sh @@ -1,22 +1,22 @@ #!/bin/bash ./clean.sh -RUST_LOG=debug cargo run --release --features memory_tracking -p basic_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p basic_queue -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p array_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p array_queue -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p lockfree_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p lockfree_queue -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p unbounded_concurrent_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p unbounded_concurrent_queue -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p bounded_ringbuffer -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p bounded_ringbuffer -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p atomic_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p atomic_queue -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p wf_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p wf_queue -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p scc_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p scc_queue -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p scc2_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p scc2_queue -- -t 1 basic +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p basic_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p basic_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p array_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p array_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p lockfree_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p lockfree_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p unbounded_concurrent_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p unbounded_concurrent_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p bounded_ringbuffer -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p bounded_ringbuffer -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p atomic_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p atomic_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p wf_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p wf_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p scc_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p scc_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p scc2_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p scc2_queue -- -t 1 prod-con bat output/* From d211828ad92db3833a4390a3d211e0a5c8dfdb6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Tue, 3 Feb 2026 16:37:28 +0100 Subject: [PATCH 08/16] Change Handle to HandleQueue --- benchmark_core/src/benchmarks/queue_benchmarks.rs | 2 +- benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs | 4 ++-- .../src/benchmarks/queue_benchmarks/enq_deq.rs | 2 +- .../src/benchmarks/queue_benchmarks/enq_deq_pairs.rs | 2 +- .../src/benchmarks/queue_benchmarks/prod_con.rs | 2 +- benchmark_core/src/benchmarks/test_helpers.rs | 6 +++--- benchmark_core/src/order.rs | 2 +- benchmark_core/src/traits.rs | 11 +++++------ data_structures/queues/array_queue/src/lib.rs | 6 +++--- data_structures/queues/atomic_queue/src/lib.rs | 6 +++--- data_structures/queues/basic_queue/src/lib.rs | 6 +++--- data_structures/queues/bbq/src/lib.rs | 6 +++--- data_structures/queues/boost_queue_cpp/src/lib.rs | 6 +++--- .../queues/bounded_concurrent_queue/src/lib.rs | 6 +++--- data_structures/queues/bounded_ringbuffer/src/lib.rs | 6 +++--- data_structures/queues/faaa_queue/src/lib.rs | 6 +++--- data_structures/queues/faaa_queue_cpp/src/lib.rs | 6 +++--- data_structures/queues/lcrq/src/lib.rs | 6 +++--- data_structures/queues/lcrq_cpp/src/lib.rs | 6 +++--- data_structures/queues/lf_queue/src/lib.rs | 6 +++--- data_structures/queues/lockfree_queue/src/lib.rs | 6 +++--- data_structures/queues/lprq/src/lib.rs | 6 +++--- data_structures/queues/lprq/src/lprq_rs.rs | 6 +++--- data_structures/queues/lprq_cpp/src/lib.rs | 6 +++--- data_structures/queues/moodycamel_cpp/src/lib.rs | 6 +++--- data_structures/queues/ms_queue/src/lib.rs | 6 +++--- data_structures/queues/scc2_queue/src/lib.rs | 6 +++--- data_structures/queues/scc_queue/src/lib.rs | 6 +++--- data_structures/queues/seg_queue/src/lib.rs | 6 +++--- data_structures/queues/tz_queue_hp/src/lib.rs | 6 +++--- data_structures/queues/tz_queue_leak/src/lib.rs | 6 +++--- .../queues/unbounded_concurrent_queue/src/lib.rs | 6 +++--- data_structures/queues/wf_queue/src/lib.rs | 8 ++++---- data_structures/stacks/lockfree_stack/src/lib.rs | 6 +++--- data_structures/stacks/scc2_stack/src/lib.rs | 6 +++--- data_structures/stacks/scc_stack/src/lib.rs | 6 +++--- readme.md | 10 +++++----- 37 files changed, 105 insertions(+), 106 deletions(-) diff --git a/benchmark_core/src/benchmarks/queue_benchmarks.rs b/benchmark_core/src/benchmarks/queue_benchmarks.rs index 906e00d..3e38d08 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks.rs @@ -4,7 +4,7 @@ use clap::Parser; use crate::arguments::{Args, QueueBenchmarks}; use crate::benchmarks::benchmark_helpers; #[allow(unused_imports)] -use crate::traits::{ConcurrentQueue, Handle}; +use crate::traits::{ConcurrentQueue, HandleQueue}; #[allow(unused_imports)] use log::{self, debug, error, info}; use std::collections::hash_map::DefaultHasher; diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs b/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs index 9064371..6b38fa9 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs @@ -1,5 +1,5 @@ use crate::arguments::{BFSArgs, QueueBenchmarks}; -use crate::traits::{ConcurrentQueue, Handle}; +use crate::traits::{ConcurrentQueue, HandleQueue}; use crate::benchmarks::benchmark_helpers; use std::{fs::OpenOptions, sync::{atomic::{AtomicUsize, Ordering}, Barrier}}; use core_affinity::CoreId; @@ -189,7 +189,7 @@ C: ConcurrentQueue, } fn pbfs_helper( - mut handle: impl Handle, + mut handle: impl HandleQueue, result_vector: &[AtomicUsize], graph: &[Vec], i: usize, diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs index 9b41a64..b6fd386 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs @@ -1,7 +1,7 @@ use core_affinity::CoreId; use log::{debug, error, info, trace}; use rand::Rng; -use crate::traits::{ConcurrentQueue, Handle}; +use crate::traits::{ConcurrentQueue, HandleQueue}; use crate::benchmarks::benchmark_helpers; use std::fs::OpenOptions; use std::io::Write; diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs index 05ee7d3..d930aff 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs @@ -2,7 +2,7 @@ use core_affinity::CoreId; use log::{debug, error, info, trace}; use rand::Rng; use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; -use crate::traits::{ConcurrentQueue, Handle}; +use crate::traits::{ConcurrentQueue, HandleQueue}; use crate::benchmarks::benchmark_helpers; use std::fs::OpenOptions; use std::io::Write; diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs b/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs index 517142a..2ae5177 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs @@ -1,7 +1,7 @@ use core_affinity::CoreId; use log::{debug, error, info, trace}; use rand::Rng; -use crate::traits::{ConcurrentQueue, Handle}; +use crate::traits::{ConcurrentQueue, HandleQueue}; use crate::benchmarks::benchmark_helpers; use std::fs::OpenOptions; use std::io::Write; diff --git a/benchmark_core/src/benchmarks/test_helpers.rs b/benchmark_core/src/benchmarks/test_helpers.rs index f80d896..492cfe6 100644 --- a/benchmark_core/src/benchmarks/test_helpers.rs +++ b/benchmark_core/src/benchmarks/test_helpers.rs @@ -1,6 +1,6 @@ /// A very simple ConcurrentQueue implementation for testing pub(crate) mod test_queue { - use crate::traits::{ConcurrentQueue, Handle}; + use crate::traits::{ConcurrentQueue, HandleQueue}; use std::collections::VecDeque; use std::sync::Mutex; @@ -12,7 +12,7 @@ pub(crate) mod test_queue { queue: &'a TestQueue, } - impl Handle for TestQueueHandle<'_, T> { + impl HandleQueue for TestQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { self.queue.queue.lock().unwrap().push_back(item); Ok(()) @@ -24,7 +24,7 @@ pub(crate) mod test_queue { } impl ConcurrentQueue for TestQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { TestQueueHandle { queue: self } } diff --git a/benchmark_core/src/order.rs b/benchmark_core/src/order.rs index 7f31e95..a5ca687 100644 --- a/benchmark_core/src/order.rs +++ b/benchmark_core/src/order.rs @@ -6,7 +6,7 @@ use std::sync::{ Barrier, }; -use crate::traits::{ConcurrentQueue, Handle}; +use crate::traits::{ConcurrentQueue, HandleQueue}; #[allow(clippy::result_unit_err)] pub fn benchmark_order_box( diff --git a/benchmark_core/src/traits.rs b/benchmark_core/src/traits.rs index cccfc52..3897a46 100644 --- a/benchmark_core/src/traits.rs +++ b/benchmark_core/src/traits.rs @@ -1,7 +1,7 @@ -/// One of the traits that all queues implemented in the benchmark -/// needs to implement. +/// Trait that all queues need to implement pub trait ConcurrentQueue { - fn register(&self) -> impl Handle; + /// Returns a handle that exposes the queue API + fn register(&self) -> impl HandleQueue; /// Returns the name of the queue. fn get_id(&self) -> String; /// Used to create a new queue. @@ -9,9 +9,8 @@ pub trait ConcurrentQueue { fn new(size: usize) -> Self; } -/// One of the traits all queues implemented in the benchmark -/// needs to implement. -pub trait Handle { +/// Trait that exposes the correct API for queues +pub trait HandleQueue { /// Pushes an item to the queue. /// If it fails, returns the item pushed. fn push(&mut self, item: T) -> Result<(), T>; diff --git a/data_structures/queues/array_queue/src/lib.rs b/data_structures/queues/array_queue/src/lib.rs index 76d712d..3e76eda 100644 --- a/data_structures/queues/array_queue/src/lib.rs +++ b/data_structures/queues/array_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use crossbeam::queue::ArrayQueue; pub struct AQueueHandle<'a, T>{ @@ -11,7 +11,7 @@ pub struct AQueue{ impl ConcurrentQueue for AQueue { - fn register(&self) -> impl Handle{ + fn register(&self) -> impl HandleQueue{ AQueueHandle{ queue: self, } @@ -26,7 +26,7 @@ impl ConcurrentQueue for AQueue { } } -impl Handle for AQueueHandle<'_, T>{ +impl HandleQueue for AQueueHandle<'_, T>{ fn push(&mut self, value: T) -> Result<(), T>{ self.queue.array_queue.push(value) } diff --git a/data_structures/queues/atomic_queue/src/lib.rs b/data_structures/queues/atomic_queue/src/lib.rs index b3c8a0c..ba3c3f0 100644 --- a/data_structures/queues/atomic_queue/src/lib.rs +++ b/data_structures/queues/atomic_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct AtomicQueue { pub queue: atomic_queue_upstream::Queue, @@ -9,7 +9,7 @@ pub struct AtomicQueueHandle<'a, T> { } impl ConcurrentQueue for AtomicQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { AtomicQueueHandle { queue: self, } @@ -24,7 +24,7 @@ impl ConcurrentQueue for AtomicQueue { } } -impl Handle for AtomicQueueHandle<'_, T> { +impl HandleQueue for AtomicQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T>{ if !self.queue.queue.push(item) { return Err(T::default()); diff --git a/data_structures/queues/basic_queue/src/lib.rs b/data_structures/queues/basic_queue/src/lib.rs index 8f48a74..55ae933 100644 --- a/data_structures/queues/basic_queue/src/lib.rs +++ b/data_structures/queues/basic_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use std::{collections::VecDeque, sync::Mutex}; pub struct BQueue { @@ -39,7 +39,7 @@ pub struct BasicQueueHandle<'a, T> { } impl ConcurrentQueue for BasicQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { BasicQueueHandle { queue: self, } @@ -54,7 +54,7 @@ impl ConcurrentQueue for BasicQueue { } } -impl Handle for BasicQueueHandle<'_, T> { +impl HandleQueue for BasicQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T>{ self.queue.bqueue.push(item); Ok(()) diff --git a/data_structures/queues/bbq/src/lib.rs b/data_structures/queues/bbq/src/lib.rs index d497c14..9f5c121 100644 --- a/data_structures/queues/bbq/src/lib.rs +++ b/data_structures/queues/bbq/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use bbq_upstream::BlockingQueue; pub struct BBQueue{ @@ -10,7 +10,7 @@ pub struct BBQHandle<'a, T> { } impl ConcurrentQueue for BBQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { BBQHandle:: { queue: self, } @@ -25,7 +25,7 @@ impl ConcurrentQueue for BBQueue { } } -impl Handle for BBQHandle<'_, T> { +impl HandleQueue for BBQHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { self.queue.queue.push(item).expect("failed push"); Ok(()) diff --git a/data_structures/queues/boost_queue_cpp/src/lib.rs b/data_structures/queues/boost_queue_cpp/src/lib.rs index 72e08ff..12441ed 100644 --- a/data_structures/queues/boost_queue_cpp/src/lib.rs +++ b/data_structures/queues/boost_queue_cpp/src/lib.rs @@ -2,7 +2,7 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; // Include the generated bindings include!(concat!(env!("OUT_DIR"), "/bindings.rs")); @@ -47,7 +47,7 @@ struct BoostCppQueueHandle<'a,T> { pub q: &'a BoostCppQueue } -impl Handle for BoostCppQueueHandle<'_,T> { +impl HandleQueue for BoostCppQueueHandle<'_,T> { fn push(&mut self, item: T) -> Result<(), T> { let ptr: *mut std::ffi::c_void = Box::::into_raw(Box::new(item)) as *mut std::ffi::c_void; match self.q.push(ptr) { @@ -68,7 +68,7 @@ impl Handle for BoostCppQueueHandle<'_,T> { } impl ConcurrentQueue for BoostCppQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { BoostCppQueueHandle { q: self, } diff --git a/data_structures/queues/bounded_concurrent_queue/src/lib.rs b/data_structures/queues/bounded_concurrent_queue/src/lib.rs index 43d8f94..7800063 100644 --- a/data_structures/queues/bounded_concurrent_queue/src/lib.rs +++ b/data_structures/queues/bounded_concurrent_queue/src/lib.rs @@ -1,7 +1,7 @@ use concurrent_queue::PushError; use log::warn; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct BoundedCQueueHandle<'a, T> { queue: &'a BoundedCQueue @@ -12,7 +12,7 @@ pub struct BoundedCQueue { } impl ConcurrentQueue for BoundedCQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { BoundedCQueueHandle { queue: self, } @@ -27,7 +27,7 @@ impl ConcurrentQueue for BoundedCQueue { } } -impl Handle for BoundedCQueueHandle<'_, T> { +impl HandleQueue for BoundedCQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T>{ if let Err(err) = self.queue.cq.push(item) { let i = match err { diff --git a/data_structures/queues/bounded_ringbuffer/src/lib.rs b/data_structures/queues/bounded_ringbuffer/src/lib.rs index 7701239..364571f 100644 --- a/data_structures/queues/bounded_ringbuffer/src/lib.rs +++ b/data_structures/queues/bounded_ringbuffer/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use std::sync::Mutex; pub struct BRingBuffer { @@ -67,7 +67,7 @@ pub struct BRingBufferHandle<'a, T>{ } -impl Handle for BRingBufferHandle<'_, T>{ +impl HandleQueue for BRingBufferHandle<'_, T>{ fn pop(&mut self) -> Option{ let mut buf = self.queue.brbuffer.bounded_ringbuffer.lock().unwrap(); buf.pop() @@ -80,7 +80,7 @@ impl Handle for BRingBufferHandle<'_, T>{ } impl ConcurrentQueue for BoundedRingBuffer{ - fn register(&self) -> impl Handle{ + fn register(&self) -> impl HandleQueue{ BRingBufferHandle:: { queue: self, } diff --git a/data_structures/queues/faaa_queue/src/lib.rs b/data_structures/queues/faaa_queue/src/lib.rs index 26c91e7..3aa17e4 100644 --- a/data_structures/queues/faaa_queue/src/lib.rs +++ b/data_structures/queues/faaa_queue/src/lib.rs @@ -3,7 +3,7 @@ use std::{ptr::null_mut, sync::atomic::{AtomicPtr as RawAtomicPtr, AtomicUsize, use haphazard::{AtomicPtr as HpAtomicPtr, HazardPointer}; use crossbeam::utils::CachePadded; use log::trace; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; const BUFFER_SIZE: usize = 1024; @@ -136,7 +136,7 @@ pub struct FAAAQueueHandle<'a, T> { } impl ConcurrentQueue for FAAAQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { FAAAQueueHandle { queue: self, hp: HazardPointer::new(), @@ -154,7 +154,7 @@ impl ConcurrentQueue for FAAAQueue { } } -impl Handle for FAAAQueueHandle<'_, T> { +impl HandleQueue for FAAAQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { self.queue.enqueue(item, &mut self.hp); Ok(()) diff --git a/data_structures/queues/faaa_queue_cpp/src/lib.rs b/data_structures/queues/faaa_queue_cpp/src/lib.rs index 6744732..4a92064 100644 --- a/data_structures/queues/faaa_queue_cpp/src/lib.rs +++ b/data_structures/queues/faaa_queue_cpp/src/lib.rs @@ -4,7 +4,7 @@ use std::{cell::Cell, sync::atomic::{AtomicI32, Ordering}}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; // Include the generated bindings include!(concat!(env!("OUT_DIR"), "/bindings.rs")); @@ -80,7 +80,7 @@ struct FAAAQHandle<'a, T> { pub q: &'a FAAAQueue } -impl Handle for FAAAQHandle<'_, T> { +impl HandleQueue for FAAAQHandle<'_, T> { fn push(&mut self, item: T) -> Result <(), T>{ let ptr: *mut std::ffi::c_void = Box::::into_raw(Box::new(item)) as *mut std::ffi::c_void; match self.q.push(ptr) { @@ -100,7 +100,7 @@ impl Handle for FAAAQHandle<'_, T> { } impl ConcurrentQueue for FAAAQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { FAAAQHandle { q: self, } diff --git a/data_structures/queues/lcrq/src/lib.rs b/data_structures/queues/lcrq/src/lib.rs index 4ed3577..6f9b5d3 100644 --- a/data_structures/queues/lcrq/src/lib.rs +++ b/data_structures/queues/lcrq/src/lib.rs @@ -8,7 +8,7 @@ use haphazard::{raw::Pointer, AtomicPtr as HpAtomicPtr, HazardPointer}; #[allow(unused_imports)] use log::{debug, error, trace}; #[allow(unused_imports)] -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use crossbeam::utils::CachePadded; static RING_SIZE: usize = 1024; @@ -380,7 +380,7 @@ impl ConcurrentQueue for LCRQueue { fn new(_size: usize) -> Self { LCRQueue::new() } - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { LCRQueueHandle { queue: self, hp1: HazardPointer::new(), @@ -395,7 +395,7 @@ struct LCRQueueHandle<'a, T: std::fmt::Debug> { // hp2: HazardPointer<'static>, } -impl Handle for LCRQueueHandle<'_, T> { +impl HandleQueue for LCRQueueHandle<'_, T> { fn pop(&mut self) -> Option { self.queue.dequeue(&mut self.hp1) } diff --git a/data_structures/queues/lcrq_cpp/src/lib.rs b/data_structures/queues/lcrq_cpp/src/lib.rs index 92f064b..8d057b5 100644 --- a/data_structures/queues/lcrq_cpp/src/lib.rs +++ b/data_structures/queues/lcrq_cpp/src/lib.rs @@ -4,7 +4,7 @@ use std::{cell::Cell, sync::atomic::{AtomicI32, Ordering}}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; // Include the generated bindings include!(concat!(env!("OUT_DIR"), "/bindings.rs")); @@ -75,7 +75,7 @@ struct LCRQHandle<'a, T> { pub q: &'a LCRQueue } -impl Handle for LCRQHandle<'_, T> { +impl HandleQueue for LCRQHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { let ptr: *mut std::ffi::c_void = Box::::into_raw(Box::new(item)) as *mut std::ffi::c_void; match self.q.push(ptr) { @@ -95,7 +95,7 @@ impl Handle for LCRQHandle<'_, T> { } impl ConcurrentQueue for LCRQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { LCRQHandle { q: self, } diff --git a/data_structures/queues/lf_queue/src/lib.rs b/data_structures/queues/lf_queue/src/lib.rs index 6bae198..3be402a 100644 --- a/data_structures/queues/lf_queue/src/lib.rs +++ b/data_structures/queues/lf_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct LFQueue { pub lfq: lf_queue_upstream::Queue @@ -9,7 +9,7 @@ pub struct LFQueueHandle<'a, T> { } impl ConcurrentQueue for LFQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { LFQueueHandle { queue: self, } @@ -24,7 +24,7 @@ impl ConcurrentQueue for LFQueue { } } -impl Handle for LFQueueHandle<'_, T> { +impl HandleQueue for LFQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T>{ self.queue.lfq.push(item); Ok(()) diff --git a/data_structures/queues/lockfree_queue/src/lib.rs b/data_structures/queues/lockfree_queue/src/lib.rs index 9cd8fce..afbc98a 100644 --- a/data_structures/queues/lockfree_queue/src/lib.rs +++ b/data_structures/queues/lockfree_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct LockfreeQueueHandle<'a, T> { @@ -10,7 +10,7 @@ pub struct LockfreeQueue { } impl ConcurrentQueue for LockfreeQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { LockfreeQueueHandle { queue: self, } @@ -25,7 +25,7 @@ impl ConcurrentQueue for LockfreeQueue { } } -impl Handle for LockfreeQueueHandle<'_, T> { +impl HandleQueue for LockfreeQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T>{ self.queue.lfq.push(item); Ok(()) diff --git a/data_structures/queues/lprq/src/lib.rs b/data_structures/queues/lprq/src/lib.rs index 048e208..52ed122 100644 --- a/data_structures/queues/lprq/src/lib.rs +++ b/data_structures/queues/lprq/src/lib.rs @@ -3,7 +3,7 @@ use std::sync::atomic::Ordering::SeqCst as SeqCst; use haphazard::{AtomicPtr as HpAtomicPtr, HazardPointer}; use log::{debug, trace}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use crossbeam::utils::CachePadded; static RING_SIZE: u64 = 1024; @@ -338,7 +338,7 @@ impl ConcurrentQueue for LPRQueue { fn new(_size: usize) -> Self { LPRQueue::new() } - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { LPRQueueHandle { queue: self, hp: HazardPointer::new(), @@ -351,7 +351,7 @@ struct LPRQueueHandle<'a, T> { hp: HazardPointer<'static>, } -impl Handle for LPRQueueHandle<'_, T> { +impl HandleQueue for LPRQueueHandle<'_, T> { fn pop(&mut self) -> Option { self.queue.dequeue(&mut self.hp) } diff --git a/data_structures/queues/lprq/src/lprq_rs.rs b/data_structures/queues/lprq/src/lprq_rs.rs index dca1056..5a62203 100644 --- a/data_structures/queues/lprq/src/lprq_rs.rs +++ b/data_structures/queues/lprq/src/lprq_rs.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use lprq_rs::LPRQueue; pub struct LPRQueueRSHandle<'a, T>{ @@ -10,7 +10,7 @@ pub struct LPRQRS{ } impl ConcurrentQueue for LPRQRS{ - fn register(&self) -> impl Handle{ + fn register(&self) -> impl HandleQueue{ LPRQueueRSHandle{ queue: self, } @@ -27,7 +27,7 @@ impl ConcurrentQueue for LPRQRS{ } } -impl Handle for LPRQueueRSHandle<'_, T> { +impl HandleQueue for LPRQueueRSHandle<'_, T> { fn push(&mut self, value: T) -> Result<(), T> { self.queue.lprqueue.enqueue(value); Ok(()) diff --git a/data_structures/queues/lprq_cpp/src/lib.rs b/data_structures/queues/lprq_cpp/src/lib.rs index 6ab3a4b..83123a3 100644 --- a/data_structures/queues/lprq_cpp/src/lib.rs +++ b/data_structures/queues/lprq_cpp/src/lib.rs @@ -4,7 +4,7 @@ use std::{cell::Cell, sync::atomic::{AtomicI32, Ordering}}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; // Include the generated bindings include!(concat!(env!("OUT_DIR"), "/bindings.rs")); @@ -80,7 +80,7 @@ struct LPRQHandle<'a, T> { pub q: &'a LPRQueue } -impl Handle for LPRQHandle<'_, T> { +impl HandleQueue for LPRQHandle<'_, T> { fn push(&mut self, item: T) -> Result <(), T>{ let ptr: *mut std::ffi::c_void = Box::::into_raw(Box::new(item)) as *mut std::ffi::c_void; match self.q.push(ptr) { @@ -100,7 +100,7 @@ impl Handle for LPRQHandle<'_, T> { } impl ConcurrentQueue for LPRQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { LPRQHandle { q: self, } diff --git a/data_structures/queues/moodycamel_cpp/src/lib.rs b/data_structures/queues/moodycamel_cpp/src/lib.rs index a110d59..eb54222 100644 --- a/data_structures/queues/moodycamel_cpp/src/lib.rs +++ b/data_structures/queues/moodycamel_cpp/src/lib.rs @@ -2,7 +2,7 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; // Include the generated bindings include!(concat!(env!("OUT_DIR"), "/bindings.rs")); @@ -49,7 +49,7 @@ struct MoodyCamelCppQueueHandle<'a,T> { pub q: &'a MoodyCamelCppQueue } -impl Handle for MoodyCamelCppQueueHandle<'_,T> { +impl HandleQueue for MoodyCamelCppQueueHandle<'_,T> { fn push(&mut self, item: T) -> Result<(), T>{ let ptr: *mut std::ffi::c_void = Box::::into_raw(Box::new(item)) as *mut std::ffi::c_void; match self.q.push(ptr) { @@ -72,7 +72,7 @@ impl Handle for MoodyCamelCppQueueHandle<'_,T> { } impl ConcurrentQueue for MoodyCamelCppQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { MoodyCamelCppQueueHandle { q: self, } diff --git a/data_structures/queues/ms_queue/src/lib.rs b/data_structures/queues/ms_queue/src/lib.rs index a80e062..9481db0 100644 --- a/data_structures/queues/ms_queue/src/lib.rs +++ b/data_structures/queues/ms_queue/src/lib.rs @@ -3,7 +3,7 @@ use std::mem::MaybeUninit; use haphazard::{raw::Pointer, AtomicPtr, HazardPointer}; use log::{error, trace}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; struct Node { next: AtomicPtr>, @@ -162,7 +162,7 @@ pub struct MSQueueHandle<'a, T> { } impl ConcurrentQueue for MSQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { MSQueueHandle { queue: self, hp1: HazardPointer::new(), @@ -181,7 +181,7 @@ impl ConcurrentQueue for MSQueue { } } -impl Handle for MSQueueHandle<'_, T> { +impl HandleQueue for MSQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T>{ self.queue.enqueue(&mut self.hp1, item); Ok(()) diff --git a/data_structures/queues/scc2_queue/src/lib.rs b/data_structures/queues/scc2_queue/src/lib.rs index 3950532..93306b9 100644 --- a/data_structures/queues/scc2_queue/src/lib.rs +++ b/data_structures/queues/scc2_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct SCC2Queue { pub queue: scc2::Queue, @@ -9,7 +9,7 @@ pub struct SCC2QueueHandle<'a, T: 'static> { } impl ConcurrentQueue for SCC2Queue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { SCC2QueueHandle { queue: self, } @@ -24,7 +24,7 @@ impl ConcurrentQueue for SCC2Queue { } } -impl Handle for SCC2QueueHandle<'_, T> { +impl HandleQueue for SCC2QueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { let _ = self.queue.queue.push(item); Ok(()) diff --git a/data_structures/queues/scc_queue/src/lib.rs b/data_structures/queues/scc_queue/src/lib.rs index b4987e1..2db110f 100644 --- a/data_structures/queues/scc_queue/src/lib.rs +++ b/data_structures/queues/scc_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct SCCQueue { pub queue: scc::Queue, @@ -9,7 +9,7 @@ pub struct SCCQueueHandle<'a, T: 'static> { } impl ConcurrentQueue for SCCQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { SCCQueueHandle { queue: self, } @@ -24,7 +24,7 @@ impl ConcurrentQueue for SCCQueue { } } -impl Handle for SCCQueueHandle<'_, T> { +impl HandleQueue for SCCQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { let _ = self.queue.queue.push(item); Ok(()) diff --git a/data_structures/queues/seg_queue/src/lib.rs b/data_structures/queues/seg_queue/src/lib.rs index 2b6ac84..704ee5c 100644 --- a/data_structures/queues/seg_queue/src/lib.rs +++ b/data_structures/queues/seg_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use crossbeam::queue::SegQueue; pub struct SegQueueHandle<'a, T>{ @@ -10,7 +10,7 @@ pub struct SQueue{ } impl ConcurrentQueue for SQueue{ - fn register(&self) -> impl Handle{ + fn register(&self) -> impl HandleQueue{ SegQueueHandle{ queue: self, } @@ -27,7 +27,7 @@ impl ConcurrentQueue for SQueue{ } } -impl Handle for SegQueueHandle<'_, T> { +impl HandleQueue for SegQueueHandle<'_, T> { fn push(&mut self, value: T) -> Result<(), T> { self.queue.seg_queue.push(value); Ok(()) diff --git a/data_structures/queues/tz_queue_hp/src/lib.rs b/data_structures/queues/tz_queue_hp/src/lib.rs index 55674e4..f323c6f 100644 --- a/data_structures/queues/tz_queue_hp/src/lib.rs +++ b/data_structures/queues/tz_queue_hp/src/lib.rs @@ -1,7 +1,7 @@ #[allow(unused_imports)] use log::{debug, trace}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use std::{fmt::{Debug, Display}, sync::atomic::{AtomicUsize, Ordering}}; use haphazard::HazardPointer; @@ -198,7 +198,7 @@ impl ConcurrentQueue for TZQueue { fn get_id(&self) -> String { String::from("tz_queue_hp") } - fn register(&self) -> impl benchmark_core::traits::Handle { + fn register(&self) -> impl benchmark_core::traits::HandleQueue { TZQueueHandle { q: self, hp1: HazardPointer::new(), @@ -211,7 +211,7 @@ struct TZQueueHandle<'a, T: Copy> { hp1: HazardPointer<'static>, } -impl Handle for TZQueueHandle<'_, T> { +impl HandleQueue for TZQueueHandle<'_, T> { fn pop(&mut self) -> Option { self.q.dequeue(&mut self.hp1) } diff --git a/data_structures/queues/tz_queue_leak/src/lib.rs b/data_structures/queues/tz_queue_leak/src/lib.rs index 000f9fb..2ef47d0 100644 --- a/data_structures/queues/tz_queue_leak/src/lib.rs +++ b/data_structures/queues/tz_queue_leak/src/lib.rs @@ -1,7 +1,7 @@ #[allow(unused_imports)] use log::{debug, trace}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use std::{fmt::{Debug, Display}, sync::atomic::{AtomicPtr, AtomicUsize, Ordering}}; #[derive(Copy, Clone, Debug)] @@ -189,7 +189,7 @@ impl ConcurrentQueue for TZQueue { fn get_id(&self) -> String { String::from("tz_queue") } - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { TZQueueHandle { q: self } @@ -200,7 +200,7 @@ struct TZQueueHandle<'a, T: Copy> { q: &'a TZQueue, } -impl Handle for TZQueueHandle<'_, T> { +impl HandleQueue for TZQueueHandle<'_, T> { fn pop(&mut self) -> Option { self.q.dequeue() } diff --git a/data_structures/queues/unbounded_concurrent_queue/src/lib.rs b/data_structures/queues/unbounded_concurrent_queue/src/lib.rs index 472f5ea..450c984 100644 --- a/data_structures/queues/unbounded_concurrent_queue/src/lib.rs +++ b/data_structures/queues/unbounded_concurrent_queue/src/lib.rs @@ -1,7 +1,7 @@ use concurrent_queue::PushError; use log::warn; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct UnboundedCQueue { q: concurrent_queue::ConcurrentQueue, @@ -12,7 +12,7 @@ pub struct UnboundedCQueueHandle<'a, T> { } impl ConcurrentQueue for UnboundedCQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { UnboundedCQueueHandle { queue: self, } @@ -27,7 +27,7 @@ impl ConcurrentQueue for UnboundedCQueue { } } -impl Handle for UnboundedCQueueHandle<'_, T> { +impl HandleQueue for UnboundedCQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T>{ if let Err(err) = self.queue.q.push(item) { let i = match err { diff --git a/data_structures/queues/wf_queue/src/lib.rs b/data_structures/queues/wf_queue/src/lib.rs index 2c3ff6c..c66cc43 100644 --- a/data_structures/queues/wf_queue/src/lib.rs +++ b/data_structures/queues/wf_queue/src/lib.rs @@ -1,5 +1,5 @@ use wfqueue_upstream::{Queueable, WfQueue}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct WFQueueHandle<'a, T> { queue: &'a WFQueue @@ -13,7 +13,7 @@ impl ConcurrentQueue for WFQueue where Box: Queueable { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { WFQueueHandle { queue: self, } @@ -30,7 +30,7 @@ where } } -impl Handle for WFQueueHandle<'_, T> +impl HandleQueue for WFQueueHandle<'_, T> where Box: Queueable { @@ -49,7 +49,7 @@ where #[cfg(test)] mod tests { - use super::{ConcurrentQueue, Handle, WFQueue}; + use super::{ConcurrentQueue, HandleQueue, WFQueue}; // #[test] // fn create_bq() { diff --git a/data_structures/stacks/lockfree_stack/src/lib.rs b/data_structures/stacks/lockfree_stack/src/lib.rs index 5b01652..59fb756 100644 --- a/data_structures/stacks/lockfree_stack/src/lib.rs +++ b/data_structures/stacks/lockfree_stack/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct LockfreeStack{ pub lfs: lockfree::stack::Stack } @@ -8,7 +8,7 @@ pub struct LockFreeStacKHandle<'a, T> { } impl ConcurrentQueue for LockfreeStack { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { LockFreeStacKHandle{ stack: self, } @@ -23,7 +23,7 @@ impl ConcurrentQueue for LockfreeStack { } } -impl Handle for LockFreeStacKHandle<'_, T>{ +impl HandleQueue for LockFreeStacKHandle<'_, T>{ fn push(&mut self, item: T) -> Result<(), T>{ self.stack.lfs.push(item); Ok(()) diff --git a/data_structures/stacks/scc2_stack/src/lib.rs b/data_structures/stacks/scc2_stack/src/lib.rs index d74c896..0521198 100644 --- a/data_structures/stacks/scc2_stack/src/lib.rs +++ b/data_structures/stacks/scc2_stack/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct SCC2Stack { pub queue: scc2::Stack, @@ -9,7 +9,7 @@ pub struct SCC2StackHandle<'a, T: 'static> { } impl ConcurrentQueue for SCC2Stack { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { SCC2StackHandle { queue: self, } @@ -24,7 +24,7 @@ impl ConcurrentQueue for SCC2Stack { } } -impl Handle for SCC2StackHandle<'_, T> { +impl HandleQueue for SCC2StackHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { let _ = self.queue.queue.push(item); Ok(()) diff --git a/data_structures/stacks/scc_stack/src/lib.rs b/data_structures/stacks/scc_stack/src/lib.rs index 561bef8..518f4e8 100644 --- a/data_structures/stacks/scc_stack/src/lib.rs +++ b/data_structures/stacks/scc_stack/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct SCCStack { pub queue: scc::Stack, @@ -9,7 +9,7 @@ pub struct SCCStackHandle<'a, T: 'static> { } impl ConcurrentQueue for SCCStack { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { SCCStackHandle { queue: self, } @@ -24,7 +24,7 @@ impl ConcurrentQueue for SCCStack { } } -impl Handle for SCCStackHandle<'_, T> { +impl HandleQueue for SCCStackHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { let _ = self.queue.queue.push(item); Ok(()) diff --git a/readme.md b/readme.md index 3da7f91..e38f147 100644 --- a/readme.md +++ b/readme.md @@ -112,7 +112,7 @@ Your queue will have to implement the traits found in `src/traits.rs` so that th /// The required queue trait. pub trait ConcurrentQueue { /// Returns a thread-local handle for the queue. - fn register(&self) -> impl Handle; + fn register(&self) -> impl HandleQueue; /// Returns the name of the queue. fn get_id(&self) -> String; @@ -123,7 +123,7 @@ pub trait ConcurrentQueue { } /// The required queue handle trait. -pub trait Handle { +pub trait HandleQueue { /// Pushes an item to the queue. /// If it fails, returns the item pushed. fn push(&mut self, item: T) -> Result<(), T>; @@ -252,7 +252,7 @@ Now all that is left is to create the Rust queue files. Create `lib.rs` and `mai #![allow(non_camel_case_types)] #![allow(non_snake_case)] -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; // Include the generated bindings include!(concat!(env!("OUT_DIR"), "/bindings.rs")); @@ -297,7 +297,7 @@ struct YourQueueHandle<'a,T> { pub q: &'a YourCppQueue } -impl Handle for YourCppQueueHandle<'_,T> { +impl HandleQueue for YourCppQueueHandle<'_,T> { fn push(&mut self, item: T) -> Result<(), T> { let ptr: *mut std::ffi::c_void = Box::::into_raw(Box::new(item)) as *mut std::ffi::c_void; match self.q.push(ptr) { @@ -318,7 +318,7 @@ impl Handle for YourCppQueueHandle<'_,T> { } impl ConcurrentQueue for YourCppQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { YourCppQueueHandle { q: self, } From eac4befecc489346b5347ab47e80cd305c7839e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:37:24 +0100 Subject: [PATCH 09/16] Add priority queue data structure --- Cargo.toml | 3 +- benchmark_core/src/traits.rs | 21 +++ .../basic_priority_queue/Cargo.toml | 14 ++ .../basic_priority_queue/src/lib.rs | 150 ++++++++++++++++++ .../basic_priority_queue/src/main.rs | 23 +++ 5 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 data_structures/priority_queues/basic_priority_queue/Cargo.toml create mode 100644 data_structures/priority_queues/basic_priority_queue/src/lib.rs create mode 100644 data_structures/priority_queues/basic_priority_queue/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 701926c..429c253 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,8 @@ members = [ "data_structures/queues/seg_queue", "data_structures/queues/tz_queue_leak", "data_structures/queues/tz_queue_hp", - "data_structures/queues/wf_queue", + "data_structures/queues/wf_queue", + "data_structures/priority_queues/basic_priority_queue", ] [workspace.dependencies] diff --git a/benchmark_core/src/traits.rs b/benchmark_core/src/traits.rs index 3897a46..9d4b437 100644 --- a/benchmark_core/src/traits.rs +++ b/benchmark_core/src/traits.rs @@ -17,3 +17,24 @@ pub trait HandleQueue { /// Pops an item from the queue. fn pop(&mut self) -> Option; } + +/// Trait that all priority queues need to implement +pub trait ConcurrentPriorityQueue { + /// Returns a handle that exposes the priority queue API + fn register(&self) -> impl HandlePriorityQueue; + /// Returns the name of the queue. + fn get_id(&self) -> String; + /// Used to create a new queue. + /// `size` is discarded for unbounded queues. + fn new(size: usize) -> Self; +} + +/// Trait that exposes the correct API for priority queues +pub trait HandlePriorityQueue { + /// Inserts an item into the priority queue. + /// In case of failure, returns the item and priority that failed to insert. + fn insert(&mut self, priority: P, item: T) -> Result<(), (P, T)>; + /// Deletes the minimum item from the queue + /// Returns nothing if the queue is empty + fn delete_min(&mut self) -> Option; +} diff --git a/data_structures/priority_queues/basic_priority_queue/Cargo.toml b/data_structures/priority_queues/basic_priority_queue/Cargo.toml new file mode 100644 index 0000000..e7cc65b --- /dev/null +++ b/data_structures/priority_queues/basic_priority_queue/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "basic_priority_queue" +version = "0.1.0" +edition = "2021" + +[dependencies] +benchmark_core = { path = "../../../benchmark_core" } +log = { workspace = true } +env_logger = { workspace = true, optional=true } + +[features] +default = ["log/release_max_level_info", "dep:env_logger"] +verbose-release = ["log/release_max_level_trace", "dep:env_logger"] +silent-release = ["log/release_max_level_off"] diff --git a/data_structures/priority_queues/basic_priority_queue/src/lib.rs b/data_structures/priority_queues/basic_priority_queue/src/lib.rs new file mode 100644 index 0000000..3e3c72e --- /dev/null +++ b/data_structures/priority_queues/basic_priority_queue/src/lib.rs @@ -0,0 +1,150 @@ +use benchmark_core::traits::{ConcurrentPriorityQueue, HandlePriorityQueue}; +use std::cmp::{Ordering, Reverse}; +use std::{collections::binary_heap::BinaryHeap, sync::Mutex}; + +pub struct KeyValuePair { + key: Reverse

, + item: T, +} + +impl KeyValuePair { + pub fn new(key: P, item: T) -> Self { + Self { + key: Reverse(key), + item, + } + } +} + +impl Ord for KeyValuePair { + fn cmp(&self, other: &Self) -> Ordering { + self.key.cmp(&other.key) + } +} + +impl PartialOrd for KeyValuePair { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialEq for KeyValuePair { + fn eq(&self, other: &Self) -> bool { + self.key == other.key + } +} + +impl Eq for KeyValuePair {} + +pub struct BinHeapWrap { + bin_heap: Mutex>>, +} + +impl BinHeapWrap { + pub fn delete_min(&self) -> Option> { + let mut q = self.bin_heap.lock().unwrap(); + q.pop() + } + + pub fn insert(&self, item: KeyValuePair) { + let mut q = self.bin_heap.lock().unwrap(); + q.push(item); + } + + pub fn is_empty(&self) -> bool { + self.bin_heap.lock().unwrap().is_empty() + } + + pub fn new() -> Self { + BinHeapWrap { + bin_heap: Mutex::new(BinaryHeap::new()), + } + } +} + +impl Default for BinHeapWrap { + fn default() -> Self { + Self::new() + } +} + +pub struct BasicPriorityQueue { + pub basic_priority_queue: BinHeapWrap, +} + +pub struct BasicPriorityQueueHandle<'a, P: Ord, T> { + priority_queue: &'a BasicPriorityQueue, +} + +impl ConcurrentPriorityQueue for BasicPriorityQueue { + fn register(&self) -> impl HandlePriorityQueue { + BasicPriorityQueueHandle { + priority_queue: self, + } + } + fn get_id(&self) -> String { + String::from("basic_priority_queue") + } + fn new(_size: usize) -> Self { + BasicPriorityQueue { + basic_priority_queue: BinHeapWrap::::new(), + } + } +} + +impl HandlePriorityQueue + for BasicPriorityQueueHandle<'_, P, T> +{ + fn insert(&mut self, priority: P, item: T) -> Result<(), (P, T)> { + let kv_pair = KeyValuePair::new(priority, item); + self.priority_queue.basic_priority_queue.insert(kv_pair); + Ok(()) + } + fn delete_min(&mut self) -> Option { + match self.priority_queue.basic_priority_queue.delete_min() { + Some(kv_pair) => Some(kv_pair.item), + None => None, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn create_basic_priority_queue() { + let pq: BasicPriorityQueue = BasicPriorityQueue { + basic_priority_queue: BinHeapWrap::new(), + }; + pq.basic_priority_queue.insert(KeyValuePair::new(1, 10)); + assert_eq!(pq.basic_priority_queue.delete_min().unwrap().item, 10); + } + + #[test] + fn register_basic_priority_queue() { + let pq = BasicPriorityQueue::::new(0); + let mut handle = pq.register(); + handle.insert(1, 10).unwrap(); + assert_eq!(handle.delete_min().unwrap(), 10); + } + + #[test] + fn test_order_basic_priority_queue() { + let pq = BasicPriorityQueue::::new(0); + + let mut handle = pq.register(); + assert_eq!(handle.insert(5, 50), Ok(())); + assert_eq!(handle.insert(4, 40), Ok(())); + assert_eq!(handle.insert(1, 10), Ok(())); + assert_eq!(handle.insert(2, 20), Ok(())); + assert_eq!(handle.insert(3, 30), Ok(())); + + assert_eq!(handle.delete_min(), Some(10)); + assert_eq!(handle.delete_min(), Some(20)); + assert_eq!(handle.delete_min(), Some(30)); + assert_eq!(handle.delete_min(), Some(40)); + assert_eq!(handle.delete_min(), Some(50)); + assert_eq!(handle.delete_min(), None); + } +} diff --git a/data_structures/priority_queues/basic_priority_queue/src/main.rs b/data_structures/priority_queues/basic_priority_queue/src/main.rs new file mode 100644 index 0000000..b78187a --- /dev/null +++ b/data_structures/priority_queues/basic_priority_queue/src/main.rs @@ -0,0 +1,23 @@ +use log::*; +// use benchmark_core::benchmarks::priority_queue_benchmarks::benchmark_priority_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + // match benchmark_priority_queue::>("basic_priority_queue") { + // Ok(_) => println!("Benchmark done."), + // Err(e) => { + // eprintln!("Benchmark received error: {}", e); + // println!("Benchmark exiting due to error."); + // } + // } + + println!("Hello from Basic Priority Queue Main"); +} From 2c8988e2e0214c68ba805031c85402f6d949a904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Wed, 4 Feb 2026 16:07:40 +0100 Subject: [PATCH 10/16] Add is_empty() and min() functions to the PriorityQueue trait --- benchmark_core/src/traits.rs | 8 ++++++++ .../basic_priority_queue/src/lib.rs | 17 +++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/benchmark_core/src/traits.rs b/benchmark_core/src/traits.rs index 9d4b437..2563075 100644 --- a/benchmark_core/src/traits.rs +++ b/benchmark_core/src/traits.rs @@ -37,4 +37,12 @@ pub trait HandlePriorityQueue { /// Deletes the minimum item from the queue /// Returns nothing if the queue is empty fn delete_min(&mut self) -> Option; + /// Checks if the priority queue is empty + fn is_empty(&mut self) -> bool; + /// Peeks at the smallest key-value pair but doesn't remove it from the + /// queue + /// Returns an enum wrapped in a Some() of the form (key, value) if there + /// exists a smallest value + /// Returns None if there is no item in the queue + fn min(&mut self) -> Option<(&P, &T)>; } diff --git a/data_structures/priority_queues/basic_priority_queue/src/lib.rs b/data_structures/priority_queues/basic_priority_queue/src/lib.rs index 3e3c72e..f59b7c8 100644 --- a/data_structures/priority_queues/basic_priority_queue/src/lib.rs +++ b/data_structures/priority_queues/basic_priority_queue/src/lib.rs @@ -55,6 +55,10 @@ impl BinHeapWrap { self.bin_heap.lock().unwrap().is_empty() } + pub fn min(&self) -> Option<&KeyValuePair> { + self.bin_heap.lock().unwrap().peek() + } + pub fn new() -> Self { BinHeapWrap { bin_heap: Mutex::new(BinaryHeap::new()), @@ -95,17 +99,26 @@ impl ConcurrentPriorityQueue for BasicPriorityQueue { impl HandlePriorityQueue for BasicPriorityQueueHandle<'_, P, T> { - fn insert(&mut self, priority: P, item: T) -> Result<(), (P, T)> { + fn insert(&self, priority: P, item: T) -> Result<(), (P, T)> { let kv_pair = KeyValuePair::new(priority, item); self.priority_queue.basic_priority_queue.insert(kv_pair); Ok(()) } - fn delete_min(&mut self) -> Option { + fn delete_min(&self) -> Option { match self.priority_queue.basic_priority_queue.delete_min() { Some(kv_pair) => Some(kv_pair.item), None => None, } } + fn is_empty(&self) -> bool { + self.priority_queue.basic_priority_queue.is_empty() + } + fn min(&self) -> Option<(&P, &T)> { + match self.priority_queue.basic_priority_queue.min() { + Some(kv_pair) => Some((kv_pair.key, kv_pair.item)), + None => None, + } + } } #[cfg(test)] From ada575438be848f77c490192d60a2fd5f9839660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Wed, 4 Feb 2026 22:32:16 +0100 Subject: [PATCH 11/16] Add benchmarks for priority queue and restructure argument parsing --- benchmark_core/src/arguments.rs | 115 +++++-- .../src/benchmarks/benchmark_helpers.rs | 72 +++-- .../benchmarks/priority_queue_benchmarks.rs | 155 +++++++++ .../priority_queue_benchmarks/prod_con.rs | 305 ++++++++++++++++++ .../src/benchmarks/queue_benchmarks.rs | 85 +++-- .../src/benchmarks/queue_benchmarks/bfs.rs | 10 +- .../benchmarks/queue_benchmarks/enq_deq.rs | 41 ++- .../queue_benchmarks/enq_deq_pairs.rs | 29 +- .../benchmarks/queue_benchmarks/prod_con.rs | 18 +- benchmark_core/src/benchmarks/test_helpers.rs | 87 ++++- benchmark_core/src/traits.rs | 6 - .../basic_priority_queue/src/lib.rs | 16 +- .../basic_priority_queue/src/main.rs | 23 +- readme.md | 5 + 14 files changed, 836 insertions(+), 131 deletions(-) create mode 100644 benchmark_core/src/benchmarks/priority_queue_benchmarks/prod_con.rs diff --git a/benchmark_core/src/arguments.rs b/benchmark_core/src/arguments.rs index 15f5ac2..c888fa5 100644 --- a/benchmark_core/src/arguments.rs +++ b/benchmark_core/src/arguments.rs @@ -7,18 +7,12 @@ pub struct Args { /// Duration of each benchmark #[arg(short, long, default_value_t = 10)] pub time_limit: u64, - /// Attemps to only use on socket. Specific for the developers test environment. + /// Attemps to only use one socket. Specific for the developers test environment. #[arg(short, long, default_value_t = true, action = ArgAction::SetFalse)] pub one_socket: bool, /// How many times the chosen benchmark should be run. #[arg(short, long, default_value_t = 1)] pub iterations: u32, - /// Count empty pop operations. Off by default. - #[arg(short, long, default_value_t = false)] - pub empty_pops: bool, - /// Set the size of the bounded queues. - #[arg(short, long, default_value_t = 10000)] - pub queue_size: u32, /// Set the amount of floating point numbers generated between each operation. Default is 10. #[arg(short, long, default_value_t = 10)] pub delay: u64, @@ -27,11 +21,11 @@ pub struct Args { pub path_output: String, /// Choose which benchmark to run. #[command(subcommand)] - pub benchmark: QueueBenchmarks, + pub benchmark: BenchmarkTypes, /// If set to true, benchmark will output to stdout instead of to files. #[arg(long = "write-stdout", default_value_t = false)] pub write_to_stdout: bool, - /// Prefill the queue with values before running the benchmark. + /// Prefill the data structure with values before running the benchmark. #[arg(short, long, default_value_t = 0)] pub prefill_amount: u64, /// Write benchmark configuration and hardware info to a separate file. @@ -45,18 +39,39 @@ pub struct Args { /// Possible benchmark types. #[derive(Subcommand, Debug)] +pub enum BenchmarkTypes { + Queue(QueueArgs), + PriorityQueue(PriorityQueueArgs), +} + +/// Arguments for the Queue benchmark type +#[derive(ClapArgs, Debug, Clone)] +pub struct QueueArgs { + /// Count empty pop operations. Off by default. + #[arg(short, long, default_value_t = false)] + pub empty_pops: bool, + /// Set the size of the bounded queues. + #[arg(short, long, default_value_t = 10000)] + pub queue_size: u32, + /// The runner to use for the benchmark + #[command(subcommand)] + pub benchmark_runner: QueueBenchmarks, +} + +/// Benchmark runners for queues. +#[derive(Subcommand, Debug, Clone)] pub enum QueueBenchmarks { /// ProdCon throughput test. Decide amount of producers and consumers using flags. - ProdCon(ProdConArgs), + ProdCon(QueueProdConArgs), /// A test where each thread performs both consume and produce based on a random floating point /// value. Spread is decided using the `--spread` flag. - EnqDeq(EnqDeqArgs), - EnqDeqPairs(EnqDeqPairsArgs), - BFS(BFSArgs), + EnqDeq(QueueEnqDeqArgs), + EnqDeqPairs(QueueEnqDeqPairsArgs), + BFS(QueueBFSArgs), } -#[derive(ClapArgs, Debug)] -pub struct ProdConArgs { +#[derive(ClapArgs, Debug, Clone)] +pub struct QueueProdConArgs { /// Amount of producers to be used for basic throughput test. #[arg(short, long, default_value_t = 20)] pub producers: usize, @@ -64,8 +79,9 @@ pub struct ProdConArgs { #[arg(short, long, default_value_t = 20)] pub consumers: usize, } -#[derive(ClapArgs, Debug)] -pub struct EnqDeqArgs { + +#[derive(ClapArgs, Debug, Clone)] +pub struct QueueEnqDeqArgs { /// Set the thread count for the pingpong benchmark. #[arg(long = "thread-count", default_value_t = 20)] pub thread_count: usize, @@ -74,14 +90,16 @@ pub struct EnqDeqArgs { #[arg(long = "spread", default_value_t = 0.5)] pub spread: f64, } -#[derive(ClapArgs, Debug)] -pub struct EnqDeqPairsArgs { + +#[derive(ClapArgs, Debug, Clone)] +pub struct QueueEnqDeqPairsArgs { /// Set the thread count for the pingpong benchmark. #[arg(long = "thread-count", default_value_t = 20)] pub thread_count: usize, } -#[derive(ClapArgs, Debug)] -pub struct BFSArgs { + +#[derive(ClapArgs, Debug, Clone)] +pub struct QueueBFSArgs { #[arg(short, long, default_value_t = 20)] pub thread_count: usize, #[arg(short, long)] @@ -89,16 +107,45 @@ pub struct BFSArgs { #[arg(short, long, default_value_t = false)] pub no_verify: bool, } + +/// Arguments for the PriorityQueue benchmark type +#[derive(ClapArgs, Debug, Clone)] +pub struct PriorityQueueArgs { + /// Set the size of the bounded queues. + #[arg(short, long, default_value_t = 10000)] + pub queue_size: u32, + /// The runner to use for the benchmark + #[command(subcommand)] + pub benchmark_runner: PriorityQueueBenchmarks, +} + +/// Benchmark runners for priority queues. +#[derive(Subcommand, Debug, Clone)] +pub enum PriorityQueueBenchmarks { + /// Producer Consumer throughput test. Decide amount of producers and consumers using flags. + ProdCon(PQProdConArgs), +} + +#[derive(ClapArgs, Debug, Clone)] +pub struct PQProdConArgs { + /// Amount of producers to be used for basic throughput test. + #[arg(short, long, default_value_t = 20)] + pub producers: usize, + /// Amount of consumers to be used for basic throughput test. + #[arg(short, long, default_value_t = 20)] + pub consumers: usize, +} + /// This is used to write the benchmark type to the output. /// That is why the arguments are discarded. impl Display for QueueBenchmarks { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - QueueBenchmarks::ProdCon(_) => write!(f, "ProdCon"), - QueueBenchmarks::EnqDeq(_) => write!(f, "EnqDeq"), + QueueBenchmarks::ProdCon(_) => write!(f, "ProdCon"), + QueueBenchmarks::EnqDeq(_) => write!(f, "EnqDeq"), QueueBenchmarks::EnqDeqPairs(_) => write!(f, "EnqDeqPairs"), // #[cfg(feature = "bfs")] - QueueBenchmarks::BFS(_) => write!(f, "BFS"), + QueueBenchmarks::BFS(_) => write!(f, "BFS"), } } } @@ -108,7 +155,6 @@ impl Display for Args { writeln!(f, "Time limit: {}", self.time_limit)?; writeln!(f, "One socket?: {}", self.one_socket)?; writeln!(f, "Iterations: {}", self.iterations)?; - writeln!(f, "Queue size: {}", self.queue_size)?; writeln!(f, "Delay: {}", self.delay)?; writeln!(f, "Output path: {}", self.path_output)?; writeln!(f, "Benchmark: {:?}", self.benchmark)?; @@ -118,6 +164,13 @@ impl Display for Args { } } +impl Display for BenchmarkTypes { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "Benchmark type: {:?}", self)?; + Ok(()) + } +} + /// Implemented so that tests are easier to write. impl Default for Args { fn default() -> Self { @@ -126,13 +179,15 @@ impl Default for Args { time_limit: 1, one_socket: true, iterations: 1, - empty_pops: false, - queue_size: 10000, delay: 10, path_output: "".to_string(), - benchmark: QueueBenchmarks::ProdCon(ProdConArgs { - producers: 5, - consumers: 5, + benchmark: BenchmarkTypes::Queue(QueueArgs { + empty_pops: false, + queue_size: 10000, + benchmark_runner: QueueBenchmarks::ProdCon(QueueProdConArgs { + producers: 5, + consumers: 5, + }), }), write_to_stdout: true, print_info: false, diff --git a/benchmark_core/src/benchmarks/benchmark_helpers.rs b/benchmark_core/src/benchmarks/benchmark_helpers.rs index 224089e..4b75837 100644 --- a/benchmark_core/src/benchmarks/benchmark_helpers.rs +++ b/benchmark_core/src/benchmarks/benchmark_helpers.rs @@ -1,8 +1,8 @@ -#[cfg(feature = "memory_tracking")] -use jemalloc_ctl::{epoch, stats}; use crate::arguments::Args; #[cfg(feature = "memory_tracking")] use crate::traits::ConcurrentQueue; +#[cfg(feature = "memory_tracking")] +use jemalloc_ctl::{epoch, stats}; use log::{debug, error, trace}; use std::fs::OpenOptions; use std::io::Write; @@ -20,16 +20,15 @@ pub struct BenchConfig { } #[cfg(feature = "memory_tracking")] -pub fn create_mem_tracking_thread( +pub fn create_mem_tracking_thread( bench_conf: &BenchConfig, _current_iteration: u32, test_q: &Q, - _done: &std::sync::Arc) --> Result>, std::io::Error> + _done: &std::sync::Arc, +) -> Result>, std::io::Error> where - Q: ConcurrentQueue + Q: ConcurrentQueue, { - use std::sync::atomic::Ordering; // TODO: Check if core stuff is possible here as well. // let mut core : CoreId = core_iter.next().unwrap(); @@ -47,7 +46,10 @@ where // Create file if printing to stdout is disabled let top_line = "Memory Allocated,Queuetype,Benchmark,Test ID,Iteration"; let mut memfile = if !to_stdout { - let output_filename = format!("{}/mem{}", bench_conf.args.path_output, bench_conf.date_time); + let output_filename = format!( + "{}/mem{}", + bench_conf.args.path_output, bench_conf.date_time + ); let mut file = OpenOptions::new() .append(true) .create(true) @@ -66,7 +68,7 @@ where // Spawn thread to check total memory allocated every 50ms let interval = bench_conf.args.memory_tracking_interval; debug!("Spawning memory thread."); - Ok(std::thread::spawn(move|| -> Result<(), std::io::Error>{ + Ok(std::thread::spawn(move || -> Result<(), std::io::Error> { while !_done.load(Ordering::Relaxed) { // Update stats if let Err(e) = epoch::advance() { @@ -75,7 +77,14 @@ where // Get allocated bytes let allocated = stats::allocated::read().unwrap(); - let output = format!("{},{},{},{},{}", allocated, queue_type, bench_type, &benchmark_id, _current_iteration); + let output = format!( + "{},{},{},{},{}", + allocated, + queue_type, + bench_type, + &benchmark_id, + _current_iteration + ); match &mut memfile { Some(file) => writeln!(file, "{}", output)?, @@ -96,7 +105,7 @@ pub fn calc_fairness(ops_per_thread: Vec) -> f64 { let length: f64 = ops_per_thread.len() as f64; debug!("The vector {:?}", ops_per_thread); - debug!("Sum: {}, Length: {}",sum, length); + debug!("Sum: {}, Length: {}", sum, length); // The thread that does the least amount of ops let minop: f64 = match ops_per_thread.iter().min() { @@ -118,20 +127,27 @@ pub fn calc_fairness(ops_per_thread: Vec) -> f64 { }; trace!("Maxop fairness: {}", maxop); - let fairness: f64 = f64::min((length * minop) / sum as f64, sum as f64 / (length * maxop)); + let fairness: f64 = + f64::min((length * minop) / sum as f64, sum as f64 / (length * maxop)); debug!("Calculated fairness: {}", fairness); fairness } /// Function to print the specifications of the hardware used and the benchmnark configs that ran -pub fn print_info(queue: String, bench_conf: &BenchConfig) -> Result<(), std::io::Error>{ +pub fn print_info( + queue: String, + bench_conf: &BenchConfig, +) -> Result<(), std::io::Error> { // Create file if printing to stdout is disabled if bench_conf.args.write_to_stdout { return Ok(()); } let memfile = { - let output_filename = format!("{}/info{}.txt", bench_conf.args.path_output, bench_conf.benchmark_id); + let output_filename = format!( + "{}/info{}.txt", + bench_conf.args.path_output, bench_conf.benchmark_id + ); let file = OpenOptions::new() .append(true) .create(true) @@ -141,7 +157,11 @@ pub fn print_info(queue: String, bench_conf: &BenchConfig) -> Result<(), std::io let num: u64 = 1000; let sys = System::new_all(); if let Some(mut file) = memfile { - writeln!(file, "Benchmark done: {}", bench_conf.args.benchmark)?; + writeln!( + file, + "Benchmark done: {}", + bench_conf.args.benchmark + )?; writeln!(file, "With queue: {}", queue)?; writeln!(file, "Arguments used in test:")?; @@ -149,12 +169,22 @@ pub fn print_info(queue: String, bench_conf: &BenchConfig) -> Result<(), std::io writeln!(file, "Test ran on hardware specs:")?; writeln!(file, "System name: {}", System::name().unwrap())?; - writeln!(file, "System kernel version: {}", System::kernel_version().unwrap())?; - writeln!(file, "System OS version: {}", System::os_version().unwrap())?; - writeln!(file, "Total RAM (in GB): {:?}", sys.total_memory()/(num.pow(3)))?; - - } - else { + writeln!( + file, + "System kernel version: {}", + System::kernel_version().unwrap() + )?; + writeln!( + file, + "System OS version: {}", + System::os_version().unwrap() + )?; + writeln!( + file, + "Total RAM (in GB): {:?}", + sys.total_memory() / (num.pow(3)) + )?; + } else { eprintln!("Error producing info file") } Ok(()) diff --git a/benchmark_core/src/benchmarks/priority_queue_benchmarks.rs b/benchmark_core/src/benchmarks/priority_queue_benchmarks.rs index e69de29..0b115bc 100644 --- a/benchmark_core/src/benchmarks/priority_queue_benchmarks.rs +++ b/benchmark_core/src/benchmarks/priority_queue_benchmarks.rs @@ -0,0 +1,155 @@ +#[allow(unused_imports)] +use crate::arguments::{ + Args, BenchmarkTypes, PriorityQueueArgs, PriorityQueueBenchmarks, +}; +use crate::benchmarks::benchmark_helpers; +#[allow(unused_imports)] +use crate::traits::{ConcurrentPriorityQueue, HandlePriorityQueue}; +use chrono::Local; +use clap::Parser; +#[allow(unused_imports)] +use log::{self, debug, error, info}; +use std::collections::hash_map::DefaultHasher; +use std::fs::OpenOptions; +use std::hash::{Hash, Hasher}; +use std::io::Write; +#[allow(unused_imports)] +use std::sync::atomic::AtomicBool; + +pub mod prod_con; + +/// Create the queue, and run the selected benchmark a set of times +pub fn benchmark_priority_queue( + queue_name: &str, +) -> Result<(), std::io::Error> +where + Q: ConcurrentPriorityQueue + Send, + T: Default, + for<'a> &'a Q: Send, +{ + // Setup output and parse arguments + let SetupResult { + bench_conf, + pq_conf, + .. + } = setup_benchmark()?; + let bench_conf = &bench_conf; + + // Create a runner lambda for the different benchmarks, mainly needed for eg. BFS to load graph and so on + let mut runner: Box< + dyn FnMut( + Q, + &benchmark_helpers::BenchConfig, + ) -> Result<(), std::io::Error>, + > = match &pq_conf.benchmark_runner { + PriorityQueueBenchmarks::ProdCon(_) => { + Box::new(move |q, bench_conf| { + prod_con::benchmark_prod_con(q, bench_conf) + }) + } + }; + + for _current_iteration in 0..bench_conf.args.iterations { + // Create the queue. + let test_q: Q = Q::new(pq_conf.queue_size as usize); + + // Start memory tracking (if enabled) + #[cfg(feature = "memory_tracking")] + let (done, mem_thread_handle) = { + let done = + std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); + let handle = benchmark_helpers::create_mem_tracking_thread( + bench_conf, + _current_iteration, + &test_q, + &done, + )?; + (done, handle) + }; + + // Execute the benchmark + runner(test_q, bench_conf)?; + + // Join the thread again + debug!("Queue should have been dropped now."); + + // Stop memory tracking (if enabled) + #[cfg(feature = "memory_tracking")] + { + use std::sync::atomic::Ordering; + debug!("Joining memory thread."); + done.store(true, Ordering::Relaxed); + if let Err(e) = mem_thread_handle.join().unwrap() { + log::error!("Couldn't join memory tracking thread: {}", e); + } + } + } + + if bench_conf.args.print_info { + benchmark_helpers::print_info(queue_name.to_string(), bench_conf)?; + } + + Ok(()) +} + +pub struct SetupResult { + pub bench_conf: benchmark_helpers::BenchConfig, + pub pq_conf: PriorityQueueArgs, + pub columns: String, // Optional, but alreadyy written (TODO: have a stream of some sort here) +} + +/// Set up the actual benchmark. +/// +/// All work unrelated to the chosen benchmark is done here. +pub fn setup_benchmark() -> Result { + let args = crate::arguments::Args::parse(); + + let pq_args = match &args.benchmark { + BenchmarkTypes::PriorityQueue(queue_args) => queue_args.clone(), + _ => panic!( + "Trying to run a queue benchmark with another benchmark type" + ), + }; + + let date_time = Local::now().format("%Y%m%d%H%M%S").to_string(); + // Create benchmark hashed id + let benchmark_id = { + let mut hasher = DefaultHasher::new(); + date_time.hash(&mut hasher); + format!("{:x}", hasher.finish()) + }; + + debug!("Benchmark ID: {}", benchmark_id); + debug!("Arguments: {:?}", args); + + // Create dir if it doesnt already exist. + if !std::path::Path::new(&args.path_output).exists() { + std::fs::create_dir(&args.path_output)?; + } + + let output_filename = format!("{}/{}", args.path_output, date_time); + let bench_conf = benchmark_helpers::BenchConfig { + args, + date_time, + benchmark_id, + output_filename, + }; + + let columns = "Throughput,Enqueues,Dequeues,Consumers,Producers,Thread Count,Queuetype,Benchmark,Test ID,Fairness,Spread,Queue Size"; + + if bench_conf.args.write_to_stdout { + println!("{columns}") + } else { + let mut file = OpenOptions::new() + .append(true) + .create(true) + .open(&bench_conf.output_filename)?; + writeln!(file, "{columns}")?; + } + + Ok(SetupResult { + bench_conf, + pq_conf: pq_args, + columns: columns.to_string(), + }) +} diff --git a/benchmark_core/src/benchmarks/priority_queue_benchmarks/prod_con.rs b/benchmark_core/src/benchmarks/priority_queue_benchmarks/prod_con.rs new file mode 100644 index 0000000..8b95288 --- /dev/null +++ b/benchmark_core/src/benchmarks/priority_queue_benchmarks/prod_con.rs @@ -0,0 +1,305 @@ +use core_affinity::CoreId; +use log::{debug, error, info, trace}; +use rand::Rng; +use crate::arguments::{BenchmarkTypes, PriorityQueueBenchmarks}; +use crate::traits::{ConcurrentPriorityQueue, HandlePriorityQueue}; +use crate::benchmarks::benchmark_helpers; +use std::fs::OpenOptions; +use std::io::Write; +use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; +use std::sync::{mpsc, Arc}; + +// TODO(emilbjornlinger): Change benchmark to something reasonable + +/// # Explanation: +/// A simple benchmark that measures the throughput of a queue. +/// Has by default a 10 floating points generated delay between each operation, but this can be changed +/// through flags passed to the program. +/// Benchmark specific flags: +/// * -p Set specified amount of producers +/// * -c Set specified amount of consumers +#[allow(dead_code)] +pub fn benchmark_prod_con(cqueue: C, bench_conf: &benchmark_helpers::BenchConfig) -> Result<(), std::io::Error> +where + C: ConcurrentPriorityQueue, + P: Ord + From, + T: Default, + for<'a> &'a C: Send +{ + let args = match &bench_conf.args.benchmark { + BenchmarkTypes::PriorityQueue(args) => match &args.benchmark_runner { + PriorityQueueBenchmarks::ProdCon(a) => a, + } + _ => panic!(), + }; + + let queue_args = match &bench_conf.args.benchmark { + BenchmarkTypes::PriorityQueue(queue_args) => queue_args.clone(), + _ => panic!( + "Trying to run a queue benchmark with another benchmark type" + ), + }; + + { + debug!("Prefilling priority queue with {} items.", bench_conf.args.prefill_amount); + let mut tmp_handle = cqueue.register(); + for i in 0..bench_conf.args.prefill_amount { + let prio: usize = i.try_into().unwrap(); + let _ = tmp_handle.insert(P::from(prio), Default::default()); + } + } + let producers = args.producers; + let consumers = args.consumers; + + let time_limit: u64 = bench_conf.args.time_limit; + let barrier = Barrier::new(consumers + producers + 1); + let pops = AtomicUsize::new(0); + let pushes = AtomicUsize::new(0); + let done = AtomicBool::new(false); + let (tx, rx) = mpsc::channel(); + info!("Starting throughput benchmark with {} consumer and {} producers", consumers, producers); + + // get cores for fairness of threads + let available_cores: Vec = + core_affinity::get_core_ids().unwrap_or(vec![CoreId { id: 0 }]); + let mut core_iter = available_cores.into_iter().cycle(); + + // Shared atomic bool for when a thread fails + let thread_failed = Arc::new(AtomicBool::new(false)); + + let _ = std::thread::scope(|s| -> Result<(), std::io::Error>{ + let queue = &cqueue; + let pushes = &pushes; + let pops = &pops; + let done = &done; + let barrier = &barrier; + let tx = &tx; + let &consumers = &consumers; + let &producers = &producers; + let is_one_socket = &bench_conf.args.one_socket; + let thread_failed = &thread_failed; + + for i in 0..producers{ + let mut core : CoreId = core_iter.next().unwrap(); + // if is_one_socket is true, make all thread ids even + // (this was used for our testing enviroment to get one socket) + if *is_one_socket { + core = core_iter.next().unwrap(); + } + trace!("Thread: {} Core: {:?}", i, core); + s.spawn(move || { + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + core_affinity::set_for_current(core); + let mut handle = queue.register(); + // push + let mut l_pushes= 0; + let _thread_failed = thread_failed.clone(); // Every thread clones the thread_failed bool + barrier.wait(); + while !done.load(Ordering::Relaxed) { + // NOTE: Maybe we should care about this result? + let _ = handle.insert(P::from(l_pushes), T::default()); + l_pushes += 1; + // Add some delay to simulate real workload + for _ in 0..bench_conf.args.delay { + let _some_num = rand::rng().random::(); + } + } + pushes.fetch_add(l_pushes, Ordering::Relaxed); + // Thread sends its total operations down the channel for fairness calculations + if let Err(e) = tx.send(l_pushes) { + error!("Error sending operations down the channel: {}", e); + }; + })); + // A thread panicked, aborting the benchmark... + if let Err (e) = result { + error!("Thread {} panicked in pushing: {:?}. Aborting benchmark, padding results to zero", i, e); + thread_failed.store(true, Ordering::Relaxed); + done.store(true, Ordering::Relaxed); + } + }); + } + for i in 0..consumers { + let mut core : CoreId = core_iter.next().expect("Core iter error"); + // if is_one_socket is true, make all thread ids even + // (this was used for our testing enviroment to get one socket) + if *is_one_socket { + core = core_iter.next().unwrap(); + } + trace!("Thread: {} Core: {:?}", i, core); + + s.spawn(move || { + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + core_affinity::set_for_current(core); + let mut handle = queue.register(); + // pop + let mut l_pops = 0; + let mut empty_pops = 0; + let _thread_failed = thread_failed.clone(); // Every thread clones the thread_failed bool + barrier.wait(); + // TODO: add empty pops probably to fairness calculations + while !done.load(Ordering::Relaxed) { + match handle.delete_min() { + Some(_) => l_pops += 1, + None => { + // if bench_conf.args.empty_pops { + // l_pops += 1; + // } + empty_pops += 1; + } + } + for _ in 0..bench_conf.args.delay { + let _some_num = rand::rng().random::(); + } + } + pops.fetch_add(l_pops, Ordering::Relaxed); + // Thread sends its total operations down the channel for fairness calculations + if let Err(e) = tx.send(l_pops + empty_pops) { + error!("Error sending operations down the channel: {}", e); + }; + })); + // A thread panicked, aborting the benchmark... + if let Err(e) = result { + error!("Thread {} panicked while popping: {:?}. Aborting benchmark, padding results to zero", i, e); + thread_failed.store(true, Ordering::Relaxed); + done.store(true, Ordering::Relaxed); + } + }); + } + debug!("Waiting for barrier"); + barrier.wait(); + debug!("Done waiting for barrier. Going to sleep."); + std::thread::sleep(std::time::Duration::from_secs(time_limit)); + done.store(true, Ordering::Relaxed); + Ok(()) + }); + drop(tx); + debug!("TX Dropped"); + let pops = pops.into_inner(); + let pushes = pushes.into_inner(); + + // Fairness + // Get total operations per thread + let ops_per_thread = { + let mut vals = vec![]; + for received in rx { + vals.push(received); + }; + vals + }; + // If a thread crashed, pad the results with zero-values + let formatted = if thread_failed.load(Ordering::Relaxed) { + format!("0,0,0,{},{},-1,{},{},{},0,-1,{}", producers, consumers, cqueue.get_id(), bench_conf.args.benchmark, bench_conf.benchmark_id, queue_args.queue_size) + } + else { + let fairness = benchmark_helpers::calc_fairness(ops_per_thread); + format!("{},{},{},{},{},{},{},{},{},{},{},{}", + (pushes + pops) as f64 / time_limit as f64, + pushes, + pops, + consumers, + producers, + -1, + cqueue.get_id(), + bench_conf.args.benchmark, + bench_conf.benchmark_id, + fairness, + -1, + queue_args.queue_size) + }; + if !bench_conf.args.write_to_stdout { + let mut file = OpenOptions::new() + .append(true) + .create(true) + .open(&bench_conf.output_filename)?; + + writeln!(file, "{}", formatted)?; + + } else { + println!("{}", formatted); + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::arguments::{Args, PQProdConArgs, PriorityQueueArgs}; + use crate::benchmarks::test_helpers::test_priority_queue::TestPriorityQueue; + + #[test] + fn run_basic_prod_con() { + let def_args = Args::default(); + let args = Args { + benchmark: BenchmarkTypes::PriorityQueue(PriorityQueueArgs { + queue_size: 10000, + benchmark_runner: PriorityQueueBenchmarks::ProdCon(PQProdConArgs { + producers: 10, + consumers: 10, + }) + }), + ..def_args + }; + let bench_conf = benchmark_helpers::BenchConfig { + args, + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + let queue: TestPriorityQueue = TestPriorityQueue::new(0); + if benchmark_prod_con(queue, &bench_conf).is_err() { + panic!(); + } + } + + #[test] + fn run_basic_with_string() { + let def_args = Args::default(); + let args = Args { + benchmark: BenchmarkTypes::PriorityQueue(PriorityQueueArgs { + queue_size: 10000, + benchmark_runner: PriorityQueueBenchmarks::ProdCon(PQProdConArgs { + producers: 10, + consumers: 10, + }) + }), + ..def_args + }; + let bench_conf = benchmark_helpers::BenchConfig { + args, + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + let queue: TestPriorityQueue = TestPriorityQueue::new(0); + if benchmark_prod_con(queue, &bench_conf).is_err() { + panic!(); + } + } + + #[test] + fn run_basic_with_struct() { + let args = Args { + benchmark: BenchmarkTypes::PriorityQueue(PriorityQueueArgs { + queue_size: 10000, + benchmark_runner: PriorityQueueBenchmarks::ProdCon(PQProdConArgs { + producers: 10, + consumers: 10, + }) + }), + ..Default::default() + }; + let bench_conf = benchmark_helpers::BenchConfig { + args, + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + // TODO(emilbjornlinger): Change this struct + let queue: TestPriorityQueue = TestPriorityQueue::new(0); + if benchmark_prod_con(queue, &bench_conf).is_err() { + panic!(); + } + } +} diff --git a/benchmark_core/src/benchmarks/queue_benchmarks.rs b/benchmark_core/src/benchmarks/queue_benchmarks.rs index 3e38d08..202895d 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks.rs @@ -1,10 +1,10 @@ -use chrono::Local; -use clap::Parser; #[allow(unused_imports)] -use crate::arguments::{Args, QueueBenchmarks}; +use crate::arguments::{Args, BenchmarkTypes, QueueBenchmarks, QueueArgs}; use crate::benchmarks::benchmark_helpers; #[allow(unused_imports)] use crate::traits::{ConcurrentQueue, HandleQueue}; +use chrono::Local; +use clap::Parser; #[allow(unused_imports)] use log::{self, debug, error, info}; use std::collections::hash_map::DefaultHasher; @@ -14,56 +14,68 @@ use std::io::Write; #[allow(unused_imports)] use std::sync::atomic::AtomicBool; -pub mod prod_con; +pub mod bfs; pub mod enq_deq; pub mod enq_deq_pairs; -pub mod bfs; +pub mod prod_con; /// Create the queue, and run the selected benchmark a set of times -pub fn benchmark_queue(queue_name: &str) -> Result<(), std::io::Error> +pub fn benchmark_queue(queue_name: &str) -> Result<(), std::io::Error> where Q: ConcurrentQueue + Send, - for<'a> &'a Q: Send + for<'a> &'a Q: Send, { // Setup output and parse arguments - let SetupResult { bench_conf, .. } = setup_benchmark()?; + let SetupResult { bench_conf, queue_conf, .. } = setup_benchmark()?; let bench_conf = &bench_conf; // Create a runner lambda for the different benchmarks, mainly needed for eg. BFS to load graph and so on - let mut runner: Box Result<(), std::io::Error>> = match &bench_conf.args.benchmark { - QueueBenchmarks::ProdCon(_) => Box::new(move |q, bench_conf| prod_con::benchmark_prod_con(q, bench_conf)), - QueueBenchmarks::EnqDeq(_) => Box::new(move |q, bench_conf| enq_deq::benchmark_enq_deq(q, bench_conf)), - QueueBenchmarks::EnqDeqPairs(_) => Box::new(move |q, bench_conf| enq_deq_pairs::benchmark_enq_deq_pairs(q, bench_conf)), + let mut runner: Box< + dyn FnMut( + Q, + &benchmark_helpers::BenchConfig, + ) -> Result<(), std::io::Error>, + > = match &queue_conf.benchmark_runner { + QueueBenchmarks::ProdCon(_) => Box::new(move |q, bench_conf| { + prod_con::benchmark_prod_con(q, bench_conf) + }), + QueueBenchmarks::EnqDeq(_) => Box::new(move |q, bench_conf| { + enq_deq::benchmark_enq_deq(q, bench_conf) + }), + QueueBenchmarks::EnqDeqPairs(_) => Box::new(move |q, bench_conf| { + enq_deq_pairs::benchmark_enq_deq_pairs(q, bench_conf) + }), QueueBenchmarks::BFS(args) => { - let (graph, seq_ret_vec, start_node) = - bfs::pre_bfs_work( - Q::new(bench_conf.args.queue_size as usize), - &args, - ); - Box::new(move |q, _conf| bfs::benchmark_bfs( - q, - &graph, - bench_conf, - &seq_ret_vec, - start_node + let (graph, seq_ret_vec, start_node) = bfs::pre_bfs_work( + Q::new(queue_conf.queue_size as usize), + &args, + ); + Box::new(move |q, _conf| { + bfs::benchmark_bfs( + q, + &graph, + bench_conf, + &seq_ret_vec, + start_node, ) - ) - }, + }) + } }; for _current_iteration in 0..bench_conf.args.iterations { // Create the queue. - let test_q: Q = Q::new(bench_conf.args.queue_size as usize); + let test_q: Q = Q::new(queue_conf.queue_size as usize); // Start memory tracking (if enabled) #[cfg(feature = "memory_tracking")] let (done, mem_thread_handle) = { - let done = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); + let done = + std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); let handle = benchmark_helpers::create_mem_tracking_thread( bench_conf, _current_iteration, &test_q, - &done + &done, )?; (done, handle) }; @@ -95,6 +107,7 @@ where pub struct SetupResult { pub bench_conf: benchmark_helpers::BenchConfig, + pub queue_conf: QueueArgs, pub columns: String, // Optional, but alreadyy written (TODO: have a stream of some sort here) } @@ -103,6 +116,14 @@ pub struct SetupResult { /// All work unrelated to the chosen benchmark is done here. pub fn setup_benchmark() -> Result { let args = crate::arguments::Args::parse(); + + let queue_args = match &args.benchmark { + BenchmarkTypes::Queue(queue_args) => queue_args.clone(), + _ => panic!( + "Trying to run a queue benchmark with another benchmark type" + ), + }; + let date_time = Local::now().format("%Y%m%d%H%M%S").to_string(); // Create benchmark hashed id let benchmark_id = { @@ -127,7 +148,7 @@ pub fn setup_benchmark() -> Result { output_filename, }; - let columns = match bench_conf.args.benchmark { + let columns = match queue_args.benchmark_runner { QueueBenchmarks::BFS(_) => { "Milliseconds,Queuetype,Thread Count,Test ID" }, @@ -146,5 +167,9 @@ pub fn setup_benchmark() -> Result { writeln!(file, "{columns}")?; } - Ok(SetupResult{bench_conf, columns: columns.to_string()}) + Ok(SetupResult { + bench_conf, + queue_conf: queue_args, + columns: columns.to_string(), + }) } diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs b/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs index 6b38fa9..fa6d637 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs @@ -1,4 +1,4 @@ -use crate::arguments::{BFSArgs, QueueBenchmarks}; +use crate::arguments::{QueueBFSArgs, BenchmarkTypes, QueueBenchmarks}; use crate::traits::{ConcurrentQueue, HandleQueue}; use crate::benchmarks::benchmark_helpers; use std::{fs::OpenOptions, sync::{atomic::{AtomicUsize, Ordering}, Barrier}}; @@ -10,7 +10,7 @@ use std::io::{BufRead, BufReader, Write}; /// Generates the graph, generates the sequential solution and gets which /// node to start at. -pub fn pre_bfs_work(cqueue: C, args: &BFSArgs) +pub fn pre_bfs_work(cqueue: C, args: &QueueBFSArgs) -> (Vec>, Vec, usize) where C: ConcurrentQueue, @@ -67,9 +67,11 @@ where C: ConcurrentQueue, for<'a> &'a C: Send { - assert!(matches!(bench_conf.args.benchmark, QueueBenchmarks::BFS(_))); let args = match &bench_conf.args.benchmark { - QueueBenchmarks::BFS(a) => a, + BenchmarkTypes::Queue(args) => match &args.benchmark_runner { + QueueBenchmarks::BFS(a) => a, + _ => panic!(), + } _ => panic!(), }; let thread_count = args.thread_count; diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs index b6fd386..ddd2b67 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs @@ -1,6 +1,7 @@ use core_affinity::CoreId; use log::{debug, error, info, trace}; use rand::Rng; +use crate::arguments::{BenchmarkTypes, QueueBenchmarks}; use crate::traits::{ConcurrentQueue, HandleQueue}; use crate::benchmarks::benchmark_helpers; use std::fs::OpenOptions; @@ -22,9 +23,20 @@ T: Default, for<'a> &'a C: Send { let args = match &bench_conf.args.benchmark { - crate::arguments::QueueBenchmarks::EnqDeq(a) => a, + BenchmarkTypes::Queue(args) => match &args.benchmark_runner { + QueueBenchmarks::EnqDeq(a) => a, + _ => panic!(), + } _ => panic!(), }; + + let queue_args = match &bench_conf.args.benchmark { + BenchmarkTypes::Queue(queue_args) => queue_args.clone(), + _ => panic!( + "Trying to run a queue benchmark with another benchmark type" + ), + }; + { debug!("Prefilling queue with {} items.", bench_conf.args.prefill_amount); let mut tmp_handle = cqueue.register(); @@ -85,7 +97,7 @@ T: Default, match handle.pop() { Some(_) => l_pops += 1, None => { - if bench_conf.args.empty_pops { + if queue_args.empty_pops { l_pops += 1; } } @@ -139,7 +151,7 @@ T: Default, bench_conf.args.benchmark, bench_conf.benchmark_id, args.spread, - bench_conf.args.queue_size + queue_args.queue_size ) } else { @@ -155,7 +167,7 @@ T: Default, bench_conf.benchmark_id, fairness, args.spread, - bench_conf.args.queue_size) + queue_args.queue_size) }; // Write to file or stdout depending on flag if !bench_conf.args.write_to_stdout { @@ -174,7 +186,8 @@ T: Default, mod tests { use crate::arguments::Args; use crate::arguments::QueueBenchmarks; - use crate::arguments::EnqDeqArgs; + use crate::arguments::QueueEnqDeqArgs; + use crate::arguments::QueueArgs; use crate::benchmarks::queue_benchmarks::enq_deq::benchmark_enq_deq; use super::*; @@ -184,7 +197,14 @@ mod tests { #[test] fn run_pingpong() { let args = Args { - benchmark: QueueBenchmarks::EnqDeq(EnqDeqArgs { thread_count: 10, spread: 0.5 }), + benchmark: BenchmarkTypes::Queue(QueueArgs { + empty_pops: Default::default(), + queue_size: 10000, + benchmark_runner: QueueBenchmarks::EnqDeq(QueueEnqDeqArgs { + thread_count: 10, + spread: 0.5, + }) + }), ..Default::default() }; let bench_conf = benchmark_helpers::BenchConfig { @@ -202,7 +222,14 @@ mod tests { #[test] fn run_pingpong_with_bool() { let args = Args { - benchmark: QueueBenchmarks::EnqDeq(EnqDeqArgs { thread_count: 10, spread: 0.5 }), + benchmark: BenchmarkTypes::Queue(QueueArgs { + empty_pops: Default::default(), + queue_size: 10000, + benchmark_runner: QueueBenchmarks::EnqDeq(QueueEnqDeqArgs { + thread_count: 10, + spread: 0.5, + }) + }), ..Default::default() }; let bench_conf = benchmark_helpers::BenchConfig { diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs index d930aff..723e2fc 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs @@ -2,6 +2,7 @@ use core_affinity::CoreId; use log::{debug, error, info, trace}; use rand::Rng; use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; +use crate::arguments::{BenchmarkTypes, QueueBenchmarks}; use crate::traits::{ConcurrentQueue, HandleQueue}; use crate::benchmarks::benchmark_helpers; use std::fs::OpenOptions; @@ -17,9 +18,20 @@ T: Default, for<'a> &'a C: Send { let args = match &bench_conf.args.benchmark { - crate::arguments::QueueBenchmarks::EnqDeqPairs(a) => a, + BenchmarkTypes::Queue(args) => match &args.benchmark_runner { + QueueBenchmarks::EnqDeqPairs(a) => a, + _ => panic!(), + } _ => panic!(), }; + + let queue_args = match &bench_conf.args.benchmark { + BenchmarkTypes::Queue(queue_args) => queue_args.clone(), + _ => panic!( + "Trying to run a queue benchmark with another benchmark type" + ), + }; + { debug!("Prefilling queue with {} items.", bench_conf.args.prefill_amount); let mut tmp_handle = cqueue.register(); @@ -122,7 +134,7 @@ T: Default, bench_conf.args.benchmark, bench_conf.benchmark_id, -1, - bench_conf.args.queue_size + queue_args.queue_size ) } else { @@ -138,7 +150,7 @@ T: Default, bench_conf.benchmark_id, fairness, -1, - bench_conf.args.queue_size) + queue_args.queue_size) }; // Write to file or stdout depending on flag if !bench_conf.args.write_to_stdout { @@ -156,8 +168,9 @@ T: Default, #[cfg(test)] mod tests { use crate::arguments::Args; - use crate::arguments::EnqDeqPairsArgs; + use crate::arguments::QueueEnqDeqPairsArgs; use crate::arguments::QueueBenchmarks; + use crate::arguments::QueueArgs; use crate::benchmarks::queue_benchmarks::enq_deq_pairs::benchmark_enq_deq_pairs; use super::*; @@ -167,7 +180,13 @@ mod tests { #[test] fn run_enqdeq_pairs_with_struct() { let args = Args { - benchmark: QueueBenchmarks::EnqDeqPairs(EnqDeqPairsArgs { thread_count: 10 }), + benchmark: BenchmarkTypes::Queue(QueueArgs { + empty_pops: Default::default(), + queue_size: 10000, + benchmark_runner: QueueBenchmarks::EnqDeqPairs(QueueEnqDeqPairsArgs { + thread_count: 10, + }) + }), ..Default::default() }; let bench_conf = benchmark_helpers::BenchConfig { diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs b/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs index 2ae5177..1017ea8 100644 --- a/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs +++ b/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs @@ -1,6 +1,7 @@ use core_affinity::CoreId; use log::{debug, error, info, trace}; use rand::Rng; +use crate::arguments::{BenchmarkTypes, QueueBenchmarks}; use crate::traits::{ConcurrentQueue, HandleQueue}; use crate::benchmarks::benchmark_helpers; use std::fs::OpenOptions; @@ -23,9 +24,20 @@ where for<'a> &'a C: Send { let args = match &bench_conf.args.benchmark { - crate::arguments::QueueBenchmarks::ProdCon(a) => a, + BenchmarkTypes::Queue(args) => match &args.benchmark_runner { + QueueBenchmarks::ProdCon(a) => a, + _ => panic!(), + } _ => panic!(), }; + + let queue_args = match &bench_conf.args.benchmark { + BenchmarkTypes::Queue(queue_args) => queue_args.clone(), + _ => panic!( + "Trying to run a queue benchmark with another benchmark type" + ), + }; + { debug!("Prefilling queue with {} items.", bench_conf.args.prefill_amount); let mut tmp_handle = cqueue.register(); @@ -173,7 +185,7 @@ where }; // If a thread crashed, pad the results with zero-values let formatted = if thread_failed.load(Ordering::Relaxed) { - format!("0,0,0,{},{},-1,{},{},{},0,-1,{}", producers, consumers, cqueue.get_id(), bench_conf.args.benchmark, bench_conf.benchmark_id, bench_conf.args.queue_size) + format!("0,0,0,{},{},-1,{},{},{},0,-1,{}", producers, consumers, cqueue.get_id(), bench_conf.args.benchmark, bench_conf.benchmark_id, queue_args.queue_size) } else { let fairness = benchmark_helpers::calc_fairness(ops_per_thread); @@ -189,7 +201,7 @@ where bench_conf.benchmark_id, fairness, -1, - bench_conf.args.queue_size) + queue_args.queue_size) }; if !bench_conf.args.write_to_stdout { let mut file = OpenOptions::new() diff --git a/benchmark_core/src/benchmarks/test_helpers.rs b/benchmark_core/src/benchmarks/test_helpers.rs index 492cfe6..a426aec 100644 --- a/benchmark_core/src/benchmarks/test_helpers.rs +++ b/benchmark_core/src/benchmarks/test_helpers.rs @@ -1,4 +1,4 @@ -/// A very simple ConcurrentQueue implementation for testing +/// A simple ConcurrentQueue implementation for testing pub(crate) mod test_queue { use crate::traits::{ConcurrentQueue, HandleQueue}; use std::collections::VecDeque; @@ -39,3 +39,88 @@ pub(crate) mod test_queue { } } } + +/// A very simple ConcurrentPriorityQueue implementation for testing +pub(crate) mod test_priority_queue { + use crate::traits::{ConcurrentPriorityQueue, HandlePriorityQueue}; + use std::cmp::{Ordering, Reverse}; + use std::collections::BinaryHeap; + use std::sync::Mutex; + + pub struct KeyValuePair { + key: Reverse

, + item: T, + } + + impl KeyValuePair { + pub fn new(key: P, item: T) -> Self { + Self { + key: Reverse(key), + item, + } + } + } + + impl Ord for KeyValuePair { + fn cmp(&self, other: &Self) -> Ordering { + self.key.cmp(&other.key) + } + } + + impl PartialOrd for KeyValuePair { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } + } + + impl PartialEq for KeyValuePair { + fn eq(&self, other: &Self) -> bool { + self.key == other.key + } + } + + impl Eq for KeyValuePair {} + + pub struct TestPriorityQueue { + queue: Mutex>>, + } + + pub struct TestPriorityQueueHandle<'a, P: Ord, T> { + queue: &'a TestPriorityQueue, + } + + impl HandlePriorityQueue + for TestPriorityQueueHandle<'_, P, T> + { + fn insert(&mut self, priority: P, item: T) -> Result<(), (P, T)> { + let kv_pair = KeyValuePair::new(priority, item); + self.queue.queue.lock().unwrap().push(kv_pair); + Ok(()) + } + fn delete_min(&mut self) -> Option { + match self.queue.queue.lock().unwrap().pop() { + Some(kv_pair) => Some(kv_pair.item), + None => None, + } + } + fn is_empty(&mut self) -> bool { + self.queue.queue.lock().unwrap().is_empty() + } + } + + impl ConcurrentPriorityQueue for TestPriorityQueue { + fn register(&self) -> impl HandlePriorityQueue { + TestPriorityQueueHandle { queue: self } + } + + fn get_id(&self) -> String { + "test_queue".to_string() + } + + fn new(_size: usize) -> Self { + TestPriorityQueue { + queue: Mutex::new(BinaryHeap::new()), + } + } + } +} diff --git a/benchmark_core/src/traits.rs b/benchmark_core/src/traits.rs index 2563075..1599d64 100644 --- a/benchmark_core/src/traits.rs +++ b/benchmark_core/src/traits.rs @@ -39,10 +39,4 @@ pub trait HandlePriorityQueue { fn delete_min(&mut self) -> Option; /// Checks if the priority queue is empty fn is_empty(&mut self) -> bool; - /// Peeks at the smallest key-value pair but doesn't remove it from the - /// queue - /// Returns an enum wrapped in a Some() of the form (key, value) if there - /// exists a smallest value - /// Returns None if there is no item in the queue - fn min(&mut self) -> Option<(&P, &T)>; } diff --git a/data_structures/priority_queues/basic_priority_queue/src/lib.rs b/data_structures/priority_queues/basic_priority_queue/src/lib.rs index f59b7c8..4c021c4 100644 --- a/data_structures/priority_queues/basic_priority_queue/src/lib.rs +++ b/data_structures/priority_queues/basic_priority_queue/src/lib.rs @@ -55,10 +55,6 @@ impl BinHeapWrap { self.bin_heap.lock().unwrap().is_empty() } - pub fn min(&self) -> Option<&KeyValuePair> { - self.bin_heap.lock().unwrap().peek() - } - pub fn new() -> Self { BinHeapWrap { bin_heap: Mutex::new(BinaryHeap::new()), @@ -99,26 +95,20 @@ impl ConcurrentPriorityQueue for BasicPriorityQueue { impl HandlePriorityQueue for BasicPriorityQueueHandle<'_, P, T> { - fn insert(&self, priority: P, item: T) -> Result<(), (P, T)> { + fn insert(&mut self, priority: P, item: T) -> Result<(), (P, T)> { let kv_pair = KeyValuePair::new(priority, item); self.priority_queue.basic_priority_queue.insert(kv_pair); Ok(()) } - fn delete_min(&self) -> Option { + fn delete_min(&mut self) -> Option { match self.priority_queue.basic_priority_queue.delete_min() { Some(kv_pair) => Some(kv_pair.item), None => None, } } - fn is_empty(&self) -> bool { + fn is_empty(&mut self) -> bool { self.priority_queue.basic_priority_queue.is_empty() } - fn min(&self) -> Option<(&P, &T)> { - match self.priority_queue.basic_priority_queue.min() { - Some(kv_pair) => Some((kv_pair.key, kv_pair.item)), - None => None, - } - } } #[cfg(test)] diff --git a/data_structures/priority_queues/basic_priority_queue/src/main.rs b/data_structures/priority_queues/basic_priority_queue/src/main.rs index b78187a..93e4534 100644 --- a/data_structures/priority_queues/basic_priority_queue/src/main.rs +++ b/data_structures/priority_queues/basic_priority_queue/src/main.rs @@ -1,6 +1,5 @@ +use benchmark_core::benchmarks::priority_queue_benchmarks::benchmark_priority_queue; use log::*; -// use benchmark_core::benchmarks::priority_queue_benchmarks::benchmark_priority_queue; - fn main() { // initialize env_logger if not in silent release mode @@ -11,13 +10,15 @@ fn main() { } log::info!("Starting benchmark"); - // match benchmark_priority_queue::>("basic_priority_queue") { - // Ok(_) => println!("Benchmark done."), - // Err(e) => { - // eprintln!("Benchmark received error: {}", e); - // println!("Benchmark exiting due to error."); - // } - // } - - println!("Hello from Basic Priority Queue Main"); + match benchmark_priority_queue::< + basic_priority_queue::BasicPriorityQueue, + i32, + >("basic_priority_queue") + { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } } diff --git a/readme.md b/readme.md index e38f147..5e271b0 100644 --- a/readme.md +++ b/readme.md @@ -2,6 +2,7 @@ This is a project to benchmark different implementations of queues (currently FIFO, LIFO, bounded or unbounded) to measure their output and performance. # Contents +- [Disclaimer](#disclaimer) - [How to use](#how-to-use) - [Queue implementations](#queue-implementations) - [Benchmarks](#benchmarks) @@ -14,6 +15,10 @@ This is a project to benchmark different implementations of queues (currently FI - [BFS](#bfs) - [Logging](#logging) +## Disclaimer + +This project is currently undergoing a rework. The basic functionality still works but some features don't work as described in this README. Some arguments have been reworked to support other data structures, so the description below is not currently valid. Use the `--help` command to get the up-to-date arguments. Some features don't work for certain data structures, for example, `benchmark_core/memeory_tracking` doesn't work for the priority_queue data structures. The output will also look slightly different, but this is planned to be fixed in the future. + ## How to use: ```bash # Using cargo run From a8e0d465880db506f210870ea35e38512df1ae3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Thu, 5 Feb 2026 11:18:13 +0100 Subject: [PATCH 12/16] Add update of software repositories for boost install in workflow --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 3dbf5ff..48b00c0 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install Boost - run: sudo apt-get install -y libboost-all-dev + run: sudo apt-get update && sudo apt-get install -y libboost-all-dev - name: Get submodules run: git submodule init && git submodule update - name: Build From b5c7995de553d5cdf3cc6957d23d3678e8d1a683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Thu, 5 Feb 2026 11:38:52 +0100 Subject: [PATCH 13/16] Add ignore tag for compute heavy tests --- data_structures/priority_queues/basic_priority_queue/src/lib.rs | 2 +- data_structures/queues/array_queue/src/lib.rs | 1 + data_structures/queues/atomic_queue/src/lib.rs | 1 + data_structures/queues/basic_queue/src/lib.rs | 1 + data_structures/queues/bbq/src/lib.rs | 1 + data_structures/queues/boost_queue_cpp/src/lib.rs | 1 + data_structures/queues/bounded_concurrent_queue/src/lib.rs | 1 + data_structures/queues/faaa_queue/src/lib.rs | 1 + data_structures/queues/faaa_queue_cpp/src/lib.rs | 1 + data_structures/queues/lcrq/src/lib.rs | 1 + data_structures/queues/lcrq_cpp/src/lib.rs | 1 + data_structures/queues/lf_queue/src/lib.rs | 1 + data_structures/queues/lockfree_queue/src/lib.rs | 1 + data_structures/queues/lprq/src/lib.rs | 1 + data_structures/queues/lprq/src/lprq_rs.rs | 1 + data_structures/queues/lprq_cpp/src/lib.rs | 1 + data_structures/queues/ms_queue/src/lib.rs | 1 + data_structures/queues/seg_queue/src/lib.rs | 1 + data_structures/queues/tz_queue_hp/src/lib.rs | 1 + data_structures/queues/tz_queue_leak/src/lib.rs | 1 + data_structures/queues/unbounded_concurrent_queue/src/lib.rs | 1 + 21 files changed, 21 insertions(+), 1 deletion(-) diff --git a/data_structures/priority_queues/basic_priority_queue/src/lib.rs b/data_structures/priority_queues/basic_priority_queue/src/lib.rs index 4c021c4..bae731f 100644 --- a/data_structures/priority_queues/basic_priority_queue/src/lib.rs +++ b/data_structures/priority_queues/basic_priority_queue/src/lib.rs @@ -133,7 +133,7 @@ mod tests { } #[test] - fn test_order_basic_priority_queue() { + fn basic_usage_basic_priority_queue() { let pq = BasicPriorityQueue::::new(0); let mut handle = pq.register(); diff --git a/data_structures/queues/array_queue/src/lib.rs b/data_structures/queues/array_queue/src/lib.rs index 3e76eda..9b8ed8a 100644 --- a/data_structures/queues/array_queue/src/lib.rs +++ b/data_structures/queues/array_queue/src/lib.rs @@ -59,6 +59,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 1); } #[test] + #[ignore] fn test_order() { let q: AQueue = AQueue { array_queue: ArrayQueue::new(10) diff --git a/data_structures/queues/atomic_queue/src/lib.rs b/data_structures/queues/atomic_queue/src/lib.rs index ba3c3f0..e4be0b2 100644 --- a/data_structures/queues/atomic_queue/src/lib.rs +++ b/data_structures/queues/atomic_queue/src/lib.rs @@ -57,6 +57,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 1); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: AtomicQueue = AtomicQueue::new(10); diff --git a/data_structures/queues/basic_queue/src/lib.rs b/data_structures/queues/basic_queue/src/lib.rs index 55ae933..f2decfe 100644 --- a/data_structures/queues/basic_queue/src/lib.rs +++ b/data_structures/queues/basic_queue/src/lib.rs @@ -90,6 +90,7 @@ mod tests { } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: BasicQueue = BasicQueue { diff --git a/data_structures/queues/bbq/src/lib.rs b/data_structures/queues/bbq/src/lib.rs index 9f5c121..04fcd5c 100644 --- a/data_structures/queues/bbq/src/lib.rs +++ b/data_structures/queues/bbq/src/lib.rs @@ -47,6 +47,7 @@ mod tests { assert_eq!(q.queue.pop().unwrap(), 1); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: BBQueue = BBQueue::new(100000); diff --git a/data_structures/queues/boost_queue_cpp/src/lib.rs b/data_structures/queues/boost_queue_cpp/src/lib.rs index 12441ed..504b241 100644 --- a/data_structures/queues/boost_queue_cpp/src/lib.rs +++ b/data_structures/queues/boost_queue_cpp/src/lib.rs @@ -122,6 +122,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 4); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: BoostCppQueue = BoostCppQueue::new(10); diff --git a/data_structures/queues/bounded_concurrent_queue/src/lib.rs b/data_structures/queues/bounded_concurrent_queue/src/lib.rs index 7800063..49b3e4b 100644 --- a/data_structures/queues/bounded_concurrent_queue/src/lib.rs +++ b/data_structures/queues/bounded_concurrent_queue/src/lib.rs @@ -81,6 +81,7 @@ mod tests { q.cq.push(1).unwrap(); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: BoundedCQueue = BoundedCQueue { diff --git a/data_structures/queues/faaa_queue/src/lib.rs b/data_structures/queues/faaa_queue/src/lib.rs index 3aa17e4..d113b89 100644 --- a/data_structures/queues/faaa_queue/src/lib.rs +++ b/data_structures/queues/faaa_queue/src/lib.rs @@ -195,6 +195,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 1); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: FAAAQueue = FAAAQueue::new(10); diff --git a/data_structures/queues/faaa_queue_cpp/src/lib.rs b/data_structures/queues/faaa_queue_cpp/src/lib.rs index 4a92064..548d8c2 100644 --- a/data_structures/queues/faaa_queue_cpp/src/lib.rs +++ b/data_structures/queues/faaa_queue_cpp/src/lib.rs @@ -159,6 +159,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 4); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: FAAAQueue = FAAAQueue::new(); diff --git a/data_structures/queues/lcrq/src/lib.rs b/data_structures/queues/lcrq/src/lib.rs index 6f9b5d3..8750284 100644 --- a/data_structures/queues/lcrq/src/lib.rs +++ b/data_structures/queues/lcrq/src/lib.rs @@ -509,6 +509,7 @@ mod tests { assert_eq!(thesum, sum.into_inner()); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: LCRQueue = LCRQueue::new(); diff --git a/data_structures/queues/lcrq_cpp/src/lib.rs b/data_structures/queues/lcrq_cpp/src/lib.rs index 8d057b5..4e96850 100644 --- a/data_structures/queues/lcrq_cpp/src/lib.rs +++ b/data_structures/queues/lcrq_cpp/src/lib.rs @@ -152,6 +152,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 4); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: LCRQueue = LCRQueue::new(); diff --git a/data_structures/queues/lf_queue/src/lib.rs b/data_structures/queues/lf_queue/src/lib.rs index 3be402a..09d5e7e 100644 --- a/data_structures/queues/lf_queue/src/lib.rs +++ b/data_structures/queues/lf_queue/src/lib.rs @@ -56,6 +56,7 @@ mod tests { } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: LFQueue = LFQueue::new(10); diff --git a/data_structures/queues/lockfree_queue/src/lib.rs b/data_structures/queues/lockfree_queue/src/lib.rs index afbc98a..d0c0385 100644 --- a/data_structures/queues/lockfree_queue/src/lib.rs +++ b/data_structures/queues/lockfree_queue/src/lib.rs @@ -60,6 +60,7 @@ mod tests { } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: LockfreeQueue = LockfreeQueue { diff --git a/data_structures/queues/lprq/src/lib.rs b/data_structures/queues/lprq/src/lib.rs index 52ed122..5edfce7 100644 --- a/data_structures/queues/lprq/src/lib.rs +++ b/data_structures/queues/lprq/src/lib.rs @@ -440,6 +440,7 @@ mod tests { assert_eq!(thesum, sum.into_inner()); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: LPRQueue = LPRQueue::new(); diff --git a/data_structures/queues/lprq/src/lprq_rs.rs b/data_structures/queues/lprq/src/lprq_rs.rs index 5a62203..4894195 100644 --- a/data_structures/queues/lprq/src/lprq_rs.rs +++ b/data_structures/queues/lprq/src/lprq_rs.rs @@ -56,6 +56,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 1); } #[test] + #[ignore] fn test_order() { let q: LPRQRS = LPRQRS::new(100); if benchmark_core::order::benchmark_order_i32(q, 10, 5, true, 10).is_err() { diff --git a/data_structures/queues/lprq_cpp/src/lib.rs b/data_structures/queues/lprq_cpp/src/lib.rs index 83123a3..61306ec 100644 --- a/data_structures/queues/lprq_cpp/src/lib.rs +++ b/data_structures/queues/lprq_cpp/src/lib.rs @@ -157,6 +157,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 4); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: LPRQueue = LPRQueue::new(); diff --git a/data_structures/queues/ms_queue/src/lib.rs b/data_structures/queues/ms_queue/src/lib.rs index 9481db0..8b05ae9 100644 --- a/data_structures/queues/ms_queue/src/lib.rs +++ b/data_structures/queues/ms_queue/src/lib.rs @@ -215,6 +215,7 @@ mod tests { } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: MSQueue = MSQueue::new(10); diff --git a/data_structures/queues/seg_queue/src/lib.rs b/data_structures/queues/seg_queue/src/lib.rs index 704ee5c..3089bbb 100644 --- a/data_structures/queues/seg_queue/src/lib.rs +++ b/data_structures/queues/seg_queue/src/lib.rs @@ -56,6 +56,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 1); } #[test] + #[ignore] fn test_order() { let q: SQueue = SQueue::new(100); if benchmark_core::order::benchmark_order_i32(q, 10, 5, true, 10).is_err() { diff --git a/data_structures/queues/tz_queue_hp/src/lib.rs b/data_structures/queues/tz_queue_hp/src/lib.rs index f323c6f..e04ee58 100644 --- a/data_structures/queues/tz_queue_hp/src/lib.rs +++ b/data_structures/queues/tz_queue_hp/src/lib.rs @@ -347,6 +347,7 @@ mod tests { drop(q); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: TZQueue = TZQueue::new(1000000); diff --git a/data_structures/queues/tz_queue_leak/src/lib.rs b/data_structures/queues/tz_queue_leak/src/lib.rs index 2ef47d0..983e5dd 100644 --- a/data_structures/queues/tz_queue_leak/src/lib.rs +++ b/data_structures/queues/tz_queue_leak/src/lib.rs @@ -330,6 +330,7 @@ mod tests { drop(q); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: TZQueue = TZQueue::new(10); diff --git a/data_structures/queues/unbounded_concurrent_queue/src/lib.rs b/data_structures/queues/unbounded_concurrent_queue/src/lib.rs index 450c984..1bbd055 100644 --- a/data_structures/queues/unbounded_concurrent_queue/src/lib.rs +++ b/data_structures/queues/unbounded_concurrent_queue/src/lib.rs @@ -68,6 +68,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 1); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: UnboundedCQueue = UnboundedCQueue::new(0); From 99493010818546174cfff3b7e93ee582d14e4dc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Thu, 5 Feb 2026 11:51:49 +0100 Subject: [PATCH 14/16] Add cfg tag test for test modules --- benchmark_core/src/benchmarks/test_helpers.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/benchmark_core/src/benchmarks/test_helpers.rs b/benchmark_core/src/benchmarks/test_helpers.rs index a426aec..07de017 100644 --- a/benchmark_core/src/benchmarks/test_helpers.rs +++ b/benchmark_core/src/benchmarks/test_helpers.rs @@ -1,4 +1,5 @@ /// A simple ConcurrentQueue implementation for testing +#[cfg(test)] pub(crate) mod test_queue { use crate::traits::{ConcurrentQueue, HandleQueue}; use std::collections::VecDeque; @@ -41,6 +42,7 @@ pub(crate) mod test_queue { } /// A very simple ConcurrentPriorityQueue implementation for testing +#[cfg(test)] pub(crate) mod test_priority_queue { use crate::traits::{ConcurrentPriorityQueue, HandlePriorityQueue}; use std::cmp::{Ordering, Reverse}; From a9ed612d0fae374a2a8610ef463685bba9bbeb03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Thu, 5 Feb 2026 16:21:06 +0100 Subject: [PATCH 15/16] Rename queues to fifo_queues --- .../src/benchmarks/queue_benchmarks.rs | 175 ---------- .../src/benchmarks/queue_benchmarks/bfs.rs | 330 ------------------ .../benchmarks/queue_benchmarks/enq_deq.rs | 246 ------------- .../queue_benchmarks/enq_deq_pairs.rs | 203 ----------- .../benchmarks/queue_benchmarks/prod_con.rs | 273 --------------- .../array_queue/Cargo.toml | 0 .../array_queue/src/lib.rs | 0 .../fifo_queues/array_queue/src/main.rs | 21 ++ .../atomic_queue/Cargo.toml | 0 .../atomic_queue/src/lib.rs | 0 .../fifo_queues/atomic_queue/src/main.rs | 21 ++ .../basic_queue/Cargo.toml | 0 .../basic_queue/src/lib.rs | 0 .../fifo_queues/basic_queue/src/main.rs | 21 ++ .../{queues => fifo_queues}/bbq/Cargo.toml | 0 .../{queues => fifo_queues}/bbq/src/lib.rs | 0 .../lcrq => fifo_queues/bbq}/src/main.rs | 4 +- .../boost_queue_cpp/Cargo.toml | 0 .../boost_queue_cpp/build.rs | 0 .../boost_queue_cpp/cpp_src/boost_wrapper.cpp | 0 .../boost_queue_cpp/cpp_src/boost_wrapper.hpp | 0 .../boost_queue_cpp/src/lib.rs | 0 .../fifo_queues/boost_queue_cpp/src/main.rs | 21 ++ .../bounded_concurrent_queue/Cargo.toml | 0 .../bounded_concurrent_queue/src/lib.rs | 0 .../bounded_concurrent_queue/src/main.rs | 21 ++ .../bounded_ringbuffer/Cargo.toml | 0 .../bounded_ringbuffer/src/lib.rs | 0 .../bounded_ringbuffer/src/main.rs | 21 ++ .../faaa_queue/Cargo.toml | 0 .../faaa_queue/src/lib.rs | 0 .../fifo_queues/faaa_queue/src/main.rs | 21 ++ .../faaa_queue_cpp/Cargo.toml | 0 .../faaa_queue_cpp/build.rs | 0 .../cpp_src/faaa_queue/FAAArrayQueue.hpp | 0 .../cpp_src/faaa_queue/HazardPointers.hpp | 0 .../cpp_src/faaa_queue_wrapper.cpp | 0 .../cpp_src/faaa_queue_wrapper.hpp | 0 .../faaa_queue_cpp/src/lib.rs | 0 .../fifo_queues/faaa_queue_cpp/src/main.rs | 21 ++ .../{queues => fifo_queues}/lcrq/Cargo.toml | 0 .../{queues => fifo_queues}/lcrq/src/lib.rs | 0 .../lcrq}/src/main.rs | 4 +- .../lcrq_cpp/Cargo.toml | 0 .../{queues => fifo_queues}/lcrq_cpp/build.rs | 0 .../lcrq_cpp/cpp_src/HazardPointers.hpp | 0 .../lcrq_cpp/cpp_src/LCRQueue.hpp | 0 .../lcrq_cpp/cpp_src/lcrq_wrapper.cpp | 0 .../lcrq_cpp/cpp_src/lcrq_wrapper.hpp | 0 .../lcrq_cpp/src/lib.rs | 0 .../fifo_queues/lcrq_cpp/src/main.rs | 21 ++ .../lf_queue/Cargo.toml | 0 .../lf_queue/src/lib.rs | 0 .../lf_queue}/src/main.rs | 4 +- .../lockfree_queue/Cargo.toml | 0 .../lockfree_queue/src/lib.rs | 0 .../fifo_queues/lockfree_queue/src/main.rs | 21 ++ .../{queues => fifo_queues}/lprq/Cargo.toml | 0 .../{queues => fifo_queues}/lprq/src/lib.rs | 0 .../lprq/src/lprq_rs.rs | 0 .../lcrq_cpp => fifo_queues/lprq}/src/main.rs | 4 +- .../lprq_cpp/Cargo.toml | 0 .../{queues => fifo_queues}/lprq_cpp/build.rs | 0 .../cpp-ring-queues-research/.dockerignore | 0 .../cpp-ring-queues-research/.gitignore | 0 .../cpp-ring-queues-research/CLI11.cmake | 0 .../cpp-ring-queues-research/CMakeLists.txt | 0 .../cpp-ring-queues-research/Dockerfile | 0 .../cpp-ring-queues-research/Gtest.cmake | 0 .../cpp_src/cpp-ring-queues-research/LICENSE | 0 .../cpp-ring-queues-research/README.md | 0 .../include/CacheRemap.hpp | 0 .../include/Forked.hpp | 0 .../include/HazardPointers.hpp | 0 .../include/LPRQueue.hpp | 0 .../include/LinkedRingQueue.hpp | 0 .../include/MetaprogrammingUtils.hpp | 0 .../include/Metrics.hpp | 0 .../include/ModLCRQueue.hpp | 0 .../include/RQCell.hpp | 0 .../include/Stats.hpp | 0 .../include/ThreadGroup.hpp | 0 .../include/x86AtomicOps.hpp | 0 .../lprq_cpp/cpp_src/lprq_wrapper.cpp | 0 .../lprq_cpp/cpp_src/lprq_wrapper.hpp | 0 .../lprq_cpp/src/lib.rs | 0 .../fifo_queues/lprq_cpp/src/main.rs | 21 ++ .../moodycamel_cpp/Cargo.toml | 0 .../moodycamel_cpp/build.rs | 0 .../moodycamel_cpp/cpp_src/concurrentqueue | 0 .../cpp_src/moodycamel_wrapper.cpp | 0 .../cpp_src/moodycamel_wrapper.hpp | 0 .../moodycamel_cpp/src/lib.rs | 0 .../fifo_queues/moodycamel_cpp/src/main.rs | 21 ++ .../ms_queue/Cargo.toml | 0 .../ms_queue/src/lib.rs | 0 .../ms_queue}/src/main.rs | 4 +- .../scc2_queue/Cargo.toml | 0 .../scc2_queue/src/lib.rs | 0 .../fifo_queues/scc2_queue/src/main.rs | 21 ++ .../scc_queue/Cargo.toml | 0 .../scc_queue/src/lib.rs | 0 .../fifo_queues/scc_queue/src/main.rs | 21 ++ .../seg_queue/Cargo.toml | 0 .../seg_queue/src/lib.rs | 0 .../seg_queue}/src/main.rs | 4 +- .../tz_queue_hp/Cargo.toml | 0 .../tz_queue_hp/src/lib.rs | 0 .../fifo_queues/tz_queue_hp/src/main.rs | 21 ++ .../tz_queue_leak/Cargo.toml | 0 .../tz_queue_leak/src/lib.rs | 0 .../fifo_queues/tz_queue_leak/src/main.rs | 21 ++ .../unbounded_concurrent_queue/Cargo.toml | 0 .../unbounded_concurrent_queue/src/lib.rs | 0 .../unbounded_concurrent_queue/src/main.rs | 21 ++ .../wf_queue/Cargo.toml | 0 .../wf_queue/src/lib.rs | 0 .../bbq => fifo_queues/wf_queue}/src/main.rs | 4 +- .../queues/boost_queue_cpp/src/main.rs | 21 -- .../bounded_concurrent_queue/src/main.rs | 21 -- .../queues/bounded_ringbuffer/src/main.rs | 21 -- data_structures/queues/faaa_queue/src/main.rs | 21 -- .../queues/faaa_queue_cpp/src/main.rs | 21 -- data_structures/queues/lf_queue/src/main.rs | 21 -- .../queues/lockfree_queue/src/main.rs | 21 -- data_structures/queues/lprq/src/main.rs | 21 -- data_structures/queues/lprq_cpp/src/main.rs | 21 -- .../queues/moodycamel_cpp/src/main.rs | 21 -- data_structures/queues/ms_queue/src/main.rs | 21 -- data_structures/queues/scc_queue/src/main.rs | 21 -- data_structures/queues/seg_queue/src/main.rs | 21 -- .../queues/tz_queue_hp/src/main.rs | 21 -- .../queues/tz_queue_leak/src/main.rs | 21 -- .../unbounded_concurrent_queue/src/main.rs | 21 -- data_structures/queues/wf_queue/src/main.rs | 21 -- 135 files changed, 371 insertions(+), 1598 deletions(-) delete mode 100644 benchmark_core/src/benchmarks/queue_benchmarks.rs delete mode 100644 benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs delete mode 100644 benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs delete mode 100644 benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs delete mode 100644 benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs rename data_structures/{queues => fifo_queues}/array_queue/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/array_queue/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/array_queue/src/main.rs rename data_structures/{queues => fifo_queues}/atomic_queue/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/atomic_queue/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/atomic_queue/src/main.rs rename data_structures/{queues => fifo_queues}/basic_queue/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/basic_queue/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/basic_queue/src/main.rs rename data_structures/{queues => fifo_queues}/bbq/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/bbq/src/lib.rs (100%) rename data_structures/{queues/lcrq => fifo_queues/bbq}/src/main.rs (77%) rename data_structures/{queues => fifo_queues}/boost_queue_cpp/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/boost_queue_cpp/build.rs (100%) rename data_structures/{queues => fifo_queues}/boost_queue_cpp/cpp_src/boost_wrapper.cpp (100%) rename data_structures/{queues => fifo_queues}/boost_queue_cpp/cpp_src/boost_wrapper.hpp (100%) rename data_structures/{queues => fifo_queues}/boost_queue_cpp/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/boost_queue_cpp/src/main.rs rename data_structures/{queues => fifo_queues}/bounded_concurrent_queue/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/bounded_concurrent_queue/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/bounded_concurrent_queue/src/main.rs rename data_structures/{queues => fifo_queues}/bounded_ringbuffer/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/bounded_ringbuffer/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/bounded_ringbuffer/src/main.rs rename data_structures/{queues => fifo_queues}/faaa_queue/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/faaa_queue/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/faaa_queue/src/main.rs rename data_structures/{queues => fifo_queues}/faaa_queue_cpp/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/faaa_queue_cpp/build.rs (100%) rename data_structures/{queues => fifo_queues}/faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp (100%) rename data_structures/{queues => fifo_queues}/faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp (100%) rename data_structures/{queues => fifo_queues}/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp (100%) rename data_structures/{queues => fifo_queues}/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp (100%) rename data_structures/{queues => fifo_queues}/faaa_queue_cpp/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/faaa_queue_cpp/src/main.rs rename data_structures/{queues => fifo_queues}/lcrq/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/lcrq/src/lib.rs (100%) rename data_structures/{queues/array_queue => fifo_queues/lcrq}/src/main.rs (77%) rename data_structures/{queues => fifo_queues}/lcrq_cpp/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/lcrq_cpp/build.rs (100%) rename data_structures/{queues => fifo_queues}/lcrq_cpp/cpp_src/HazardPointers.hpp (100%) rename data_structures/{queues => fifo_queues}/lcrq_cpp/cpp_src/LCRQueue.hpp (100%) rename data_structures/{queues => fifo_queues}/lcrq_cpp/cpp_src/lcrq_wrapper.cpp (100%) rename data_structures/{queues => fifo_queues}/lcrq_cpp/cpp_src/lcrq_wrapper.hpp (100%) rename data_structures/{queues => fifo_queues}/lcrq_cpp/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/lcrq_cpp/src/main.rs rename data_structures/{queues => fifo_queues}/lf_queue/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/lf_queue/src/lib.rs (100%) rename data_structures/{queues/atomic_queue => fifo_queues/lf_queue}/src/main.rs (75%) rename data_structures/{queues => fifo_queues}/lockfree_queue/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/lockfree_queue/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/lockfree_queue/src/main.rs rename data_structures/{queues => fifo_queues}/lprq/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/lprq/src/lib.rs (100%) rename data_structures/{queues => fifo_queues}/lprq/src/lprq_rs.rs (100%) rename data_structures/{queues/lcrq_cpp => fifo_queues/lprq}/src/main.rs (76%) rename data_structures/{queues => fifo_queues}/lprq_cpp/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/build.rs (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/README.md (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Forked.hpp (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/HazardPointers.hpp (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LinkedRingQueue.hpp (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/MetaprogrammingUtils.hpp (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Metrics.hpp (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/RQCell.hpp (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Stats.hpp (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/lprq_wrapper.cpp (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/cpp_src/lprq_wrapper.hpp (100%) rename data_structures/{queues => fifo_queues}/lprq_cpp/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/lprq_cpp/src/main.rs rename data_structures/{queues => fifo_queues}/moodycamel_cpp/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/moodycamel_cpp/build.rs (100%) rename data_structures/{queues => fifo_queues}/moodycamel_cpp/cpp_src/concurrentqueue (100%) rename data_structures/{queues => fifo_queues}/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp (100%) rename data_structures/{queues => fifo_queues}/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp (100%) rename data_structures/{queues => fifo_queues}/moodycamel_cpp/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/moodycamel_cpp/src/main.rs rename data_structures/{queues => fifo_queues}/ms_queue/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/ms_queue/src/lib.rs (100%) rename data_structures/{queues/basic_queue => fifo_queues/ms_queue}/src/main.rs (75%) rename data_structures/{queues => fifo_queues}/scc2_queue/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/scc2_queue/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/scc2_queue/src/main.rs rename data_structures/{queues => fifo_queues}/scc_queue/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/scc_queue/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/scc_queue/src/main.rs rename data_structures/{queues => fifo_queues}/seg_queue/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/seg_queue/src/lib.rs (100%) rename data_structures/{queues/scc2_queue => fifo_queues/seg_queue}/src/main.rs (77%) rename data_structures/{queues => fifo_queues}/tz_queue_hp/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/tz_queue_hp/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/tz_queue_hp/src/main.rs rename data_structures/{queues => fifo_queues}/tz_queue_leak/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/tz_queue_leak/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/tz_queue_leak/src/main.rs rename data_structures/{queues => fifo_queues}/unbounded_concurrent_queue/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/unbounded_concurrent_queue/src/lib.rs (100%) create mode 100644 data_structures/fifo_queues/unbounded_concurrent_queue/src/main.rs rename data_structures/{queues => fifo_queues}/wf_queue/Cargo.toml (100%) rename data_structures/{queues => fifo_queues}/wf_queue/src/lib.rs (100%) rename data_structures/{queues/bbq => fifo_queues/wf_queue}/src/main.rs (75%) delete mode 100644 data_structures/queues/boost_queue_cpp/src/main.rs delete mode 100644 data_structures/queues/bounded_concurrent_queue/src/main.rs delete mode 100644 data_structures/queues/bounded_ringbuffer/src/main.rs delete mode 100644 data_structures/queues/faaa_queue/src/main.rs delete mode 100644 data_structures/queues/faaa_queue_cpp/src/main.rs delete mode 100644 data_structures/queues/lf_queue/src/main.rs delete mode 100644 data_structures/queues/lockfree_queue/src/main.rs delete mode 100644 data_structures/queues/lprq/src/main.rs delete mode 100644 data_structures/queues/lprq_cpp/src/main.rs delete mode 100644 data_structures/queues/moodycamel_cpp/src/main.rs delete mode 100644 data_structures/queues/ms_queue/src/main.rs delete mode 100644 data_structures/queues/scc_queue/src/main.rs delete mode 100644 data_structures/queues/seg_queue/src/main.rs delete mode 100644 data_structures/queues/tz_queue_hp/src/main.rs delete mode 100644 data_structures/queues/tz_queue_leak/src/main.rs delete mode 100644 data_structures/queues/unbounded_concurrent_queue/src/main.rs delete mode 100644 data_structures/queues/wf_queue/src/main.rs diff --git a/benchmark_core/src/benchmarks/queue_benchmarks.rs b/benchmark_core/src/benchmarks/queue_benchmarks.rs deleted file mode 100644 index 202895d..0000000 --- a/benchmark_core/src/benchmarks/queue_benchmarks.rs +++ /dev/null @@ -1,175 +0,0 @@ -#[allow(unused_imports)] -use crate::arguments::{Args, BenchmarkTypes, QueueBenchmarks, QueueArgs}; -use crate::benchmarks::benchmark_helpers; -#[allow(unused_imports)] -use crate::traits::{ConcurrentQueue, HandleQueue}; -use chrono::Local; -use clap::Parser; -#[allow(unused_imports)] -use log::{self, debug, error, info}; -use std::collections::hash_map::DefaultHasher; -use std::fs::OpenOptions; -use std::hash::{Hash, Hasher}; -use std::io::Write; -#[allow(unused_imports)] -use std::sync::atomic::AtomicBool; - -pub mod bfs; -pub mod enq_deq; -pub mod enq_deq_pairs; -pub mod prod_con; - -/// Create the queue, and run the selected benchmark a set of times -pub fn benchmark_queue(queue_name: &str) -> Result<(), std::io::Error> -where - Q: ConcurrentQueue + Send, - for<'a> &'a Q: Send, -{ - // Setup output and parse arguments - let SetupResult { bench_conf, queue_conf, .. } = setup_benchmark()?; - let bench_conf = &bench_conf; - - // Create a runner lambda for the different benchmarks, mainly needed for eg. BFS to load graph and so on - let mut runner: Box< - dyn FnMut( - Q, - &benchmark_helpers::BenchConfig, - ) -> Result<(), std::io::Error>, - > = match &queue_conf.benchmark_runner { - QueueBenchmarks::ProdCon(_) => Box::new(move |q, bench_conf| { - prod_con::benchmark_prod_con(q, bench_conf) - }), - QueueBenchmarks::EnqDeq(_) => Box::new(move |q, bench_conf| { - enq_deq::benchmark_enq_deq(q, bench_conf) - }), - QueueBenchmarks::EnqDeqPairs(_) => Box::new(move |q, bench_conf| { - enq_deq_pairs::benchmark_enq_deq_pairs(q, bench_conf) - }), - QueueBenchmarks::BFS(args) => { - let (graph, seq_ret_vec, start_node) = bfs::pre_bfs_work( - Q::new(queue_conf.queue_size as usize), - &args, - ); - Box::new(move |q, _conf| { - bfs::benchmark_bfs( - q, - &graph, - bench_conf, - &seq_ret_vec, - start_node, - ) - }) - } - }; - - for _current_iteration in 0..bench_conf.args.iterations { - // Create the queue. - let test_q: Q = Q::new(queue_conf.queue_size as usize); - - // Start memory tracking (if enabled) - #[cfg(feature = "memory_tracking")] - let (done, mem_thread_handle) = { - let done = - std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); - let handle = benchmark_helpers::create_mem_tracking_thread( - bench_conf, - _current_iteration, - &test_q, - &done, - )?; - (done, handle) - }; - - // Execute the benchmark - runner(test_q, bench_conf)?; - - // Join the thread again - debug!("Queue should have been dropped now."); - - // Stop memory tracking (if enabled) - #[cfg(feature = "memory_tracking")] - { - use std::sync::atomic::Ordering; - debug!("Joining memory thread."); - done.store(true, Ordering::Relaxed); - if let Err(e) = mem_thread_handle.join().unwrap() { - log::error!("Couldn't join memory tracking thread: {}", e); - } - } - } - - if bench_conf.args.print_info { - benchmark_helpers::print_info(queue_name.to_string(), bench_conf)?; - } - - Ok(()) -} - -pub struct SetupResult { - pub bench_conf: benchmark_helpers::BenchConfig, - pub queue_conf: QueueArgs, - pub columns: String, // Optional, but alreadyy written (TODO: have a stream of some sort here) -} - -/// Set up the actual benchmark. -/// -/// All work unrelated to the chosen benchmark is done here. -pub fn setup_benchmark() -> Result { - let args = crate::arguments::Args::parse(); - - let queue_args = match &args.benchmark { - BenchmarkTypes::Queue(queue_args) => queue_args.clone(), - _ => panic!( - "Trying to run a queue benchmark with another benchmark type" - ), - }; - - let date_time = Local::now().format("%Y%m%d%H%M%S").to_string(); - // Create benchmark hashed id - let benchmark_id = { - let mut hasher = DefaultHasher::new(); - date_time.hash(&mut hasher); - format!("{:x}", hasher.finish()) - }; - - debug!("Benchmark ID: {}", benchmark_id); - debug!("Arguments: {:?}", args); - - // Create dir if it doesnt already exist. - if !std::path::Path::new(&args.path_output).exists() { - std::fs::create_dir(&args.path_output)?; - } - - let output_filename = format!("{}/{}", args.path_output, date_time); - let bench_conf = benchmark_helpers::BenchConfig { - args, - date_time, - benchmark_id, - output_filename, - }; - - let columns = match queue_args.benchmark_runner { - QueueBenchmarks::BFS(_) => { - "Milliseconds,Queuetype,Thread Count,Test ID" - }, - _ => { - "Throughput,Enqueues,Dequeues,Consumers,Producers,Thread Count,Queuetype,Benchmark,Test ID,Fairness,Spread,Queue Size" - } - }; - - if bench_conf.args.write_to_stdout { - println!("{columns}") - } else { - let mut file = OpenOptions::new() - .append(true) - .create(true) - .open(&bench_conf.output_filename)?; - writeln!(file, "{columns}")?; - } - - Ok(SetupResult { - bench_conf, - queue_conf: queue_args, - columns: columns.to_string(), - }) -} diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs b/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs deleted file mode 100644 index fa6d637..0000000 --- a/benchmark_core/src/benchmarks/queue_benchmarks/bfs.rs +++ /dev/null @@ -1,330 +0,0 @@ -use crate::arguments::{QueueBFSArgs, BenchmarkTypes, QueueBenchmarks}; -use crate::traits::{ConcurrentQueue, HandleQueue}; -use crate::benchmarks::benchmark_helpers; -use std::{fs::OpenOptions, sync::{atomic::{AtomicUsize, Ordering}, Barrier}}; -use core_affinity::CoreId; -use log::{debug, error, info, trace}; -use std::fs::File; -use std::io::{BufRead, BufReader, Write}; - - -/// Generates the graph, generates the sequential solution and gets which -/// node to start at. -pub fn pre_bfs_work(cqueue: C, args: &QueueBFSArgs) - -> (Vec>, Vec, usize) -where -C: ConcurrentQueue, - for<'a> &'a C: Send -{ - info!("Loading graph now..."); - let graph = create_graph( - args.graph_file.clone(), - ).unwrap(); - // Find start node. Currently finds node with most neighbours. - let mut biggest = 0; - let mut curr = 0; - for (i, edge) in graph.iter().enumerate() { - if edge.len() > biggest { - biggest = edge.len(); - curr = i; - } - } - info!("Generating correct solution..."); - debug!("Start node is: {curr}"); - - let seq_ret_vec = if !args.no_verify { - sequential_bfs(cqueue, &graph, curr) // TODO: Use a better generic sequential queue - } else { - vec![] - }; - (graph, seq_ret_vec, curr) -} - -/* -arr[] -dist_to_start_node -*/ - -/// Explanation: -/// A benchmark to test how fast your data structure can complete a Breadth-First Search (BFS) -/// and if it does so correctly. -/// Need to send in your data structure and the graph you want to do bfs on (only .mtx files allowed). -/// Benchmark specififc flags: -/// * `--graph-file` The .mtx graph file you want to use in your bfs. -/// * `--thread-count` (OPTIONAL) The amount of threads you want to have in your benchmark (if left out, standard 20). -/// * `--no-verify` (OPTIONAL) Boolean to opt out of verifying the parallel benchmark results against the sequential (standard false). -/// -/// Ex. run: -/// cargo run -features data_structure,bfs -- bfs --graph-file graph.mtx -pub fn benchmark_bfs ( - cqueue: C, - graph: &[Vec], - bench_conf: &benchmark_helpers::BenchConfig, - seq_ret_vec: &[usize], - start_node: usize, - ) -> Result<(), std::io::Error> -where -C: ConcurrentQueue, - for<'a> &'a C: Send -{ - let args = match &bench_conf.args.benchmark { - BenchmarkTypes::Queue(args) => match &args.benchmark_runner { - QueueBenchmarks::BFS(a) => a, - _ => panic!(), - } - _ => panic!(), - }; - let thread_count = args.thread_count; - debug!("Starting parallell BFS now"); - let (dur_par, par_ret_vec) = parallell_bfs(&cqueue, graph, start_node, thread_count, bench_conf); - debug!("Graph traversal done. Took {:?}.", dur_par); - - if !args.no_verify { - debug!("Comparing results to the sequential solution"); - for (i, node) in par_ret_vec.iter().enumerate() { - trace!("Pos: {} Parallell: {} Sequential: {}", i, *node, seq_ret_vec[i]); - if *node != seq_ret_vec[i] { - error!("Parallell BFS solution arrived at wrong answer."); - return Ok(()); - } - } - debug!("Solution looks good."); - } - let formatted = format!("{},{},{},{}", - dur_par.as_millis(), - cqueue.get_id(), - args.thread_count, - bench_conf.benchmark_id); - if !bench_conf.args.write_to_stdout { - let mut file = OpenOptions::new() - .append(true) - .create(true) - .open(&bench_conf.output_filename)?; - - writeln!(file, "{}", formatted)?; - - } else { - println!("{}", formatted); - } - - Ok(()) -} - -fn parallell_bfs ( - cqueue: &C, - graph: &[Vec], - start_node: usize, - thread_count: usize, - bench_conf: &benchmark_helpers::BenchConfig) --> (std::time::Duration, Vec) -where -C: ConcurrentQueue, - for<'a> &'a C: Send -{ - - let result_vector: Vec = - (0..graph.len()).map(|_| AtomicUsize::new(usize::MAX)).collect(); - - // Set distance of first node - result_vector[start_node].store(0, Ordering::Relaxed); - - let idle_count: AtomicUsize = AtomicUsize::new(0); - let no_work_count: AtomicUsize = AtomicUsize::new(0); - let barrier = Barrier::new(thread_count + 1); - // Add start node to queue - let _ = cqueue.register().push(start_node); - - // Get cores for fairness of threads - let available_cores: Vec = - core_affinity::get_core_ids().unwrap_or(vec![CoreId { id: 0 }]); - let mut core_iter = available_cores.into_iter().cycle(); - - let scope_result = std::thread::scope(|s| -> Result{ - let idle_count = &idle_count; - let no_work_count = &no_work_count; - let barrier = &barrier; - let result_vector = &result_vector; - let mut handles = vec![]; - let is_one_socket = &bench_conf.args.one_socket; - for i in 0..thread_count { - handles.push({ - let mut core : CoreId = core_iter.next().unwrap(); - // if is_one_socket is true, make all thread ids even - // (this was used for our testing enviroment to get one socket) - if *is_one_socket { - core = core_iter.next().unwrap(); - } - s.spawn(move|| { - core_affinity::set_for_current(core); - // Register queue - let handle = cqueue.register(); - // Wait for other queues - barrier.wait(); - // Start BFS - pbfs_helper( - handle, - result_vector, - graph, - i, - no_work_count, - idle_count, - thread_count - ); - }) - }); - } - barrier.wait(); - let start = std::time::Instant::now(); - for handle in handles { - handle.join().unwrap(); - } - let duration = start.elapsed(); - Ok(duration) - }); - let duration = scope_result.expect("Should never return error"); - let ret_vec: Vec = result_vector - .iter() - .map(|val| val.load(Ordering::Relaxed)) - .collect(); - trace!("Parallell sol: {:?}", ret_vec); - (duration, ret_vec) -} - -fn pbfs_helper( - mut handle: impl HandleQueue, - result_vector: &[AtomicUsize], - graph: &[Vec], - i: usize, - no_work_count: &AtomicUsize, - idle_count: &AtomicUsize, - thread_count: usize) -{ - let mut next = None; - loop { - if next.is_none() { - next = handle.pop(); - } - match next { - Some(node) => { - next = None; - trace!("Thread: {i}; Acquired node {node}"); - let distance = result_vector[node].load(Ordering::SeqCst); - for neighbour in &graph[node] { - let mut n_distance = result_vector[*neighbour].load(Ordering::SeqCst); - while distance + 1 < n_distance { - if result_vector[*neighbour].compare_exchange_weak( - n_distance, - distance + 1, - Ordering::SeqCst, - Ordering::SeqCst) - .is_ok() - { - match handle.push(*neighbour) { - Err(e) => { - error!("Failed to push to queue: {e}"); - continue; - }, - Ok(_) => { - trace!("Thread: {i}; Pushed {}", *neighbour); - break; - }, - } - } - n_distance = result_vector[*neighbour].load(Ordering::SeqCst); - } - } - }, - None => { - trace!("Thread: {i}; Did not acquire any work"); - no_work_count.fetch_add(1, Ordering::Relaxed); - loop { - next = handle.pop(); - if next.is_some() { break; } - if no_work_count.load(Ordering::Relaxed) >= thread_count - && should_terminate(idle_count, no_work_count, thread_count) - { - return; - } - } - no_work_count.fetch_sub(1, Ordering::Relaxed); - } - } - } -} - -fn should_terminate(idle_count: &AtomicUsize, no_work_count: &AtomicUsize, thread_count: usize) -> bool { - idle_count.fetch_add(1, Ordering::Relaxed); - while no_work_count.load(Ordering::Relaxed) >= thread_count { - if idle_count.load(Ordering::Relaxed) >= thread_count { - return true; - } - //PAUSE? no-op - std::hint::spin_loop(); - } - idle_count.fetch_sub(1, Ordering::Relaxed); - false -} - -fn sequential_bfs(cqueue: C, graph: &[Vec], start_node: usize) -> Vec -where -C: ConcurrentQueue, - for<'a> &'a C: Send -{ - let mut result_vector: Vec = (0..graph.len()).map(|_| usize::MAX).collect(); - let mut visited: std::collections::HashSet = std::collections::HashSet::new(); - let mut q = cqueue.register(); - result_vector[start_node] = 0; - if q.push(start_node).is_err() { - error!("Failed to start BFS, couldn't push start node"); - } - while let Some(node) = q.pop() { - let distance = result_vector[node]; - for n in &graph[node] { - if visited.contains(n) { - continue; - } - let n_distance = result_vector[*n]; - if n_distance > distance + 1 { - result_vector[*n] = distance + 1; - } - if q.push(*n).is_err() { - error!("Failed to push in sequential BFS"); - } - visited.insert(*n); - } - } - trace!("Sequential sol: {:?}", result_vector); - result_vector -} - -pub fn create_graph(graph_file: String) -> Result>, std::io::Error> { - let file = File::open(graph_file)?; - let reader = BufReader::new(file); - - let mut edges = Vec::new(); - for line in reader.lines() { - let line = line?; - if line.starts_with('%') { - continue; - } - - let edge: Vec = line.split(' ') - .map(|n| n.parse::().expect("File populated with non-integers")) - .collect(); - - edges.push(edge); - } - - let size = edges[0][0] + 1; // in case graph is not zero-indexed. - let mut graph: Vec> = vec![Vec::new(); size]; - - for edge in edges.iter().skip(1) { - let src = edge[0]; - let dst = edge[1]; - graph[src].push(dst); - } - - Ok(graph) -} -// Milliseconds,Queuetype,Thread Count,Test ID - diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs deleted file mode 100644 index ddd2b67..0000000 --- a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq.rs +++ /dev/null @@ -1,246 +0,0 @@ -use core_affinity::CoreId; -use log::{debug, error, info, trace}; -use rand::Rng; -use crate::arguments::{BenchmarkTypes, QueueBenchmarks}; -use crate::traits::{ConcurrentQueue, HandleQueue}; -use crate::benchmarks::benchmark_helpers; -use std::fs::OpenOptions; -use std::io::Write; -use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; -use std::sync::{mpsc, Arc}; - -/// # Explanation: -/// A benchmark that measures the throughput of a queue. -/// Here threads vary between producers and consumers, -/// Benchmark specific flags: -/// * --spread Set the spread of consumers/producers, value between 0 - 1. Ex. --spread 0.3, gives 30% consume, 70% produce -/// * --thread-count Set the amount of threads to run in the benchmark -#[allow(dead_code)] -pub fn benchmark_enq_deq (cqueue: C, bench_conf: &benchmark_helpers::BenchConfig) -> Result<(), std::io::Error> -where -C: ConcurrentQueue, -T: Default, - for<'a> &'a C: Send -{ - let args = match &bench_conf.args.benchmark { - BenchmarkTypes::Queue(args) => match &args.benchmark_runner { - QueueBenchmarks::EnqDeq(a) => a, - _ => panic!(), - } - _ => panic!(), - }; - - let queue_args = match &bench_conf.args.benchmark { - BenchmarkTypes::Queue(queue_args) => queue_args.clone(), - _ => panic!( - "Trying to run a queue benchmark with another benchmark type" - ), - }; - - { - debug!("Prefilling queue with {} items.", bench_conf.args.prefill_amount); - let mut tmp_handle = cqueue.register(); - for _ in 0..bench_conf.args.prefill_amount { - let _ = tmp_handle.push(Default::default()); - } - } - let thread_count = args.thread_count; - let time_limit: u64 = bench_conf.args.time_limit; - let barrier = Barrier::new(thread_count + 1); - let pops = AtomicUsize::new(0); - let pushes = AtomicUsize::new(0); - let done = AtomicBool::new(false); - let (tx, rx) = mpsc::channel(); - info!("Starting pingpong benchmark with {} threads", thread_count); - - - - // Get cores for fairness of threads - let available_cores: Vec = - core_affinity::get_core_ids().unwrap_or(vec![CoreId { id: 0 }]); - let mut core_iter = available_cores.into_iter().cycle(); - - // Shared atomic bool for when a thread fails - let thread_failed = Arc::new(AtomicBool::new(false)); - - - let _ = std::thread::scope(|s| -> Result<(), std::io::Error>{ - let queue = &cqueue; - let thread_failed = &thread_failed; // Every thread clones the thread_failed bool - let pushes = &pushes; - let pops = &pops; - let done = &done; - let barrier = &barrier; - let &thread_count = &thread_count; - let &spread = &args.spread; - let is_one_socket = &bench_conf.args.one_socket; - let tx = &tx; - for _i in 0..thread_count{ - let mut core : CoreId = core_iter.next().unwrap(); - // if is_one_socket is true, make all thread ids even - // (this was used for our testing enviroment to get one socket) - if *is_one_socket { - core = core_iter.next().unwrap(); - } - // println!("{:?}", core); - s.spawn(move || { - let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - core_affinity::set_for_current(core); - let mut handle = queue.register(); - let mut l_pushes = 0; - let mut l_pops = 0; - let _thread_failed = thread_failed.clone(); - barrier.wait(); - while !done.load(Ordering::Relaxed) { - let random_float = rand::rng().random::(); - if random_float > spread { - match handle.pop() { - Some(_) => l_pops += 1, - None => { - if queue_args.empty_pops { - l_pops += 1; - } - } - } - } else { - let _ = handle.push(T::default()); - l_pushes += 1; - } - for _ in 0..bench_conf.args.delay { - let _some_num = rand::rng().random::(); - } - } - - pushes.fetch_add(l_pushes, Ordering::Relaxed); - pops.fetch_add(l_pops, Ordering::Relaxed); - tx.send(l_pops + l_pushes).unwrap(); - trace!("{}: Pushed: {}, Popped: {}", _i, l_pushes, l_pops); - })); - // A thread panicked, aborting the benchmark... - if let Err(e) = result { - error!("Thread {} panicked: {:?}. Aborting benchmark, padding results to zero", _i, e); - thread_failed.store(true, Ordering::Relaxed); - done.store(true, Ordering::Relaxed); - } - }); - - } - barrier.wait(); - std::thread::sleep(std::time::Duration::from_secs(time_limit)); - done.store(true, Ordering::Relaxed); - Ok(()) - }); - drop(tx); - let pops = pops.into_inner(); - let pushes = pushes.into_inner(); - // Fairness - let ops_per_thread = { - let mut vals = vec![]; - for received in rx { - vals.push(received); - } - vals - }; - let fairness = benchmark_helpers::calc_fairness(ops_per_thread); - - // If a thread crashed, pad the results with zero-values - let formatted = if thread_failed.load(Ordering::Relaxed) { - format!("0,0,0,-1,-1,{},{},{},{},0,{},{}", - thread_count, - cqueue.get_id(), - bench_conf.args.benchmark, - bench_conf.benchmark_id, - args.spread, - queue_args.queue_size - ) - } - else { - format!("{},{},{},{},{},{},{},{},{},{},{},{}", - (pushes + pops) as f64 / time_limit as f64, - pushes, - pops, - -1, - -1, - thread_count, - cqueue.get_id(), - bench_conf.args.benchmark, - bench_conf.benchmark_id, - fairness, - args.spread, - queue_args.queue_size) - }; - // Write to file or stdout depending on flag - if !bench_conf.args.write_to_stdout { - let mut file = OpenOptions::new() - .append(true) - .create(true) - .open(&bench_conf.output_filename)?; - writeln!(file, "{}", formatted)?; - } else { - println!("{}", formatted); - } - Ok(()) -} - -#[cfg(test)] -mod tests { - use crate::arguments::Args; - use crate::arguments::QueueBenchmarks; - use crate::arguments::QueueEnqDeqArgs; - use crate::arguments::QueueArgs; - use crate::benchmarks::queue_benchmarks::enq_deq::benchmark_enq_deq; - - use super::*; - - use crate::benchmarks::test_helpers::test_queue::TestQueue; - - #[test] - fn run_pingpong() { - let args = Args { - benchmark: BenchmarkTypes::Queue(QueueArgs { - empty_pops: Default::default(), - queue_size: 10000, - benchmark_runner: QueueBenchmarks::EnqDeq(QueueEnqDeqArgs { - thread_count: 10, - spread: 0.5, - }) - }), - ..Default::default() - }; - let bench_conf = benchmark_helpers::BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test2".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_enq_deq(queue, &bench_conf).is_err() { - panic!(); - } - } - - #[test] - fn run_pingpong_with_bool() { - let args = Args { - benchmark: BenchmarkTypes::Queue(QueueArgs { - empty_pops: Default::default(), - queue_size: 10000, - benchmark_runner: QueueBenchmarks::EnqDeq(QueueEnqDeqArgs { - thread_count: 10, - spread: 0.5, - }) - }), - ..Default::default() - }; - let bench_conf = benchmark_helpers::BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test2".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_enq_deq(queue, &bench_conf).is_err() { - panic!(); - } - } -} diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs b/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs deleted file mode 100644 index 723e2fc..0000000 --- a/benchmark_core/src/benchmarks/queue_benchmarks/enq_deq_pairs.rs +++ /dev/null @@ -1,203 +0,0 @@ -use core_affinity::CoreId; -use log::{debug, error, info, trace}; -use rand::Rng; -use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; -use crate::arguments::{BenchmarkTypes, QueueBenchmarks}; -use crate::traits::{ConcurrentQueue, HandleQueue}; -use crate::benchmarks::benchmark_helpers; -use std::fs::OpenOptions; -use std::io::Write; -use std::sync::{mpsc, Arc}; - -/// # Explanation: -#[allow(dead_code)] -pub fn benchmark_enq_deq_pairs (cqueue: C, bench_conf: &benchmark_helpers::BenchConfig) -> Result<(), std::io::Error> -where -C: ConcurrentQueue, -T: Default, - for<'a> &'a C: Send -{ - let args = match &bench_conf.args.benchmark { - BenchmarkTypes::Queue(args) => match &args.benchmark_runner { - QueueBenchmarks::EnqDeqPairs(a) => a, - _ => panic!(), - } - _ => panic!(), - }; - - let queue_args = match &bench_conf.args.benchmark { - BenchmarkTypes::Queue(queue_args) => queue_args.clone(), - _ => panic!( - "Trying to run a queue benchmark with another benchmark type" - ), - }; - - { - debug!("Prefilling queue with {} items.", bench_conf.args.prefill_amount); - let mut tmp_handle = cqueue.register(); - for _ in 0..bench_conf.args.prefill_amount { - let _ = tmp_handle.push(Default::default()); - } - } - let thread_count = args.thread_count; - let time_limit: u64 = bench_conf.args.time_limit; - let barrier = Barrier::new(thread_count + 1); - let pops = AtomicUsize::new(0); - let pushes = AtomicUsize::new(0); - let done = AtomicBool::new(false); - let (tx, rx) = mpsc::channel(); - info!("Starting pingpong benchmark with {} threads", thread_count); - - - - // Get cores for fairness of threads - let available_cores: Vec = - core_affinity::get_core_ids().unwrap_or(vec![CoreId { id: 0 }]); - let mut core_iter = available_cores.into_iter().cycle(); - - // Shared atomic bool for when a thread fails - let thread_failed = Arc::new(AtomicBool::new(false)); - - - let _ = std::thread::scope(|s| -> Result<(), std::io::Error>{ - let queue = &cqueue; - let thread_failed = &thread_failed; // Every thread clones the thread_failed bool - let pushes = &pushes; - let pops = &pops; - let done = &done; - let barrier = &barrier; - let &thread_count = &thread_count; - let is_one_socket = &bench_conf.args.one_socket; - let tx = &tx; - for _i in 0..thread_count{ - let mut core : CoreId = core_iter.next().unwrap(); - // if is_one_socket is true, make all thread ids even - // (this was used for our testing enviroment to get one socket) - if *is_one_socket { - core = core_iter.next().unwrap(); - } - // println!("{:?}", core); - s.spawn(move || { - let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - core_affinity::set_for_current(core); - let mut handle = queue.register(); - let mut l_pushes = 0; - let mut l_pops = 0; - let _thread_failed = thread_failed.clone(); - barrier.wait(); - while !done.load(Ordering::Relaxed) { - let _ = handle.push(T::default()); - l_pushes += 1; - let _ = handle.pop(); - l_pops += 1; - for _ in 0..bench_conf.args.delay { - let _some_num = rand::rng().random::(); - } - } - pushes.fetch_add(l_pushes, Ordering::Relaxed); - pops.fetch_add(l_pops, Ordering::Relaxed); - tx.send(l_pops + l_pushes).unwrap(); - trace!("{}: Pushed: {}, Popped: {}", _i, l_pushes, l_pops); - })); - // A thread panicked, aborting the benchmark... - if let Err(e) = result { - error!("Thread {} panicked: {:?}. Aborting benchmark, padding results to zero", _i, e); - thread_failed.store(true, Ordering::Relaxed); - done.store(true, Ordering::Relaxed); - } - }); - - } - barrier.wait(); - std::thread::sleep(std::time::Duration::from_secs(time_limit)); - done.store(true, Ordering::Relaxed); - Ok(()) - }); - drop(tx); - let pops = pops.into_inner(); - let pushes = pushes.into_inner(); - // Fairness - let ops_per_thread = { - let mut vals = vec![]; - for received in rx { - vals.push(received); - } - vals - }; - let fairness = benchmark_helpers::calc_fairness(ops_per_thread); - - // If a thread crashed, pad the results with zero-values - let formatted = if thread_failed.load(Ordering::Relaxed) { - format!("0,0,0,-1,-1,{},{},{},{},0,{},{}", - thread_count, - cqueue.get_id(), - bench_conf.args.benchmark, - bench_conf.benchmark_id, - -1, - queue_args.queue_size - ) - } - else { - format!("{},{},{},{},{},{},{},{},{},{},{},{}", - (pushes + pops) as f64 / time_limit as f64, - pushes, - pops, - -1, - -1, - thread_count, - cqueue.get_id(), - bench_conf.args.benchmark, - bench_conf.benchmark_id, - fairness, - -1, - queue_args.queue_size) - }; - // Write to file or stdout depending on flag - if !bench_conf.args.write_to_stdout { - let mut file = OpenOptions::new() - .append(true) - .create(true) - .open(&bench_conf.output_filename)?; - writeln!(file, "{}", formatted)?; - } else { - println!("{}", formatted); - } - Ok(()) -} - -#[cfg(test)] -mod tests { - use crate::arguments::Args; - use crate::arguments::QueueEnqDeqPairsArgs; - use crate::arguments::QueueBenchmarks; - use crate::arguments::QueueArgs; - use crate::benchmarks::queue_benchmarks::enq_deq_pairs::benchmark_enq_deq_pairs; - - use super::*; - - use crate::benchmarks::test_helpers::test_queue::TestQueue; - - #[test] - fn run_enqdeq_pairs_with_struct() { - let args = Args { - benchmark: BenchmarkTypes::Queue(QueueArgs { - empty_pops: Default::default(), - queue_size: 10000, - benchmark_runner: QueueBenchmarks::EnqDeqPairs(QueueEnqDeqPairsArgs { - thread_count: 10, - }) - }), - ..Default::default() - }; - let bench_conf = benchmark_helpers::BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test2".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_enq_deq_pairs(queue, &bench_conf).is_err() { - panic!(); - } - } -} diff --git a/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs b/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs deleted file mode 100644 index 1017ea8..0000000 --- a/benchmark_core/src/benchmarks/queue_benchmarks/prod_con.rs +++ /dev/null @@ -1,273 +0,0 @@ -use core_affinity::CoreId; -use log::{debug, error, info, trace}; -use rand::Rng; -use crate::arguments::{BenchmarkTypes, QueueBenchmarks}; -use crate::traits::{ConcurrentQueue, HandleQueue}; -use crate::benchmarks::benchmark_helpers; -use std::fs::OpenOptions; -use std::io::Write; -use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; -use std::sync::{mpsc, Arc}; - -/// # Explanation: -/// A simple benchmark that measures the throughput of a queue. -/// Has by default a 10 floating points generated delay between each operation, but this can be changed -/// through flags passed to the program. -/// Benchmark specific flags: -/// * -p Set specified amount of producers -/// * -c Set specified amount of consumers -#[allow(dead_code)] -pub fn benchmark_prod_con(cqueue: C, bench_conf: &benchmark_helpers::BenchConfig) -> Result<(), std::io::Error> -where - C: ConcurrentQueue, - T: Default, - for<'a> &'a C: Send -{ - let args = match &bench_conf.args.benchmark { - BenchmarkTypes::Queue(args) => match &args.benchmark_runner { - QueueBenchmarks::ProdCon(a) => a, - _ => panic!(), - } - _ => panic!(), - }; - - let queue_args = match &bench_conf.args.benchmark { - BenchmarkTypes::Queue(queue_args) => queue_args.clone(), - _ => panic!( - "Trying to run a queue benchmark with another benchmark type" - ), - }; - - { - debug!("Prefilling queue with {} items.", bench_conf.args.prefill_amount); - let mut tmp_handle = cqueue.register(); - for _ in 0..bench_conf.args.prefill_amount { - let _ = tmp_handle.push(Default::default()); - } - } - let producers = args.producers; - let consumers = args.consumers; - - let time_limit: u64 = bench_conf.args.time_limit; - let barrier = Barrier::new(consumers + producers + 1); - let pops = AtomicUsize::new(0); - let pushes = AtomicUsize::new(0); - let done = AtomicBool::new(false); - let (tx, rx) = mpsc::channel(); - info!("Starting throughput benchmark with {} consumer and {} producers", consumers, producers); - - // get cores for fairness of threads - let available_cores: Vec = - core_affinity::get_core_ids().unwrap_or(vec![CoreId { id: 0 }]); - let mut core_iter = available_cores.into_iter().cycle(); - - // Shared atomic bool for when a thread fails - let thread_failed = Arc::new(AtomicBool::new(false)); - - let _ = std::thread::scope(|s| -> Result<(), std::io::Error>{ - let queue = &cqueue; - let pushes = &pushes; - let pops = &pops; - let done = &done; - let barrier = &barrier; - let tx = &tx; - let &consumers = &consumers; - let &producers = &producers; - let is_one_socket = &bench_conf.args.one_socket; - let thread_failed = &thread_failed; - - for i in 0..producers{ - let mut core : CoreId = core_iter.next().unwrap(); - // if is_one_socket is true, make all thread ids even - // (this was used for our testing enviroment to get one socket) - if *is_one_socket { - core = core_iter.next().unwrap(); - } - trace!("Thread: {} Core: {:?}", i, core); - s.spawn(move || { - let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - core_affinity::set_for_current(core); - let mut handle = queue.register(); - // push - let mut l_pushes = 0; - let _thread_failed = thread_failed.clone(); // Every thread clones the thread_failed bool - barrier.wait(); - while !done.load(Ordering::Relaxed) { - // NOTE: Maybe we should care about this result? - let _ = handle.push(T::default()); - l_pushes += 1; - // Add some delay to simulate real workload - for _ in 0..bench_conf.args.delay { - let _some_num = rand::rng().random::(); - } - } - pushes.fetch_add(l_pushes, Ordering::Relaxed); - // Thread sends its total operations down the channel for fairness calculations - if let Err(e) = tx.send(l_pushes) { - error!("Error sending operations down the channel: {}", e); - }; - })); - // A thread panicked, aborting the benchmark... - if let Err (e) = result { - error!("Thread {} panicked in pushing: {:?}. Aborting benchmark, padding results to zero", i, e); - thread_failed.store(true, Ordering::Relaxed); - done.store(true, Ordering::Relaxed); - } - }); - } - for i in 0..consumers { - let mut core : CoreId = core_iter.next().expect("Core iter error"); - // if is_one_socket is true, make all thread ids even - // (this was used for our testing enviroment to get one socket) - if *is_one_socket { - core = core_iter.next().unwrap(); - } - trace!("Thread: {} Core: {:?}", i, core); - - s.spawn(move || { - let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - core_affinity::set_for_current(core); - let mut handle = queue.register(); - // pop - let mut l_pops = 0; - let mut empty_pops = 0; - let _thread_failed = thread_failed.clone(); // Every thread clones the thread_failed bool - barrier.wait(); - // TODO: add empty pops probably to fairness calculations - while !done.load(Ordering::Relaxed) { - match handle.pop() { - Some(_) => l_pops += 1, - None => { - // if bench_conf.args.empty_pops { - // l_pops += 1; - // } - empty_pops += 1; - } - } - for _ in 0..bench_conf.args.delay { - let _some_num = rand::rng().random::(); - } - } - pops.fetch_add(l_pops, Ordering::Relaxed); - // Thread sends its total operations down the channel for fairness calculations - if let Err(e) = tx.send(l_pops + empty_pops) { - error!("Error sending operations down the channel: {}", e); - }; - })); - // A thread panicked, aborting the benchmark... - if let Err(e) = result { - error!("Thread {} panicked while popping: {:?}. Aborting benchmark, padding results to zero", i, e); - thread_failed.store(true, Ordering::Relaxed); - done.store(true, Ordering::Relaxed); - } - }); - } - debug!("Waiting for barrier"); - barrier.wait(); - debug!("Done waiting for barrier. Going to sleep."); - std::thread::sleep(std::time::Duration::from_secs(time_limit)); - done.store(true, Ordering::Relaxed); - Ok(()) - }); - drop(tx); - debug!("TX Dropped"); - let pops = pops.into_inner(); - let pushes = pushes.into_inner(); - - // Fairness - // Get total operations per thread - let ops_per_thread = { - let mut vals = vec![]; - for received in rx { - vals.push(received); - }; - vals - }; - // If a thread crashed, pad the results with zero-values - let formatted = if thread_failed.load(Ordering::Relaxed) { - format!("0,0,0,{},{},-1,{},{},{},0,-1,{}", producers, consumers, cqueue.get_id(), bench_conf.args.benchmark, bench_conf.benchmark_id, queue_args.queue_size) - } - else { - let fairness = benchmark_helpers::calc_fairness(ops_per_thread); - format!("{},{},{},{},{},{},{},{},{},{},{},{}", - (pushes + pops) as f64 / time_limit as f64, - pushes, - pops, - consumers, - producers, - -1, - cqueue.get_id(), - bench_conf.args.benchmark, - bench_conf.benchmark_id, - fairness, - -1, - queue_args.queue_size) - }; - if !bench_conf.args.write_to_stdout { - let mut file = OpenOptions::new() - .append(true) - .create(true) - .open(&bench_conf.output_filename)?; - - writeln!(file, "{}", formatted)?; - - } else { - println!("{}", formatted); - } - - Ok(()) -} - - -#[cfg(test)] -mod tests { - use super::*; - - use crate::arguments::Args; - use crate::benchmarks::test_helpers::test_queue::TestQueue; - - #[test] - fn run_basic_prod_con() { - let args = Args::default(); - let bench_conf = benchmark_helpers::BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test1".to_string(), - output_filename: "".to_string() - }; - let queue: TestQueue = TestQueue::new(0); - if benchmark_prod_con(queue, &bench_conf).is_err() { - panic!(); - } - } - - #[test] - fn run_basic_with_string() { - let args = Args::default(); - let bench_conf = benchmark_helpers::BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test1".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_prod_con(queue, &bench_conf).is_err() { - panic!(); - } - } - - #[test] - fn run_basic_with_struct() { - let args = Args::default(); - let bench_conf = benchmark_helpers::BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test1".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_prod_con(queue, &bench_conf).is_err() { - panic!(); - } - } -} diff --git a/data_structures/queues/array_queue/Cargo.toml b/data_structures/fifo_queues/array_queue/Cargo.toml similarity index 100% rename from data_structures/queues/array_queue/Cargo.toml rename to data_structures/fifo_queues/array_queue/Cargo.toml diff --git a/data_structures/queues/array_queue/src/lib.rs b/data_structures/fifo_queues/array_queue/src/lib.rs similarity index 100% rename from data_structures/queues/array_queue/src/lib.rs rename to data_structures/fifo_queues/array_queue/src/lib.rs diff --git a/data_structures/fifo_queues/array_queue/src/main.rs b/data_structures/fifo_queues/array_queue/src/main.rs new file mode 100644 index 0000000..450696e --- /dev/null +++ b/data_structures/fifo_queues/array_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("array_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/atomic_queue/Cargo.toml b/data_structures/fifo_queues/atomic_queue/Cargo.toml similarity index 100% rename from data_structures/queues/atomic_queue/Cargo.toml rename to data_structures/fifo_queues/atomic_queue/Cargo.toml diff --git a/data_structures/queues/atomic_queue/src/lib.rs b/data_structures/fifo_queues/atomic_queue/src/lib.rs similarity index 100% rename from data_structures/queues/atomic_queue/src/lib.rs rename to data_structures/fifo_queues/atomic_queue/src/lib.rs diff --git a/data_structures/fifo_queues/atomic_queue/src/main.rs b/data_structures/fifo_queues/atomic_queue/src/main.rs new file mode 100644 index 0000000..188c1f1 --- /dev/null +++ b/data_structures/fifo_queues/atomic_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("atomic_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/basic_queue/Cargo.toml b/data_structures/fifo_queues/basic_queue/Cargo.toml similarity index 100% rename from data_structures/queues/basic_queue/Cargo.toml rename to data_structures/fifo_queues/basic_queue/Cargo.toml diff --git a/data_structures/queues/basic_queue/src/lib.rs b/data_structures/fifo_queues/basic_queue/src/lib.rs similarity index 100% rename from data_structures/queues/basic_queue/src/lib.rs rename to data_structures/fifo_queues/basic_queue/src/lib.rs diff --git a/data_structures/fifo_queues/basic_queue/src/main.rs b/data_structures/fifo_queues/basic_queue/src/main.rs new file mode 100644 index 0000000..3d8e181 --- /dev/null +++ b/data_structures/fifo_queues/basic_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("basic_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/bbq/Cargo.toml b/data_structures/fifo_queues/bbq/Cargo.toml similarity index 100% rename from data_structures/queues/bbq/Cargo.toml rename to data_structures/fifo_queues/bbq/Cargo.toml diff --git a/data_structures/queues/bbq/src/lib.rs b/data_structures/fifo_queues/bbq/src/lib.rs similarity index 100% rename from data_structures/queues/bbq/src/lib.rs rename to data_structures/fifo_queues/bbq/src/lib.rs diff --git a/data_structures/queues/lcrq/src/main.rs b/data_structures/fifo_queues/bbq/src/main.rs similarity index 77% rename from data_structures/queues/lcrq/src/main.rs rename to data_structures/fifo_queues/bbq/src/main.rs index 4496b41..ff48662 100644 --- a/data_structures/queues/lcrq/src/main.rs +++ b/data_structures/fifo_queues/bbq/src/main.rs @@ -1,5 +1,5 @@ use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; fn main() { @@ -11,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_queue::>("array_queue") { + match benchmark_fifo_queue::>("BBQ") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/boost_queue_cpp/Cargo.toml b/data_structures/fifo_queues/boost_queue_cpp/Cargo.toml similarity index 100% rename from data_structures/queues/boost_queue_cpp/Cargo.toml rename to data_structures/fifo_queues/boost_queue_cpp/Cargo.toml diff --git a/data_structures/queues/boost_queue_cpp/build.rs b/data_structures/fifo_queues/boost_queue_cpp/build.rs similarity index 100% rename from data_structures/queues/boost_queue_cpp/build.rs rename to data_structures/fifo_queues/boost_queue_cpp/build.rs diff --git a/data_structures/queues/boost_queue_cpp/cpp_src/boost_wrapper.cpp b/data_structures/fifo_queues/boost_queue_cpp/cpp_src/boost_wrapper.cpp similarity index 100% rename from data_structures/queues/boost_queue_cpp/cpp_src/boost_wrapper.cpp rename to data_structures/fifo_queues/boost_queue_cpp/cpp_src/boost_wrapper.cpp diff --git a/data_structures/queues/boost_queue_cpp/cpp_src/boost_wrapper.hpp b/data_structures/fifo_queues/boost_queue_cpp/cpp_src/boost_wrapper.hpp similarity index 100% rename from data_structures/queues/boost_queue_cpp/cpp_src/boost_wrapper.hpp rename to data_structures/fifo_queues/boost_queue_cpp/cpp_src/boost_wrapper.hpp diff --git a/data_structures/queues/boost_queue_cpp/src/lib.rs b/data_structures/fifo_queues/boost_queue_cpp/src/lib.rs similarity index 100% rename from data_structures/queues/boost_queue_cpp/src/lib.rs rename to data_structures/fifo_queues/boost_queue_cpp/src/lib.rs diff --git a/data_structures/fifo_queues/boost_queue_cpp/src/main.rs b/data_structures/fifo_queues/boost_queue_cpp/src/main.rs new file mode 100644 index 0000000..1b6b9af --- /dev/null +++ b/data_structures/fifo_queues/boost_queue_cpp/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("boost_queue_cpp") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/bounded_concurrent_queue/Cargo.toml b/data_structures/fifo_queues/bounded_concurrent_queue/Cargo.toml similarity index 100% rename from data_structures/queues/bounded_concurrent_queue/Cargo.toml rename to data_structures/fifo_queues/bounded_concurrent_queue/Cargo.toml diff --git a/data_structures/queues/bounded_concurrent_queue/src/lib.rs b/data_structures/fifo_queues/bounded_concurrent_queue/src/lib.rs similarity index 100% rename from data_structures/queues/bounded_concurrent_queue/src/lib.rs rename to data_structures/fifo_queues/bounded_concurrent_queue/src/lib.rs diff --git a/data_structures/fifo_queues/bounded_concurrent_queue/src/main.rs b/data_structures/fifo_queues/bounded_concurrent_queue/src/main.rs new file mode 100644 index 0000000..e714c95 --- /dev/null +++ b/data_structures/fifo_queues/bounded_concurrent_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("bounded_concurrent_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/bounded_ringbuffer/Cargo.toml b/data_structures/fifo_queues/bounded_ringbuffer/Cargo.toml similarity index 100% rename from data_structures/queues/bounded_ringbuffer/Cargo.toml rename to data_structures/fifo_queues/bounded_ringbuffer/Cargo.toml diff --git a/data_structures/queues/bounded_ringbuffer/src/lib.rs b/data_structures/fifo_queues/bounded_ringbuffer/src/lib.rs similarity index 100% rename from data_structures/queues/bounded_ringbuffer/src/lib.rs rename to data_structures/fifo_queues/bounded_ringbuffer/src/lib.rs diff --git a/data_structures/fifo_queues/bounded_ringbuffer/src/main.rs b/data_structures/fifo_queues/bounded_ringbuffer/src/main.rs new file mode 100644 index 0000000..1562ebd --- /dev/null +++ b/data_structures/fifo_queues/bounded_ringbuffer/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("bounded_ringbuffer") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/faaa_queue/Cargo.toml b/data_structures/fifo_queues/faaa_queue/Cargo.toml similarity index 100% rename from data_structures/queues/faaa_queue/Cargo.toml rename to data_structures/fifo_queues/faaa_queue/Cargo.toml diff --git a/data_structures/queues/faaa_queue/src/lib.rs b/data_structures/fifo_queues/faaa_queue/src/lib.rs similarity index 100% rename from data_structures/queues/faaa_queue/src/lib.rs rename to data_structures/fifo_queues/faaa_queue/src/lib.rs diff --git a/data_structures/fifo_queues/faaa_queue/src/main.rs b/data_structures/fifo_queues/faaa_queue/src/main.rs new file mode 100644 index 0000000..f9529f0 --- /dev/null +++ b/data_structures/fifo_queues/faaa_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("faa_array_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/faaa_queue_cpp/Cargo.toml b/data_structures/fifo_queues/faaa_queue_cpp/Cargo.toml similarity index 100% rename from data_structures/queues/faaa_queue_cpp/Cargo.toml rename to data_structures/fifo_queues/faaa_queue_cpp/Cargo.toml diff --git a/data_structures/queues/faaa_queue_cpp/build.rs b/data_structures/fifo_queues/faaa_queue_cpp/build.rs similarity index 100% rename from data_structures/queues/faaa_queue_cpp/build.rs rename to data_structures/fifo_queues/faaa_queue_cpp/build.rs diff --git a/data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp b/data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp similarity index 100% rename from data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp rename to data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp diff --git a/data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp b/data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp similarity index 100% rename from data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp rename to data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp diff --git a/data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp b/data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp similarity index 100% rename from data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp rename to data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp diff --git a/data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp b/data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp similarity index 100% rename from data_structures/queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp rename to data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp diff --git a/data_structures/queues/faaa_queue_cpp/src/lib.rs b/data_structures/fifo_queues/faaa_queue_cpp/src/lib.rs similarity index 100% rename from data_structures/queues/faaa_queue_cpp/src/lib.rs rename to data_structures/fifo_queues/faaa_queue_cpp/src/lib.rs diff --git a/data_structures/fifo_queues/faaa_queue_cpp/src/main.rs b/data_structures/fifo_queues/faaa_queue_cpp/src/main.rs new file mode 100644 index 0000000..a8be8b0 --- /dev/null +++ b/data_structures/fifo_queues/faaa_queue_cpp/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("faaa_queue_cpp") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/lcrq/Cargo.toml b/data_structures/fifo_queues/lcrq/Cargo.toml similarity index 100% rename from data_structures/queues/lcrq/Cargo.toml rename to data_structures/fifo_queues/lcrq/Cargo.toml diff --git a/data_structures/queues/lcrq/src/lib.rs b/data_structures/fifo_queues/lcrq/src/lib.rs similarity index 100% rename from data_structures/queues/lcrq/src/lib.rs rename to data_structures/fifo_queues/lcrq/src/lib.rs diff --git a/data_structures/queues/array_queue/src/main.rs b/data_structures/fifo_queues/lcrq/src/main.rs similarity index 77% rename from data_structures/queues/array_queue/src/main.rs rename to data_structures/fifo_queues/lcrq/src/main.rs index e3b0f62..8bac1df 100644 --- a/data_structures/queues/array_queue/src/main.rs +++ b/data_structures/fifo_queues/lcrq/src/main.rs @@ -1,5 +1,5 @@ use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; fn main() { @@ -11,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_queue::>("array_queue") { + match benchmark_fifo_queue::>("array_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/lcrq_cpp/Cargo.toml b/data_structures/fifo_queues/lcrq_cpp/Cargo.toml similarity index 100% rename from data_structures/queues/lcrq_cpp/Cargo.toml rename to data_structures/fifo_queues/lcrq_cpp/Cargo.toml diff --git a/data_structures/queues/lcrq_cpp/build.rs b/data_structures/fifo_queues/lcrq_cpp/build.rs similarity index 100% rename from data_structures/queues/lcrq_cpp/build.rs rename to data_structures/fifo_queues/lcrq_cpp/build.rs diff --git a/data_structures/queues/lcrq_cpp/cpp_src/HazardPointers.hpp b/data_structures/fifo_queues/lcrq_cpp/cpp_src/HazardPointers.hpp similarity index 100% rename from data_structures/queues/lcrq_cpp/cpp_src/HazardPointers.hpp rename to data_structures/fifo_queues/lcrq_cpp/cpp_src/HazardPointers.hpp diff --git a/data_structures/queues/lcrq_cpp/cpp_src/LCRQueue.hpp b/data_structures/fifo_queues/lcrq_cpp/cpp_src/LCRQueue.hpp similarity index 100% rename from data_structures/queues/lcrq_cpp/cpp_src/LCRQueue.hpp rename to data_structures/fifo_queues/lcrq_cpp/cpp_src/LCRQueue.hpp diff --git a/data_structures/queues/lcrq_cpp/cpp_src/lcrq_wrapper.cpp b/data_structures/fifo_queues/lcrq_cpp/cpp_src/lcrq_wrapper.cpp similarity index 100% rename from data_structures/queues/lcrq_cpp/cpp_src/lcrq_wrapper.cpp rename to data_structures/fifo_queues/lcrq_cpp/cpp_src/lcrq_wrapper.cpp diff --git a/data_structures/queues/lcrq_cpp/cpp_src/lcrq_wrapper.hpp b/data_structures/fifo_queues/lcrq_cpp/cpp_src/lcrq_wrapper.hpp similarity index 100% rename from data_structures/queues/lcrq_cpp/cpp_src/lcrq_wrapper.hpp rename to data_structures/fifo_queues/lcrq_cpp/cpp_src/lcrq_wrapper.hpp diff --git a/data_structures/queues/lcrq_cpp/src/lib.rs b/data_structures/fifo_queues/lcrq_cpp/src/lib.rs similarity index 100% rename from data_structures/queues/lcrq_cpp/src/lib.rs rename to data_structures/fifo_queues/lcrq_cpp/src/lib.rs diff --git a/data_structures/fifo_queues/lcrq_cpp/src/main.rs b/data_structures/fifo_queues/lcrq_cpp/src/main.rs new file mode 100644 index 0000000..3f792ea --- /dev/null +++ b/data_structures/fifo_queues/lcrq_cpp/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("lcrq_cpp") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/lf_queue/Cargo.toml b/data_structures/fifo_queues/lf_queue/Cargo.toml similarity index 100% rename from data_structures/queues/lf_queue/Cargo.toml rename to data_structures/fifo_queues/lf_queue/Cargo.toml diff --git a/data_structures/queues/lf_queue/src/lib.rs b/data_structures/fifo_queues/lf_queue/src/lib.rs similarity index 100% rename from data_structures/queues/lf_queue/src/lib.rs rename to data_structures/fifo_queues/lf_queue/src/lib.rs diff --git a/data_structures/queues/atomic_queue/src/main.rs b/data_structures/fifo_queues/lf_queue/src/main.rs similarity index 75% rename from data_structures/queues/atomic_queue/src/main.rs rename to data_structures/fifo_queues/lf_queue/src/main.rs index 7c83935..e79475f 100644 --- a/data_structures/queues/atomic_queue/src/main.rs +++ b/data_structures/fifo_queues/lf_queue/src/main.rs @@ -1,5 +1,5 @@ use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; fn main() { @@ -11,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_queue::>("atomic_queue") { + match benchmark_fifo_queue::>("lf_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/lockfree_queue/Cargo.toml b/data_structures/fifo_queues/lockfree_queue/Cargo.toml similarity index 100% rename from data_structures/queues/lockfree_queue/Cargo.toml rename to data_structures/fifo_queues/lockfree_queue/Cargo.toml diff --git a/data_structures/queues/lockfree_queue/src/lib.rs b/data_structures/fifo_queues/lockfree_queue/src/lib.rs similarity index 100% rename from data_structures/queues/lockfree_queue/src/lib.rs rename to data_structures/fifo_queues/lockfree_queue/src/lib.rs diff --git a/data_structures/fifo_queues/lockfree_queue/src/main.rs b/data_structures/fifo_queues/lockfree_queue/src/main.rs new file mode 100644 index 0000000..8b28a75 --- /dev/null +++ b/data_structures/fifo_queues/lockfree_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("lockfree_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/lprq/Cargo.toml b/data_structures/fifo_queues/lprq/Cargo.toml similarity index 100% rename from data_structures/queues/lprq/Cargo.toml rename to data_structures/fifo_queues/lprq/Cargo.toml diff --git a/data_structures/queues/lprq/src/lib.rs b/data_structures/fifo_queues/lprq/src/lib.rs similarity index 100% rename from data_structures/queues/lprq/src/lib.rs rename to data_structures/fifo_queues/lprq/src/lib.rs diff --git a/data_structures/queues/lprq/src/lprq_rs.rs b/data_structures/fifo_queues/lprq/src/lprq_rs.rs similarity index 100% rename from data_structures/queues/lprq/src/lprq_rs.rs rename to data_structures/fifo_queues/lprq/src/lprq_rs.rs diff --git a/data_structures/queues/lcrq_cpp/src/main.rs b/data_structures/fifo_queues/lprq/src/main.rs similarity index 76% rename from data_structures/queues/lcrq_cpp/src/main.rs rename to data_structures/fifo_queues/lprq/src/main.rs index f4b9f01..11d1470 100644 --- a/data_structures/queues/lcrq_cpp/src/main.rs +++ b/data_structures/fifo_queues/lprq/src/main.rs @@ -1,5 +1,5 @@ use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; fn main() { @@ -11,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_queue::>("lcrq_cpp") { + match benchmark_fifo_queue::>("LPRQ") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/lprq_cpp/Cargo.toml b/data_structures/fifo_queues/lprq_cpp/Cargo.toml similarity index 100% rename from data_structures/queues/lprq_cpp/Cargo.toml rename to data_structures/fifo_queues/lprq_cpp/Cargo.toml diff --git a/data_structures/queues/lprq_cpp/build.rs b/data_structures/fifo_queues/lprq_cpp/build.rs similarity index 100% rename from data_structures/queues/lprq_cpp/build.rs rename to data_structures/fifo_queues/lprq_cpp/build.rs diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/README.md b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/README.md similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/README.md rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/README.md diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Forked.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Forked.hpp similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Forked.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Forked.hpp diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/HazardPointers.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/HazardPointers.hpp similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/HazardPointers.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/HazardPointers.hpp diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LinkedRingQueue.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LinkedRingQueue.hpp similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LinkedRingQueue.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LinkedRingQueue.hpp diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/MetaprogrammingUtils.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/MetaprogrammingUtils.hpp similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/MetaprogrammingUtils.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/MetaprogrammingUtils.hpp diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Metrics.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Metrics.hpp similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Metrics.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Metrics.hpp diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/RQCell.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/RQCell.hpp similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/RQCell.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/RQCell.hpp diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Stats.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Stats.hpp similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Stats.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Stats.hpp diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp diff --git a/data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp diff --git a/data_structures/queues/lprq_cpp/cpp_src/lprq_wrapper.cpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/lprq_wrapper.cpp similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/lprq_wrapper.cpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/lprq_wrapper.cpp diff --git a/data_structures/queues/lprq_cpp/cpp_src/lprq_wrapper.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/lprq_wrapper.hpp similarity index 100% rename from data_structures/queues/lprq_cpp/cpp_src/lprq_wrapper.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/lprq_wrapper.hpp diff --git a/data_structures/queues/lprq_cpp/src/lib.rs b/data_structures/fifo_queues/lprq_cpp/src/lib.rs similarity index 100% rename from data_structures/queues/lprq_cpp/src/lib.rs rename to data_structures/fifo_queues/lprq_cpp/src/lib.rs diff --git a/data_structures/fifo_queues/lprq_cpp/src/main.rs b/data_structures/fifo_queues/lprq_cpp/src/main.rs new file mode 100644 index 0000000..b6219e3 --- /dev/null +++ b/data_structures/fifo_queues/lprq_cpp/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("lprq_queue_cpp") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/moodycamel_cpp/Cargo.toml b/data_structures/fifo_queues/moodycamel_cpp/Cargo.toml similarity index 100% rename from data_structures/queues/moodycamel_cpp/Cargo.toml rename to data_structures/fifo_queues/moodycamel_cpp/Cargo.toml diff --git a/data_structures/queues/moodycamel_cpp/build.rs b/data_structures/fifo_queues/moodycamel_cpp/build.rs similarity index 100% rename from data_structures/queues/moodycamel_cpp/build.rs rename to data_structures/fifo_queues/moodycamel_cpp/build.rs diff --git a/data_structures/queues/moodycamel_cpp/cpp_src/concurrentqueue b/data_structures/fifo_queues/moodycamel_cpp/cpp_src/concurrentqueue similarity index 100% rename from data_structures/queues/moodycamel_cpp/cpp_src/concurrentqueue rename to data_structures/fifo_queues/moodycamel_cpp/cpp_src/concurrentqueue diff --git a/data_structures/queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp b/data_structures/fifo_queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp similarity index 100% rename from data_structures/queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp rename to data_structures/fifo_queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp diff --git a/data_structures/queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp b/data_structures/fifo_queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp similarity index 100% rename from data_structures/queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp rename to data_structures/fifo_queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp diff --git a/data_structures/queues/moodycamel_cpp/src/lib.rs b/data_structures/fifo_queues/moodycamel_cpp/src/lib.rs similarity index 100% rename from data_structures/queues/moodycamel_cpp/src/lib.rs rename to data_structures/fifo_queues/moodycamel_cpp/src/lib.rs diff --git a/data_structures/fifo_queues/moodycamel_cpp/src/main.rs b/data_structures/fifo_queues/moodycamel_cpp/src/main.rs new file mode 100644 index 0000000..c5dc266 --- /dev/null +++ b/data_structures/fifo_queues/moodycamel_cpp/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("moodycamel_cpp") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/ms_queue/Cargo.toml b/data_structures/fifo_queues/ms_queue/Cargo.toml similarity index 100% rename from data_structures/queues/ms_queue/Cargo.toml rename to data_structures/fifo_queues/ms_queue/Cargo.toml diff --git a/data_structures/queues/ms_queue/src/lib.rs b/data_structures/fifo_queues/ms_queue/src/lib.rs similarity index 100% rename from data_structures/queues/ms_queue/src/lib.rs rename to data_structures/fifo_queues/ms_queue/src/lib.rs diff --git a/data_structures/queues/basic_queue/src/main.rs b/data_structures/fifo_queues/ms_queue/src/main.rs similarity index 75% rename from data_structures/queues/basic_queue/src/main.rs rename to data_structures/fifo_queues/ms_queue/src/main.rs index a1b6bfc..f0035f4 100644 --- a/data_structures/queues/basic_queue/src/main.rs +++ b/data_structures/fifo_queues/ms_queue/src/main.rs @@ -1,5 +1,5 @@ use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; fn main() { @@ -11,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_queue::>("basic_queue") { + match benchmark_fifo_queue::>("ms_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/scc2_queue/Cargo.toml b/data_structures/fifo_queues/scc2_queue/Cargo.toml similarity index 100% rename from data_structures/queues/scc2_queue/Cargo.toml rename to data_structures/fifo_queues/scc2_queue/Cargo.toml diff --git a/data_structures/queues/scc2_queue/src/lib.rs b/data_structures/fifo_queues/scc2_queue/src/lib.rs similarity index 100% rename from data_structures/queues/scc2_queue/src/lib.rs rename to data_structures/fifo_queues/scc2_queue/src/lib.rs diff --git a/data_structures/fifo_queues/scc2_queue/src/main.rs b/data_structures/fifo_queues/scc2_queue/src/main.rs new file mode 100644 index 0000000..78d0ad9 --- /dev/null +++ b/data_structures/fifo_queues/scc2_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("scc2_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/scc_queue/Cargo.toml b/data_structures/fifo_queues/scc_queue/Cargo.toml similarity index 100% rename from data_structures/queues/scc_queue/Cargo.toml rename to data_structures/fifo_queues/scc_queue/Cargo.toml diff --git a/data_structures/queues/scc_queue/src/lib.rs b/data_structures/fifo_queues/scc_queue/src/lib.rs similarity index 100% rename from data_structures/queues/scc_queue/src/lib.rs rename to data_structures/fifo_queues/scc_queue/src/lib.rs diff --git a/data_structures/fifo_queues/scc_queue/src/main.rs b/data_structures/fifo_queues/scc_queue/src/main.rs new file mode 100644 index 0000000..c3b5997 --- /dev/null +++ b/data_structures/fifo_queues/scc_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("scc_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/seg_queue/Cargo.toml b/data_structures/fifo_queues/seg_queue/Cargo.toml similarity index 100% rename from data_structures/queues/seg_queue/Cargo.toml rename to data_structures/fifo_queues/seg_queue/Cargo.toml diff --git a/data_structures/queues/seg_queue/src/lib.rs b/data_structures/fifo_queues/seg_queue/src/lib.rs similarity index 100% rename from data_structures/queues/seg_queue/src/lib.rs rename to data_structures/fifo_queues/seg_queue/src/lib.rs diff --git a/data_structures/queues/scc2_queue/src/main.rs b/data_structures/fifo_queues/seg_queue/src/main.rs similarity index 77% rename from data_structures/queues/scc2_queue/src/main.rs rename to data_structures/fifo_queues/seg_queue/src/main.rs index 7d6f899..8007589 100644 --- a/data_structures/queues/scc2_queue/src/main.rs +++ b/data_structures/fifo_queues/seg_queue/src/main.rs @@ -1,5 +1,5 @@ use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; fn main() { @@ -11,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_queue::>("scc2_queue") { + match benchmark_fifo_queue::>("seg_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/tz_queue_hp/Cargo.toml b/data_structures/fifo_queues/tz_queue_hp/Cargo.toml similarity index 100% rename from data_structures/queues/tz_queue_hp/Cargo.toml rename to data_structures/fifo_queues/tz_queue_hp/Cargo.toml diff --git a/data_structures/queues/tz_queue_hp/src/lib.rs b/data_structures/fifo_queues/tz_queue_hp/src/lib.rs similarity index 100% rename from data_structures/queues/tz_queue_hp/src/lib.rs rename to data_structures/fifo_queues/tz_queue_hp/src/lib.rs diff --git a/data_structures/fifo_queues/tz_queue_hp/src/main.rs b/data_structures/fifo_queues/tz_queue_hp/src/main.rs new file mode 100644 index 0000000..ee6804b --- /dev/null +++ b/data_structures/fifo_queues/tz_queue_hp/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("tz_queue_hp") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/tz_queue_leak/Cargo.toml b/data_structures/fifo_queues/tz_queue_leak/Cargo.toml similarity index 100% rename from data_structures/queues/tz_queue_leak/Cargo.toml rename to data_structures/fifo_queues/tz_queue_leak/Cargo.toml diff --git a/data_structures/queues/tz_queue_leak/src/lib.rs b/data_structures/fifo_queues/tz_queue_leak/src/lib.rs similarity index 100% rename from data_structures/queues/tz_queue_leak/src/lib.rs rename to data_structures/fifo_queues/tz_queue_leak/src/lib.rs diff --git a/data_structures/fifo_queues/tz_queue_leak/src/main.rs b/data_structures/fifo_queues/tz_queue_leak/src/main.rs new file mode 100644 index 0000000..b586f34 --- /dev/null +++ b/data_structures/fifo_queues/tz_queue_leak/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("tz_queue_leak") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/unbounded_concurrent_queue/Cargo.toml b/data_structures/fifo_queues/unbounded_concurrent_queue/Cargo.toml similarity index 100% rename from data_structures/queues/unbounded_concurrent_queue/Cargo.toml rename to data_structures/fifo_queues/unbounded_concurrent_queue/Cargo.toml diff --git a/data_structures/queues/unbounded_concurrent_queue/src/lib.rs b/data_structures/fifo_queues/unbounded_concurrent_queue/src/lib.rs similarity index 100% rename from data_structures/queues/unbounded_concurrent_queue/src/lib.rs rename to data_structures/fifo_queues/unbounded_concurrent_queue/src/lib.rs diff --git a/data_structures/fifo_queues/unbounded_concurrent_queue/src/main.rs b/data_structures/fifo_queues/unbounded_concurrent_queue/src/main.rs new file mode 100644 index 0000000..b1c1c8b --- /dev/null +++ b/data_structures/fifo_queues/unbounded_concurrent_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("unbounded_concurrent_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/queues/wf_queue/Cargo.toml b/data_structures/fifo_queues/wf_queue/Cargo.toml similarity index 100% rename from data_structures/queues/wf_queue/Cargo.toml rename to data_structures/fifo_queues/wf_queue/Cargo.toml diff --git a/data_structures/queues/wf_queue/src/lib.rs b/data_structures/fifo_queues/wf_queue/src/lib.rs similarity index 100% rename from data_structures/queues/wf_queue/src/lib.rs rename to data_structures/fifo_queues/wf_queue/src/lib.rs diff --git a/data_structures/queues/bbq/src/main.rs b/data_structures/fifo_queues/wf_queue/src/main.rs similarity index 75% rename from data_structures/queues/bbq/src/main.rs rename to data_structures/fifo_queues/wf_queue/src/main.rs index 31e515c..05a910c 100644 --- a/data_structures/queues/bbq/src/main.rs +++ b/data_structures/fifo_queues/wf_queue/src/main.rs @@ -1,5 +1,5 @@ use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; fn main() { @@ -11,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_queue::>("BBQ") { + match benchmark_fifo_queue::>("wf_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/queues/boost_queue_cpp/src/main.rs b/data_structures/queues/boost_queue_cpp/src/main.rs deleted file mode 100644 index caec141..0000000 --- a/data_structures/queues/boost_queue_cpp/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("boost_queue_cpp") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/bounded_concurrent_queue/src/main.rs b/data_structures/queues/bounded_concurrent_queue/src/main.rs deleted file mode 100644 index 0685032..0000000 --- a/data_structures/queues/bounded_concurrent_queue/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("bounded_concurrent_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/bounded_ringbuffer/src/main.rs b/data_structures/queues/bounded_ringbuffer/src/main.rs deleted file mode 100644 index 5fdad37..0000000 --- a/data_structures/queues/bounded_ringbuffer/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("bounded_ringbuffer") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/faaa_queue/src/main.rs b/data_structures/queues/faaa_queue/src/main.rs deleted file mode 100644 index 002fcb4..0000000 --- a/data_structures/queues/faaa_queue/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("faa_array_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/faaa_queue_cpp/src/main.rs b/data_structures/queues/faaa_queue_cpp/src/main.rs deleted file mode 100644 index 8cc8635..0000000 --- a/data_structures/queues/faaa_queue_cpp/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("faaa_queue_cpp") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/lf_queue/src/main.rs b/data_structures/queues/lf_queue/src/main.rs deleted file mode 100644 index 2203205..0000000 --- a/data_structures/queues/lf_queue/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("lf_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/lockfree_queue/src/main.rs b/data_structures/queues/lockfree_queue/src/main.rs deleted file mode 100644 index 26a7a9d..0000000 --- a/data_structures/queues/lockfree_queue/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("lockfree_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/lprq/src/main.rs b/data_structures/queues/lprq/src/main.rs deleted file mode 100644 index 8a75d9c..0000000 --- a/data_structures/queues/lprq/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("LPRQ") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/lprq_cpp/src/main.rs b/data_structures/queues/lprq_cpp/src/main.rs deleted file mode 100644 index 88fe413..0000000 --- a/data_structures/queues/lprq_cpp/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("lprq_queue_cpp") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/moodycamel_cpp/src/main.rs b/data_structures/queues/moodycamel_cpp/src/main.rs deleted file mode 100644 index 517c214..0000000 --- a/data_structures/queues/moodycamel_cpp/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("moodycamel_cpp") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/ms_queue/src/main.rs b/data_structures/queues/ms_queue/src/main.rs deleted file mode 100644 index 62e6691..0000000 --- a/data_structures/queues/ms_queue/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("ms_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/scc_queue/src/main.rs b/data_structures/queues/scc_queue/src/main.rs deleted file mode 100644 index 40200ed..0000000 --- a/data_structures/queues/scc_queue/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("scc_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/seg_queue/src/main.rs b/data_structures/queues/seg_queue/src/main.rs deleted file mode 100644 index ec2a416..0000000 --- a/data_structures/queues/seg_queue/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("seg_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/tz_queue_hp/src/main.rs b/data_structures/queues/tz_queue_hp/src/main.rs deleted file mode 100644 index 0560b5e..0000000 --- a/data_structures/queues/tz_queue_hp/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("tz_queue_hp") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/tz_queue_leak/src/main.rs b/data_structures/queues/tz_queue_leak/src/main.rs deleted file mode 100644 index 5e25d93..0000000 --- a/data_structures/queues/tz_queue_leak/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("tz_queue_leak") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/unbounded_concurrent_queue/src/main.rs b/data_structures/queues/unbounded_concurrent_queue/src/main.rs deleted file mode 100644 index e6b426d..0000000 --- a/data_structures/queues/unbounded_concurrent_queue/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("unbounded_concurrent_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/data_structures/queues/wf_queue/src/main.rs b/data_structures/queues/wf_queue/src/main.rs deleted file mode 100644 index 24a522e..0000000 --- a/data_structures/queues/wf_queue/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_queue::>("wf_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} From 58c6707536cae2c87726d0138ef9d7125b90c558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Bj=C3=B6rnlinger?= <15017341+emilbjornlinger@users.noreply.github.com> Date: Thu, 5 Feb 2026 16:21:41 +0100 Subject: [PATCH 16/16] Change argument parsing to a flatter structure with one subcommand --- .gitmodules | 4 +- Cargo.toml | 48 +-- benchmark_core/src/arguments.rs | 199 ++++++---- benchmark_core/src/benchmarks.rs | 2 +- .../src/benchmarks/benchmark_helpers.rs | 61 ++- .../src/benchmarks/fifo_queue_benchmarks.rs | 136 +++++++ .../benchmarks/fifo_queue_benchmarks/bfs.rs | 372 ++++++++++++++++++ .../fifo_queue_benchmarks/enq_deq.rs | 237 +++++++++++ .../fifo_queue_benchmarks/enq_deq_pairs.rs | 203 ++++++++++ .../fifo_queue_benchmarks/prod_con.rs | 264 +++++++++++++ .../benchmarks/priority_queue_benchmarks.rs | 102 ++--- .../priority_queue_benchmarks/prod_con.rs | 94 ++--- .../stacks/lockfree_stack/src/main.rs | 4 +- data_structures/stacks/scc2_stack/src/main.rs | 4 +- data_structures/stacks/scc_stack/src/main.rs | 4 +- 15 files changed, 1483 insertions(+), 251 deletions(-) create mode 100644 benchmark_core/src/benchmarks/fifo_queue_benchmarks.rs create mode 100644 benchmark_core/src/benchmarks/fifo_queue_benchmarks/bfs.rs create mode 100644 benchmark_core/src/benchmarks/fifo_queue_benchmarks/enq_deq.rs create mode 100644 benchmark_core/src/benchmarks/fifo_queue_benchmarks/enq_deq_pairs.rs create mode 100644 benchmark_core/src/benchmarks/fifo_queue_benchmarks/prod_con.rs diff --git a/.gitmodules b/.gitmodules index 9f39963..0f8702a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "data_structures/queues/moodycamel_cpp/cpp_src/concurrentqueue"] - path = data_structures/queues/moodycamel_cpp/cpp_src/concurrentqueue +[submodule "data_structures/fifo_queues/moodycamel_cpp/cpp_src/concurrentqueue"] + path = data_structures/fifo_queues/moodycamel_cpp/cpp_src/concurrentqueue url = https://github.com/cameron314/concurrentqueue.git diff --git a/Cargo.toml b/Cargo.toml index 429c253..a986b91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,33 +2,33 @@ resolver = "2" members = [ "benchmark_core", - "data_structures/queues/array_queue", - "data_structures/queues/atomic_queue", - "data_structures/queues/basic_queue", - "data_structures/queues/bbq", - "data_structures/queues/boost_queue_cpp", - "data_structures/queues/bounded_concurrent_queue", - "data_structures/queues/unbounded_concurrent_queue", - "data_structures/queues/bounded_ringbuffer", - "data_structures/queues/faaa_queue", - "data_structures/queues/faaa_queue_cpp", - "data_structures/queues/lcrq_cpp", - "data_structures/queues/lcrq", - "data_structures/queues/lprq_cpp", - "data_structures/queues/lprq", - "data_structures/queues/lf_queue", - "data_structures/queues/lockfree_queue", + "data_structures/fifo_queues/array_queue", + "data_structures/fifo_queues/atomic_queue", + "data_structures/fifo_queues/basic_queue", + "data_structures/fifo_queues/bbq", + "data_structures/fifo_queues/boost_queue_cpp", + "data_structures/fifo_queues/bounded_concurrent_queue", + "data_structures/fifo_queues/unbounded_concurrent_queue", + "data_structures/fifo_queues/bounded_ringbuffer", + "data_structures/fifo_queues/faaa_queue", + "data_structures/fifo_queues/faaa_queue_cpp", + "data_structures/fifo_queues/lcrq_cpp", + "data_structures/fifo_queues/lcrq", + "data_structures/fifo_queues/lprq_cpp", + "data_structures/fifo_queues/lprq", + "data_structures/fifo_queues/lf_queue", + "data_structures/fifo_queues/lockfree_queue", "data_structures/stacks/lockfree_stack", - "data_structures/queues/moodycamel_cpp", - "data_structures/queues/ms_queue", - "data_structures/queues/scc_queue", + "data_structures/fifo_queues/moodycamel_cpp", + "data_structures/fifo_queues/ms_queue", + "data_structures/fifo_queues/scc_queue", "data_structures/stacks/scc_stack", - "data_structures/queues/scc2_queue", + "data_structures/fifo_queues/scc2_queue", "data_structures/stacks/scc2_stack", - "data_structures/queues/seg_queue", - "data_structures/queues/tz_queue_leak", - "data_structures/queues/tz_queue_hp", - "data_structures/queues/wf_queue", + "data_structures/fifo_queues/seg_queue", + "data_structures/fifo_queues/tz_queue_leak", + "data_structures/fifo_queues/tz_queue_hp", + "data_structures/fifo_queues/wf_queue", "data_structures/priority_queues/basic_priority_queue", ] diff --git a/benchmark_core/src/arguments.rs b/benchmark_core/src/arguments.rs index c888fa5..598fb87 100644 --- a/benchmark_core/src/arguments.rs +++ b/benchmark_core/src/arguments.rs @@ -1,136 +1,165 @@ use clap::{ArgAction, Args as ClapArgs, Parser, Subcommand}; use std::fmt::Display; -#[derive(Parser, Debug)] -#[command(version, about, long_about = None)] -pub struct Args { +/// General arguments for all benchmarks +#[derive(ClapArgs, Debug, Clone)] +pub struct GeneralArgs { /// Duration of each benchmark #[arg(short, long, default_value_t = 10)] pub time_limit: u64, + /// Attemps to only use one socket. Specific for the developers test environment. #[arg(short, long, default_value_t = true, action = ArgAction::SetFalse)] pub one_socket: bool, + /// How many times the chosen benchmark should be run. #[arg(short, long, default_value_t = 1)] pub iterations: u32, + /// Set the amount of floating point numbers generated between each operation. Default is 10. #[arg(short, long, default_value_t = 10)] pub delay: u64, + /// Set the output path for the result files. #[arg(long = "path", default_value_t = String::from("./output"))] pub path_output: String, - /// Choose which benchmark to run. - #[command(subcommand)] - pub benchmark: BenchmarkTypes, + /// If set to true, benchmark will output to stdout instead of to files. #[arg(long = "write-stdout", default_value_t = false)] pub write_to_stdout: bool, - /// Prefill the data structure with values before running the benchmark. - #[arg(short, long, default_value_t = 0)] - pub prefill_amount: u64, + /// Write benchmark configuration and hardware info to a separate file. #[arg(long, default_value_t = false, action = ArgAction::SetTrue)] pub print_info: bool, + #[cfg(feature = "memory_tracking")] /// The interval of which memory tracking will update [ms]. #[arg(long, default_value_t = 50)] pub memory_tracking_interval: u64, } -/// Possible benchmark types. -#[derive(Subcommand, Debug)] -pub enum BenchmarkTypes { - Queue(QueueArgs), - PriorityQueue(PriorityQueueArgs), -} - -/// Arguments for the Queue benchmark type -#[derive(ClapArgs, Debug, Clone)] -pub struct QueueArgs { +/// Arguments for the FIFO Queue benchmark types +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +pub struct FifoQueueArgs { /// Count empty pop operations. Off by default. #[arg(short, long, default_value_t = false)] pub empty_pops: bool, + /// Set the size of the bounded queues. #[arg(short, long, default_value_t = 10000)] pub queue_size: u32, + /// The runner to use for the benchmark #[command(subcommand)] - pub benchmark_runner: QueueBenchmarks, + pub benchmark_runner: FifoQueueBenchmarks, + + /// Prefill the FIFO Queue with default values before running the benchmark. + #[arg(short, long, default_value_t = 0)] + pub prefill_amount: u64, + + /// General arguments agnostic to the FIFO Queue + #[command(flatten)] + pub general_args: GeneralArgs, } -/// Benchmark runners for queues. -#[derive(Subcommand, Debug, Clone)] -pub enum QueueBenchmarks { - /// ProdCon throughput test. Decide amount of producers and consumers using flags. - ProdCon(QueueProdConArgs), - /// A test where each thread performs both consume and produce based on a random floating point - /// value. Spread is decided using the `--spread` flag. - EnqDeq(QueueEnqDeqArgs), - EnqDeqPairs(QueueEnqDeqPairsArgs), - BFS(QueueBFSArgs), +/// Benchmark runners for FIFO Queues. +#[derive(Subcommand, Debug)] +pub enum FifoQueueBenchmarks { + /// A benchmark for measuring throughput using producers and consumers that + /// are each bound to a thread + ProdCon(FifoQueueProdConArgs), + + /// A benchmark measuring throughput where a thread will switch between + /// producing and consuming + EnqDeq(FifoQueueEnqDeqArgs), + + /// A benchmark measuring throughput where a thread will enqueue an item + /// and then immediately dequeue it + EnqDeqPairs(FifoQueueEnqDeqPairsArgs), + + /// Benchmarks how fast the FIFO Queue can complete a breadth-first search + /// on a graph + BFS(FifoQueueBFSArgs), } -#[derive(ClapArgs, Debug, Clone)] -pub struct QueueProdConArgs { - /// Amount of producers to be used for basic throughput test. +#[derive(ClapArgs, Debug)] +pub struct FifoQueueProdConArgs { + /// Amount of producers to be used #[arg(short, long, default_value_t = 20)] pub producers: usize, - /// Amount of consumers to be used for basic throughput test. + + /// Amount of consumers to be used #[arg(short, long, default_value_t = 20)] pub consumers: usize, } -#[derive(ClapArgs, Debug, Clone)] -pub struct QueueEnqDeqArgs { +#[derive(ClapArgs, Debug)] +pub struct FifoQueueEnqDeqArgs { /// Set the thread count for the pingpong benchmark. #[arg(long = "thread-count", default_value_t = 20)] pub thread_count: usize, + /// Decide the spread of producers/consumers for the pingpong benchmark. /// Ex. 0.3 means 30% produce 70% consume. #[arg(long = "spread", default_value_t = 0.5)] pub spread: f64, } -#[derive(ClapArgs, Debug, Clone)] -pub struct QueueEnqDeqPairsArgs { +#[derive(ClapArgs, Debug)] +pub struct FifoQueueEnqDeqPairsArgs { /// Set the thread count for the pingpong benchmark. #[arg(long = "thread-count", default_value_t = 20)] pub thread_count: usize, } -#[derive(ClapArgs, Debug, Clone)] -pub struct QueueBFSArgs { +#[derive(ClapArgs, Debug)] +pub struct FifoQueueBFSArgs { #[arg(short, long, default_value_t = 20)] pub thread_count: usize, + #[arg(short, long)] pub graph_file: String, + #[arg(short, long, default_value_t = false)] pub no_verify: bool, } -/// Arguments for the PriorityQueue benchmark type -#[derive(ClapArgs, Debug, Clone)] +/// Arguments for the Priority Queue benchmark types +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] pub struct PriorityQueueArgs { /// Set the size of the bounded queues. #[arg(short, long, default_value_t = 10000)] pub queue_size: u32, + /// The runner to use for the benchmark #[command(subcommand)] pub benchmark_runner: PriorityQueueBenchmarks, + + /// Prefill the FIFO Queue with default values before running the benchmark. + #[arg(short, long, default_value_t = 0)] + pub prefill_amount: u64, + + /// General arguments agnostic to the Priority Queue + #[command(flatten)] + pub general_args: GeneralArgs, } /// Benchmark runners for priority queues. -#[derive(Subcommand, Debug, Clone)] +#[derive(Subcommand, Debug)] pub enum PriorityQueueBenchmarks { - /// Producer Consumer throughput test. Decide amount of producers and consumers using flags. + /// A benchmark for measuring throughput using producers and consumers that + /// are each bound to a thread ProdCon(PQProdConArgs), } -#[derive(ClapArgs, Debug, Clone)] +#[derive(ClapArgs, Debug)] pub struct PQProdConArgs { /// Amount of producers to be used for basic throughput test. #[arg(short, long, default_value_t = 20)] pub producers: usize, + /// Amount of consumers to be used for basic throughput test. #[arg(short, long, default_value_t = 20)] pub consumers: usize, @@ -138,57 +167,50 @@ pub struct PQProdConArgs { /// This is used to write the benchmark type to the output. /// That is why the arguments are discarded. -impl Display for QueueBenchmarks { +impl Display for FifoQueueBenchmarks { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - QueueBenchmarks::ProdCon(_) => write!(f, "ProdCon"), - QueueBenchmarks::EnqDeq(_) => write!(f, "EnqDeq"), - QueueBenchmarks::EnqDeqPairs(_) => write!(f, "EnqDeqPairs"), + FifoQueueBenchmarks::ProdCon(_) => write!(f, "ProdCon"), + FifoQueueBenchmarks::EnqDeq(_) => write!(f, "EnqDeq"), + FifoQueueBenchmarks::EnqDeqPairs(_) => write!(f, "EnqDeqPairs"), // #[cfg(feature = "bfs")] - QueueBenchmarks::BFS(_) => write!(f, "BFS"), + FifoQueueBenchmarks::BFS(_) => write!(f, "BFS"), } } } + +/// This is used to write the benchmark type to the output. +/// That is why the arguments are discarded. +impl Display for PriorityQueueBenchmarks { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PriorityQueueBenchmarks::ProdCon(_) => write!(f, "ProdCon"), + } + } +} + /// This is used in the print_info function. -impl Display for Args { +impl Display for GeneralArgs { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "Time limit: {}", self.time_limit)?; writeln!(f, "One socket?: {}", self.one_socket)?; writeln!(f, "Iterations: {}", self.iterations)?; writeln!(f, "Delay: {}", self.delay)?; writeln!(f, "Output path: {}", self.path_output)?; - writeln!(f, "Benchmark: {:?}", self.benchmark)?; writeln!(f, "Write to stdout: {}", self.write_to_stdout)?; - writeln!(f, "prefill amount: {}", self.prefill_amount)?; - Ok(()) - } -} - -impl Display for BenchmarkTypes { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - writeln!(f, "Benchmark type: {:?}", self)?; Ok(()) } } /// Implemented so that tests are easier to write. -impl Default for Args { +impl Default for GeneralArgs { fn default() -> Self { - Args { - prefill_amount: 0, + GeneralArgs { time_limit: 1, one_socket: true, iterations: 1, delay: 10, path_output: "".to_string(), - benchmark: BenchmarkTypes::Queue(QueueArgs { - empty_pops: false, - queue_size: 10000, - benchmark_runner: QueueBenchmarks::ProdCon(QueueProdConArgs { - producers: 5, - consumers: 5, - }), - }), write_to_stdout: true, print_info: false, #[cfg(feature = "memory_tracking")] @@ -196,3 +218,38 @@ impl Default for Args { } } } + +/// Implemented for easier testing +impl Default for FifoQueueArgs { + fn default() -> Self { + FifoQueueArgs { + empty_pops: false, + queue_size: 10000, + benchmark_runner: FifoQueueBenchmarks::ProdCon( + FifoQueueProdConArgs { + producers: 20, + consumers: 20, + }, + ), + prefill_amount: 1000, + general_args: GeneralArgs::default(), + } + } +} + +/// Implemented for easier testing +impl Default for PriorityQueueArgs { + fn default() -> Self { + PriorityQueueArgs { + queue_size: 10000, + benchmark_runner: PriorityQueueBenchmarks::ProdCon( + PQProdConArgs { + producers: 20, + consumers: 20, + }, + ), + prefill_amount: 1000, + general_args: GeneralArgs::default(), + } + } +} diff --git a/benchmark_core/src/benchmarks.rs b/benchmark_core/src/benchmarks.rs index 7bc919e..359149e 100644 --- a/benchmark_core/src/benchmarks.rs +++ b/benchmark_core/src/benchmarks.rs @@ -1,4 +1,4 @@ -pub mod queue_benchmarks; +pub mod fifo_queue_benchmarks; pub mod priority_queue_benchmarks; pub mod benchmark_helpers; pub(crate) mod test_helpers; diff --git a/benchmark_core/src/benchmarks/benchmark_helpers.rs b/benchmark_core/src/benchmarks/benchmark_helpers.rs index 4b75837..1244ca1 100644 --- a/benchmark_core/src/benchmarks/benchmark_helpers.rs +++ b/benchmark_core/src/benchmarks/benchmark_helpers.rs @@ -1,10 +1,13 @@ -use crate::arguments::Args; +use crate::arguments::GeneralArgs; #[cfg(feature = "memory_tracking")] use crate::traits::ConcurrentQueue; +use chrono::Local; #[cfg(feature = "memory_tracking")] use jemalloc_ctl::{epoch, stats}; use log::{debug, error, trace}; +use std::collections::hash_map::DefaultHasher; use std::fs::OpenOptions; +use std::hash::{Hash, Hasher}; use std::io::Write; #[cfg(feature = "memory_tracking")] use std::sync::atomic::AtomicBool; @@ -13,7 +16,7 @@ use sysinfo::System; /// Benchmark config struct /// Needs to be fully filled for benchmarks to be able to run. pub struct BenchConfig { - pub args: Args, + pub args: GeneralArgs, pub date_time: String, pub benchmark_id: String, pub output_filename: String, @@ -138,6 +141,7 @@ pub fn calc_fairness(ops_per_thread: Vec) -> f64 { pub fn print_info( queue: String, bench_conf: &BenchConfig, + benchmark: String, ) -> Result<(), std::io::Error> { // Create file if printing to stdout is disabled if bench_conf.args.write_to_stdout { @@ -157,11 +161,7 @@ pub fn print_info( let num: u64 = 1000; let sys = System::new_all(); if let Some(mut file) = memfile { - writeln!( - file, - "Benchmark done: {}", - bench_conf.args.benchmark - )?; + writeln!(file, "Benchmark done: {}", benchmark)?; writeln!(file, "With queue: {}", queue)?; writeln!(file, "Arguments used in test:")?; @@ -189,3 +189,50 @@ pub fn print_info( } Ok(()) } + +pub fn create_bench_config( + general_args: &GeneralArgs, +) -> Result { + let date_time = Local::now().format("%Y%m%d%H%M%S").to_string(); + + // Create benchmark hashed id + let benchmark_id = { + let mut hasher = DefaultHasher::new(); + date_time.hash(&mut hasher); + format!("{:x}", hasher.finish()) + }; + + debug!("Benchmark ID: {}", benchmark_id); + debug!("Arguments: {:?}", general_args); + + // Create dir if it doesn't already exist. + if !std::path::Path::new(&general_args.path_output).exists() { + std::fs::create_dir(&general_args.path_output)?; + } + + let output_filename = format!("{}/{}", general_args.path_output, date_time); + + Ok(BenchConfig { + args: general_args.clone(), + date_time, + benchmark_id, + output_filename, + }) +} + +pub fn output_result_header( + output: String, + bench_config: &BenchConfig, +) -> Result<(), std::io::Error> { + if bench_config.args.write_to_stdout { + println!("{output}") + } else { + let mut file = OpenOptions::new() + .append(true) + .create(true) + .open(&bench_config.output_filename)?; + writeln!(file, "{output}")?; + } + + Ok(()) +} diff --git a/benchmark_core/src/benchmarks/fifo_queue_benchmarks.rs b/benchmark_core/src/benchmarks/fifo_queue_benchmarks.rs new file mode 100644 index 0000000..126a01a --- /dev/null +++ b/benchmark_core/src/benchmarks/fifo_queue_benchmarks.rs @@ -0,0 +1,136 @@ +#[allow(unused_imports)] +use crate::arguments::{FifoQueueArgs, FifoQueueBenchmarks, GeneralArgs}; +use crate::benchmarks::benchmark_helpers::{self, BenchConfig}; +#[allow(unused_imports)] +use crate::traits::{ConcurrentQueue, HandleQueue}; +use clap::Parser; +#[allow(unused_imports)] +use log::{self, debug, error, info}; +#[allow(unused_imports)] +use std::sync::atomic::AtomicBool; + +pub mod bfs; +pub mod enq_deq; +pub mod enq_deq_pairs; +pub mod prod_con; + +/// Create the fifo queue, and run the selected benchmark a set of times +pub fn benchmark_fifo_queue(queue_name: &str) -> Result<(), std::io::Error> +where + Q: ConcurrentQueue + Send, + for<'a> &'a Q: Send, +{ + let (bench_conf, fifo_queue_args) = setup_benchmark()?; + + // The variables need to be references to avoid moving into closures below. + // TODO(emilbjornlinger): Find a better solution. + let bench_conf = &bench_conf; + let fifo_queue_args = &fifo_queue_args; + + // Create a runner lambda for the different benchmarks, mainly needed for eg. BFS to load graph and so on + let mut runner: Box< + dyn FnMut(Q, &BenchConfig) -> Result<(), std::io::Error>, + > = match &fifo_queue_args.benchmark_runner { + FifoQueueBenchmarks::ProdCon(_) => Box::new(move |q, bench_conf| { + prod_con::benchmark_prod_con(q, bench_conf, fifo_queue_args) + }), + FifoQueueBenchmarks::EnqDeq(_) => Box::new(move |q, bench_conf| { + enq_deq::benchmark_enq_deq(q, bench_conf, fifo_queue_args) + }), + FifoQueueBenchmarks::EnqDeqPairs(_) => { + Box::new(move |q, bench_conf| { + enq_deq_pairs::benchmark_enq_deq_pairs( + q, + bench_conf, + fifo_queue_args, + ) + }) + } + FifoQueueBenchmarks::BFS(args) => { + let (graph, seq_ret_vec, start_node) = bfs::pre_bfs_work( + Q::new(fifo_queue_args.queue_size as usize), + &args, + ); + Box::new(move |q, _conf| { + bfs::benchmark_bfs( + q, + &graph, + &bench_conf, + &seq_ret_vec, + start_node, + fifo_queue_args, + ) + }) + } + }; + + for _current_iteration in 0..bench_conf.args.iterations { + // Create the queue. + let test_q: Q = Q::new(fifo_queue_args.queue_size as usize); + + // Start memory tracking (if enabled) + #[cfg(feature = "memory_tracking")] + let (done, mem_thread_handle) = { + let done = + std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); + let handle = benchmark_helpers::create_mem_tracking_thread( + bench_conf, + _current_iteration, + &test_q, + &done, + )?; + (done, handle) + }; + + // Execute the benchmark + runner(test_q, &bench_conf)?; + + // Join the thread again + debug!("Queue should have been dropped now."); + + // Stop memory tracking (if enabled) + #[cfg(feature = "memory_tracking")] + { + use std::sync::atomic::Ordering; + debug!("Joining memory thread."); + done.store(true, Ordering::Relaxed); + if let Err(e) = mem_thread_handle.join().unwrap() { + log::error!("Couldn't join memory tracking thread: {}", e); + } + } + } + + if bench_conf.args.print_info { + benchmark_helpers::print_info( + queue_name.to_string(), + &bench_conf, + fifo_queue_args.benchmark_runner.to_string(), + )?; + } + + Ok(()) +} + +/// Parse arguments and start outputting result of benchmark +pub fn setup_benchmark() -> Result<(BenchConfig, FifoQueueArgs), std::io::Error> +{ + let args = crate::arguments::FifoQueueArgs::parse(); + let bench_config = + benchmark_helpers::create_bench_config(&args.general_args)?; + + let columns = match args.benchmark_runner { + FifoQueueBenchmarks::BFS(_) => { + "Milliseconds,Queuetype,Thread Count,Test ID" + }, + _ => { + "Throughput,Enqueues,Dequeues,Consumers,Producers,Thread Count,Queuetype,Benchmark,Test ID,Fairness,Spread,Queue Size" + } + }; + + benchmark_helpers::output_result_header( + columns.to_string(), + &bench_config, + )?; + + Ok((bench_config, args)) +} diff --git a/benchmark_core/src/benchmarks/fifo_queue_benchmarks/bfs.rs b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/bfs.rs new file mode 100644 index 0000000..1ef41a8 --- /dev/null +++ b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/bfs.rs @@ -0,0 +1,372 @@ +use crate::arguments::{FifoQueueArgs, FifoQueueBFSArgs, FifoQueueBenchmarks}; +use crate::benchmarks::benchmark_helpers::BenchConfig; +use crate::traits::{ConcurrentQueue, HandleQueue}; +use core_affinity::CoreId; +use log::{debug, error, info, trace}; +use std::fs::File; +use std::io::{BufRead, BufReader, Write}; +use std::{ + fs::OpenOptions, + sync::{ + atomic::{AtomicUsize, Ordering}, + Barrier, + }, +}; + +/// Generates the graph, generates the sequential solution and gets which +/// node to start at. +pub fn pre_bfs_work( + cqueue: C, + args: &FifoQueueBFSArgs, +) -> (Vec>, Vec, usize) +where + C: ConcurrentQueue, + for<'a> &'a C: Send, +{ + info!("Loading graph now..."); + let graph = create_graph(args.graph_file.clone()).unwrap(); + // Find start node. Currently finds node with most neighbours. + let mut biggest = 0; + let mut curr = 0; + for (i, edge) in graph.iter().enumerate() { + if edge.len() > biggest { + biggest = edge.len(); + curr = i; + } + } + info!("Generating correct solution..."); + debug!("Start node is: {curr}"); + + let seq_ret_vec = if !args.no_verify { + sequential_bfs(cqueue, &graph, curr) // TODO: Use a better generic sequential queue + } else { + vec![] + }; + (graph, seq_ret_vec, curr) +} + +/* +arr[] +dist_to_start_node +*/ + +/// Explanation: +/// A benchmark to test how fast your data structure can complete a Breadth-First Search (BFS) +/// and if it does so correctly. +/// Need to send in your data structure and the graph you want to do bfs on (only .mtx files allowed). +/// Benchmark specififc flags: +/// * `--graph-file` The .mtx graph file you want to use in your bfs. +/// * `--thread-count` (OPTIONAL) The amount of threads you want to have in your benchmark (if left out, standard 20). +/// * `--no-verify` (OPTIONAL) Boolean to opt out of verifying the parallel benchmark results against the sequential (standard false). +/// +/// Ex. run: +/// cargo run -features data_structure,bfs -- bfs --graph-file graph.mtx +pub fn benchmark_bfs( + cqueue: C, + graph: &[Vec], + bench_conf: &BenchConfig, + seq_ret_vec: &[usize], + start_node: usize, + fifo_queue_args: &FifoQueueArgs +) -> Result<(), std::io::Error> +where + C: ConcurrentQueue, + for<'a> &'a C: Send, +{ + let bfs_args = match &fifo_queue_args.benchmark_runner { + FifoQueueBenchmarks::BFS(a) => a, + _ => panic!( + "benchmark_bfs called with another FIFO Queue \ + configured. This is an implementation error." + ), + }; + let thread_count = bfs_args.thread_count; + debug!("Starting parallell BFS now"); + let (dur_par, par_ret_vec) = + parallell_bfs(&cqueue, graph, start_node, thread_count, bench_conf); + debug!("Graph traversal done. Took {:?}.", dur_par); + + if !bfs_args.no_verify { + debug!("Comparing results to the sequential solution"); + for (i, node) in par_ret_vec.iter().enumerate() { + trace!( + "Pos: {} Parallell: {} Sequential: {}", + i, + *node, + seq_ret_vec[i] + ); + if *node != seq_ret_vec[i] { + error!("Parallell BFS solution arrived at wrong answer."); + return Ok(()); + } + } + debug!("Solution looks good."); + } + let formatted = format!( + "{},{},{},{}", + dur_par.as_millis(), + cqueue.get_id(), + bfs_args.thread_count, + bench_conf.benchmark_id + ); + if !bench_conf.args.write_to_stdout { + let mut file = OpenOptions::new() + .append(true) + .create(true) + .open(&bench_conf.output_filename)?; + + writeln!(file, "{}", formatted)?; + } else { + println!("{}", formatted); + } + + Ok(()) +} + +fn parallell_bfs( + cqueue: &C, + graph: &[Vec], + start_node: usize, + thread_count: usize, + bench_conf: &BenchConfig, +) -> (std::time::Duration, Vec) +where + C: ConcurrentQueue, + for<'a> &'a C: Send, +{ + let result_vector: Vec = (0..graph.len()) + .map(|_| AtomicUsize::new(usize::MAX)) + .collect(); + + // Set distance of first node + result_vector[start_node].store(0, Ordering::Relaxed); + + let idle_count: AtomicUsize = AtomicUsize::new(0); + let no_work_count: AtomicUsize = AtomicUsize::new(0); + let barrier = Barrier::new(thread_count + 1); + // Add start node to queue + let _ = cqueue.register().push(start_node); + + // Get cores for fairness of threads + let available_cores: Vec = + core_affinity::get_core_ids().unwrap_or(vec![CoreId { id: 0 }]); + let mut core_iter = available_cores.into_iter().cycle(); + + let scope_result = + std::thread::scope(|s| -> Result { + let idle_count = &idle_count; + let no_work_count = &no_work_count; + let barrier = &barrier; + let result_vector = &result_vector; + let mut handles = vec![]; + let is_one_socket = &bench_conf.args.one_socket; + for i in 0..thread_count { + handles.push({ + let mut core: CoreId = core_iter.next().unwrap(); + // if is_one_socket is true, make all thread ids even + // (this was used for our testing enviroment to get one socket) + if *is_one_socket { + core = core_iter.next().unwrap(); + } + s.spawn(move || { + core_affinity::set_for_current(core); + // Register queue + let handle = cqueue.register(); + // Wait for other queues + barrier.wait(); + // Start BFS + pbfs_helper( + handle, + result_vector, + graph, + i, + no_work_count, + idle_count, + thread_count, + ); + }) + }); + } + barrier.wait(); + let start = std::time::Instant::now(); + for handle in handles { + handle.join().unwrap(); + } + let duration = start.elapsed(); + Ok(duration) + }); + let duration = scope_result.expect("Should never return error"); + let ret_vec: Vec = result_vector + .iter() + .map(|val| val.load(Ordering::Relaxed)) + .collect(); + trace!("Parallell sol: {:?}", ret_vec); + (duration, ret_vec) +} + +fn pbfs_helper( + mut handle: impl HandleQueue, + result_vector: &[AtomicUsize], + graph: &[Vec], + i: usize, + no_work_count: &AtomicUsize, + idle_count: &AtomicUsize, + thread_count: usize, +) { + let mut next = None; + loop { + if next.is_none() { + next = handle.pop(); + } + match next { + Some(node) => { + next = None; + trace!("Thread: {i}; Acquired node {node}"); + let distance = result_vector[node].load(Ordering::SeqCst); + for neighbour in &graph[node] { + let mut n_distance = + result_vector[*neighbour].load(Ordering::SeqCst); + while distance + 1 < n_distance { + if result_vector[*neighbour] + .compare_exchange_weak( + n_distance, + distance + 1, + Ordering::SeqCst, + Ordering::SeqCst, + ) + .is_ok() + { + match handle.push(*neighbour) { + Err(e) => { + error!("Failed to push to queue: {e}"); + continue; + } + Ok(_) => { + trace!( + "Thread: {i}; Pushed {}", + *neighbour + ); + break; + } + } + } + n_distance = + result_vector[*neighbour].load(Ordering::SeqCst); + } + } + } + None => { + trace!("Thread: {i}; Did not acquire any work"); + no_work_count.fetch_add(1, Ordering::Relaxed); + loop { + next = handle.pop(); + if next.is_some() { + break; + } + if no_work_count.load(Ordering::Relaxed) >= thread_count + && should_terminate( + idle_count, + no_work_count, + thread_count, + ) + { + return; + } + } + no_work_count.fetch_sub(1, Ordering::Relaxed); + } + } + } +} + +fn should_terminate( + idle_count: &AtomicUsize, + no_work_count: &AtomicUsize, + thread_count: usize, +) -> bool { + idle_count.fetch_add(1, Ordering::Relaxed); + while no_work_count.load(Ordering::Relaxed) >= thread_count { + if idle_count.load(Ordering::Relaxed) >= thread_count { + return true; + } + //PAUSE? no-op + std::hint::spin_loop(); + } + idle_count.fetch_sub(1, Ordering::Relaxed); + false +} + +fn sequential_bfs( + cqueue: C, + graph: &[Vec], + start_node: usize, +) -> Vec +where + C: ConcurrentQueue, + for<'a> &'a C: Send, +{ + let mut result_vector: Vec = + (0..graph.len()).map(|_| usize::MAX).collect(); + let mut visited: std::collections::HashSet = + std::collections::HashSet::new(); + let mut q = cqueue.register(); + result_vector[start_node] = 0; + if q.push(start_node).is_err() { + error!("Failed to start BFS, couldn't push start node"); + } + while let Some(node) = q.pop() { + let distance = result_vector[node]; + for n in &graph[node] { + if visited.contains(n) { + continue; + } + let n_distance = result_vector[*n]; + if n_distance > distance + 1 { + result_vector[*n] = distance + 1; + } + if q.push(*n).is_err() { + error!("Failed to push in sequential BFS"); + } + visited.insert(*n); + } + } + trace!("Sequential sol: {:?}", result_vector); + result_vector +} + +pub fn create_graph( + graph_file: String, +) -> Result>, std::io::Error> { + let file = File::open(graph_file)?; + let reader = BufReader::new(file); + + let mut edges = Vec::new(); + for line in reader.lines() { + let line = line?; + if line.starts_with('%') { + continue; + } + + let edge: Vec = line + .split(' ') + .map(|n| { + n.parse::() + .expect("File populated with non-integers") + }) + .collect(); + + edges.push(edge); + } + + let size = edges[0][0] + 1; // in case graph is not zero-indexed. + let mut graph: Vec> = vec![Vec::new(); size]; + + for edge in edges.iter().skip(1) { + let src = edge[0]; + let dst = edge[1]; + graph[src].push(dst); + } + + Ok(graph) +} +// Milliseconds,Queuetype,Thread Count,Test ID diff --git a/benchmark_core/src/benchmarks/fifo_queue_benchmarks/enq_deq.rs b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/enq_deq.rs new file mode 100644 index 0000000..c60e90f --- /dev/null +++ b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/enq_deq.rs @@ -0,0 +1,237 @@ +use crate::arguments::{FifoQueueArgs, FifoQueueBenchmarks}; +use crate::benchmarks::benchmark_helpers::{self, BenchConfig}; +use crate::traits::{ConcurrentQueue, HandleQueue}; +use core_affinity::CoreId; +use log::{debug, error, info, trace}; +use rand::Rng; +use std::fs::OpenOptions; +use std::io::Write; +use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; +use std::sync::{mpsc, Arc}; + +/// # Explanation: +/// A benchmark that measures the throughput of a queue. +/// Here threads vary between producers and consumers, +/// Benchmark specific flags: +/// * --spread Set the spread of consumers/producers, value between 0 - 1. Ex. --spread 0.3, gives 30% consume, 70% produce +/// * --thread-count Set the amount of threads to run in the benchmark +#[allow(dead_code)] +pub fn benchmark_enq_deq ( + cqueue: C, + bench_conf: &BenchConfig, + fifo_queue_args: &FifoQueueArgs, +) -> Result<(), std::io::Error> +where +C: ConcurrentQueue, +T: Default, + for<'a> &'a C: Send +{ + // Extract specific arguments for this benchmark runner + let enq_deq_args = match &fifo_queue_args.benchmark_runner { + FifoQueueBenchmarks::EnqDeq(a) => a, + _ => panic!( + "benchmark_enq_deq called with another FIFO Queue \ + configured. This is an implementation error." + ), + }; + + { + debug!("Prefilling queue with {} items.", fifo_queue_args.prefill_amount); + let mut tmp_handle = cqueue.register(); + for _ in 0..fifo_queue_args.prefill_amount { + let _ = tmp_handle.push(Default::default()); + } + } + let thread_count = enq_deq_args.thread_count; + let time_limit: u64 = bench_conf.args.time_limit; + let barrier = Barrier::new(thread_count + 1); + let pops = AtomicUsize::new(0); + let pushes = AtomicUsize::new(0); + let done = AtomicBool::new(false); + let (tx, rx) = mpsc::channel(); + info!("Starting pingpong benchmark with {} threads", thread_count); + + + + // Get cores for fairness of threads + let available_cores: Vec = + core_affinity::get_core_ids().unwrap_or(vec![CoreId { id: 0 }]); + let mut core_iter = available_cores.into_iter().cycle(); + + // Shared atomic bool for when a thread fails + let thread_failed = Arc::new(AtomicBool::new(false)); + + + let _ = std::thread::scope(|s| -> Result<(), std::io::Error>{ + let queue = &cqueue; + let thread_failed = &thread_failed; // Every thread clones the thread_failed bool + let pushes = &pushes; + let pops = &pops; + let done = &done; + let barrier = &barrier; + let &thread_count = &thread_count; + let &spread = &enq_deq_args.spread; + let is_one_socket = &bench_conf.args.one_socket; + let tx = &tx; + for _i in 0..thread_count{ + let mut core : CoreId = core_iter.next().unwrap(); + // if is_one_socket is true, make all thread ids even + // (this was used for our testing enviroment to get one socket) + if *is_one_socket { + core = core_iter.next().unwrap(); + } + // println!("{:?}", core); + s.spawn(move || { + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + core_affinity::set_for_current(core); + let mut handle = queue.register(); + let mut l_pushes = 0; + let mut l_pops = 0; + let _thread_failed = thread_failed.clone(); + barrier.wait(); + while !done.load(Ordering::Relaxed) { + let random_float = rand::rng().random::(); + if random_float > spread { + match handle.pop() { + Some(_) => l_pops += 1, + None => { + if fifo_queue_args.empty_pops { + l_pops += 1; + } + } + } + } else { + let _ = handle.push(T::default()); + l_pushes += 1; + } + for _ in 0..bench_conf.args.delay { + let _some_num = rand::rng().random::(); + } + } + + pushes.fetch_add(l_pushes, Ordering::Relaxed); + pops.fetch_add(l_pops, Ordering::Relaxed); + tx.send(l_pops + l_pushes).unwrap(); + trace!("{}: Pushed: {}, Popped: {}", _i, l_pushes, l_pops); + })); + // A thread panicked, aborting the benchmark... + if let Err(e) = result { + error!("Thread {} panicked: {:?}. Aborting benchmark, padding results to zero", _i, e); + thread_failed.store(true, Ordering::Relaxed); + done.store(true, Ordering::Relaxed); + } + }); + + } + barrier.wait(); + std::thread::sleep(std::time::Duration::from_secs(time_limit)); + done.store(true, Ordering::Relaxed); + Ok(()) + }); + drop(tx); + let pops = pops.into_inner(); + let pushes = pushes.into_inner(); + // Fairness + let ops_per_thread = { + let mut vals = vec![]; + for received in rx { + vals.push(received); + } + vals + }; + let fairness = benchmark_helpers::calc_fairness(ops_per_thread); + + // If a thread crashed, pad the results with zero-values + let formatted = if thread_failed.load(Ordering::Relaxed) { + format!("0,0,0,-1,-1,{},{},{},{},0,{},{}", + thread_count, + cqueue.get_id(), + fifo_queue_args.benchmark_runner, + bench_conf.benchmark_id, + enq_deq_args.spread, + fifo_queue_args.queue_size + ) + } + else { + format!("{},{},{},{},{},{},{},{},{},{},{},{}", + (pushes + pops) as f64 / time_limit as f64, + pushes, + pops, + -1, + -1, + thread_count, + cqueue.get_id(), + fifo_queue_args.benchmark_runner, + bench_conf.benchmark_id, + fairness, + enq_deq_args.spread, + fifo_queue_args.queue_size + ) + }; + // Write to file or stdout depending on flag + if !bench_conf.args.write_to_stdout { + let mut file = OpenOptions::new() + .append(true) + .create(true) + .open(&bench_conf.output_filename)?; + writeln!(file, "{}", formatted)?; + } else { + println!("{}", formatted); + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use crate::arguments::FifoQueueArgs; + use crate::arguments::FifoQueueBenchmarks; + use crate::arguments::FifoQueueEnqDeqArgs; + + use super::*; + + use crate::benchmarks::test_helpers::test_queue::TestQueue; + + #[test] + fn run_pingpong() { + let fifo_queue_args = FifoQueueArgs { + benchmark_runner: FifoQueueBenchmarks::EnqDeq( + FifoQueueEnqDeqArgs { thread_count: 10 , spread: 0.5 }, + ), + ..Default::default() + }; + let bench_conf = benchmark_helpers::BenchConfig { + args: fifo_queue_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test2".to_string(), + output_filename: "".to_string(), + }; + let queue: TestQueue = TestQueue::new(0); + if benchmark_enq_deq(queue, &bench_conf, &fifo_queue_args) + .is_err() + { + panic!(); + } + } + + #[test] + fn run_pingpong_with_bool() { + let fifo_queue_args = FifoQueueArgs { + benchmark_runner: FifoQueueBenchmarks::EnqDeq( + FifoQueueEnqDeqArgs { thread_count: 10 , spread: 0.5 }, + ), + ..Default::default() + }; + let bench_conf = benchmark_helpers::BenchConfig { + args: fifo_queue_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test2".to_string(), + output_filename: "".to_string(), + }; + let queue: TestQueue = TestQueue::new(0); + if benchmark_enq_deq(queue, &bench_conf, &fifo_queue_args) + .is_err() + { + panic!(); + } + } +} diff --git a/benchmark_core/src/benchmarks/fifo_queue_benchmarks/enq_deq_pairs.rs b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/enq_deq_pairs.rs new file mode 100644 index 0000000..14b79ee --- /dev/null +++ b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/enq_deq_pairs.rs @@ -0,0 +1,203 @@ +use crate::arguments::{FifoQueueArgs, FifoQueueBenchmarks}; +use crate::benchmarks::benchmark_helpers::{self, BenchConfig}; +use crate::traits::{ConcurrentQueue, HandleQueue}; +use core_affinity::CoreId; +use log::{debug, error, info, trace}; +use rand::Rng; +use std::fs::OpenOptions; +use std::io::Write; +use std::sync::{ + atomic::{AtomicBool, AtomicUsize, Ordering}, + Barrier, +}; +use std::sync::{mpsc, Arc}; + +/// # Explanation: +#[allow(dead_code)] +pub fn benchmark_enq_deq_pairs( + cqueue: C, + bench_conf: &BenchConfig, + fifo_queue_args: &FifoQueueArgs, +) -> Result<(), std::io::Error> +where + C: ConcurrentQueue, + T: Default, + for<'a> &'a C: Send, +{ + // Extract specific arguments for this benchmark runner + let enq_deq_pairs_args = match &fifo_queue_args.benchmark_runner { + FifoQueueBenchmarks::EnqDeqPairs(a) => a, + _ => panic!( + "benchmark_enq_deq_pairs called with another FIFO Queue \ + configured. This is an implementation error." + ), + }; + + { + debug!( + "Prefilling queue with {} items.", + fifo_queue_args.prefill_amount + ); + + let mut tmp_handle = cqueue.register(); + for _ in 0..fifo_queue_args.prefill_amount { + let _ = tmp_handle.push(Default::default()); + } + } + + let thread_count = enq_deq_pairs_args.thread_count; + let time_limit: u64 = bench_conf.args.time_limit; + let barrier = Barrier::new(thread_count + 1); + let pops = AtomicUsize::new(0); + let pushes = AtomicUsize::new(0); + let done = AtomicBool::new(false); + let (tx, rx) = mpsc::channel(); + info!("Starting pingpong benchmark with {} threads", thread_count); + + // Get cores for fairness of threads + let available_cores: Vec = + core_affinity::get_core_ids().unwrap_or(vec![CoreId { id: 0 }]); + let mut core_iter = available_cores.into_iter().cycle(); + + // Shared atomic bool for when a thread fails + let thread_failed = Arc::new(AtomicBool::new(false)); + + let _ = std::thread::scope(|s| -> Result<(), std::io::Error> { + let queue = &cqueue; + let thread_failed = &thread_failed; // Every thread clones the thread_failed bool + let pushes = &pushes; + let pops = &pops; + let done = &done; + let barrier = &barrier; + let &thread_count = &thread_count; + let is_one_socket = &bench_conf.args.one_socket; + let tx = &tx; + for _i in 0..thread_count { + let mut core: CoreId = core_iter.next().unwrap(); + // if is_one_socket is true, make all thread ids even + // (this was used for our testing enviroment to get one socket) + if *is_one_socket { + core = core_iter.next().unwrap(); + } + // println!("{:?}", core); + s.spawn(move || { + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + core_affinity::set_for_current(core); + let mut handle = queue.register(); + let mut l_pushes = 0; + let mut l_pops = 0; + let _thread_failed = thread_failed.clone(); + barrier.wait(); + while !done.load(Ordering::Relaxed) { + let _ = handle.push(T::default()); + l_pushes += 1; + let _ = handle.pop(); + l_pops += 1; + for _ in 0..bench_conf.args.delay { + let _some_num = rand::rng().random::(); + } + } + pushes.fetch_add(l_pushes, Ordering::Relaxed); + pops.fetch_add(l_pops, Ordering::Relaxed); + tx.send(l_pops + l_pushes).unwrap(); + trace!("{}: Pushed: {}, Popped: {}", _i, l_pushes, l_pops); + })); + // A thread panicked, aborting the benchmark... + if let Err(e) = result { + error!("Thread {} panicked: {:?}. Aborting benchmark, padding results to zero", _i, e); + thread_failed.store(true, Ordering::Relaxed); + done.store(true, Ordering::Relaxed); + } + }); + } + barrier.wait(); + std::thread::sleep(std::time::Duration::from_secs(time_limit)); + done.store(true, Ordering::Relaxed); + Ok(()) + }); + drop(tx); + let pops = pops.into_inner(); + let pushes = pushes.into_inner(); + // Fairness + let ops_per_thread = { + let mut vals = vec![]; + for received in rx { + vals.push(received); + } + vals + }; + let fairness = benchmark_helpers::calc_fairness(ops_per_thread); + + // If a thread crashed, pad the results with zero-values + let formatted = if thread_failed.load(Ordering::Relaxed) { + format!( + "0,0,0,-1,-1,{},{},{},{},0,{},{}", + thread_count, + cqueue.get_id(), + fifo_queue_args.benchmark_runner, + bench_conf.benchmark_id, + -1, + fifo_queue_args.queue_size + ) + } else { + format!( + "{},{},{},{},{},{},{},{},{},{},{},{}", + (pushes + pops) as f64 / time_limit as f64, + pushes, + pops, + -1, + -1, + thread_count, + cqueue.get_id(), + fifo_queue_args.benchmark_runner, + bench_conf.benchmark_id, + fairness, + -1, + fifo_queue_args.queue_size + ) + }; + // Write to file or stdout depending on flag + if !bench_conf.args.write_to_stdout { + let mut file = OpenOptions::new() + .append(true) + .create(true) + .open(&bench_conf.output_filename)?; + writeln!(file, "{}", formatted)?; + } else { + println!("{}", formatted); + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use crate::arguments::FifoQueueArgs; + use crate::arguments::FifoQueueBenchmarks; + use crate::arguments::FifoQueueEnqDeqPairsArgs; + + use super::*; + + use crate::benchmarks::test_helpers::test_queue::TestQueue; + + #[test] + fn run_enqdeq_pairs_with_struct() { + let fifo_queue_args = FifoQueueArgs { + benchmark_runner: FifoQueueBenchmarks::EnqDeqPairs( + FifoQueueEnqDeqPairsArgs { thread_count: 20 }, + ), + ..Default::default() + }; + let bench_conf = benchmark_helpers::BenchConfig { + args: fifo_queue_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test2".to_string(), + output_filename: "".to_string(), + }; + let queue: TestQueue = TestQueue::new(0); + if benchmark_enq_deq_pairs(queue, &bench_conf, &fifo_queue_args) + .is_err() + { + panic!(); + } + } +} diff --git a/benchmark_core/src/benchmarks/fifo_queue_benchmarks/prod_con.rs b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/prod_con.rs new file mode 100644 index 0000000..b1e1b09 --- /dev/null +++ b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/prod_con.rs @@ -0,0 +1,264 @@ +use core_affinity::CoreId; +use log::{debug, error, info, trace}; +use rand::Rng; +use crate::arguments::{FifoQueueArgs, FifoQueueBenchmarks}; +use crate::traits::{ConcurrentQueue, HandleQueue}; +use crate::benchmarks::benchmark_helpers::{self, BenchConfig}; +use std::fs::OpenOptions; +use std::io::Write; +use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; +use std::sync::{mpsc, Arc}; + +/// # Explanation: +/// A simple benchmark that measures the throughput of a queue. +/// Has by default a 10 floating points generated delay between each operation, but this can be changed +/// through flags passed to the program. +/// Benchmark specific flags: +/// * -p Set specified amount of producers +/// * -c Set specified amount of consumers +#[allow(dead_code)] +pub fn benchmark_prod_con(cqueue: C, bench_conf: &BenchConfig, fifo_queue_args: &FifoQueueArgs) -> Result<(), std::io::Error> +where + C: ConcurrentQueue, + T: Default, + for<'a> &'a C: Send +{ + // Extract specific arguments for this benchmark runner + let prod_con_args = match &fifo_queue_args.benchmark_runner { + FifoQueueBenchmarks::ProdCon(a) => a, + _ => panic!("benchmark_prod_con called with another FIFO Queue \ + configured. This is an implementation error.") + }; + + { + debug!("Prefilling queue with {} items.", fifo_queue_args.prefill_amount); + let mut tmp_handle = cqueue.register(); + for _ in 0..fifo_queue_args.prefill_amount { + let _ = tmp_handle.push(Default::default()); + } + } + let producers = prod_con_args.producers; + let consumers = prod_con_args.consumers; + + let time_limit: u64 = bench_conf.args.time_limit; + let barrier = Barrier::new(consumers + producers + 1); + let pops = AtomicUsize::new(0); + let pushes = AtomicUsize::new(0); + let done = AtomicBool::new(false); + let (tx, rx) = mpsc::channel(); + info!("Starting throughput benchmark with {} consumer and {} producers", consumers, producers); + + // get cores for fairness of threads + let available_cores: Vec = + core_affinity::get_core_ids().unwrap_or(vec![CoreId { id: 0 }]); + let mut core_iter = available_cores.into_iter().cycle(); + + // Shared atomic bool for when a thread fails + let thread_failed = Arc::new(AtomicBool::new(false)); + + let _ = std::thread::scope(|s| -> Result<(), std::io::Error>{ + let queue = &cqueue; + let pushes = &pushes; + let pops = &pops; + let done = &done; + let barrier = &barrier; + let tx = &tx; + let &consumers = &consumers; + let &producers = &producers; + let is_one_socket = &bench_conf.args.one_socket; + let thread_failed = &thread_failed; + + for i in 0..producers{ + let mut core : CoreId = core_iter.next().unwrap(); + // if is_one_socket is true, make all thread ids even + // (this was used for our testing enviroment to get one socket) + if *is_one_socket { + core = core_iter.next().unwrap(); + } + trace!("Thread: {} Core: {:?}", i, core); + s.spawn(move || { + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + core_affinity::set_for_current(core); + let mut handle = queue.register(); + // push + let mut l_pushes = 0; + let _thread_failed = thread_failed.clone(); // Every thread clones the thread_failed bool + barrier.wait(); + while !done.load(Ordering::Relaxed) { + // NOTE: Maybe we should care about this result? + let _ = handle.push(T::default()); + l_pushes += 1; + // Add some delay to simulate real workload + for _ in 0..bench_conf.args.delay { + let _some_num = rand::rng().random::(); + } + } + pushes.fetch_add(l_pushes, Ordering::Relaxed); + // Thread sends its total operations down the channel for fairness calculations + if let Err(e) = tx.send(l_pushes) { + error!("Error sending operations down the channel: {}", e); + }; + })); + // A thread panicked, aborting the benchmark... + if let Err (e) = result { + error!("Thread {} panicked in pushing: {:?}. Aborting benchmark, padding results to zero", i, e); + thread_failed.store(true, Ordering::Relaxed); + done.store(true, Ordering::Relaxed); + } + }); + } + for i in 0..consumers { + let mut core : CoreId = core_iter.next().expect("Core iter error"); + // if is_one_socket is true, make all thread ids even + // (this was used for our testing enviroment to get one socket) + if *is_one_socket { + core = core_iter.next().unwrap(); + } + trace!("Thread: {} Core: {:?}", i, core); + + s.spawn(move || { + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + core_affinity::set_for_current(core); + let mut handle = queue.register(); + // pop + let mut l_pops = 0; + let mut empty_pops = 0; + let _thread_failed = thread_failed.clone(); // Every thread clones the thread_failed bool + barrier.wait(); + // TODO: add empty pops probably to fairness calculations + while !done.load(Ordering::Relaxed) { + match handle.pop() { + Some(_) => l_pops += 1, + None => { + // if bench_conf.args.empty_pops { + // l_pops += 1; + // } + empty_pops += 1; + } + } + for _ in 0..bench_conf.args.delay { + let _some_num = rand::rng().random::(); + } + } + pops.fetch_add(l_pops, Ordering::Relaxed); + // Thread sends its total operations down the channel for fairness calculations + if let Err(e) = tx.send(l_pops + empty_pops) { + error!("Error sending operations down the channel: {}", e); + }; + })); + // A thread panicked, aborting the benchmark... + if let Err(e) = result { + error!("Thread {} panicked while popping: {:?}. Aborting benchmark, padding results to zero", i, e); + thread_failed.store(true, Ordering::Relaxed); + done.store(true, Ordering::Relaxed); + } + }); + } + debug!("Waiting for barrier"); + barrier.wait(); + debug!("Done waiting for barrier. Going to sleep."); + std::thread::sleep(std::time::Duration::from_secs(time_limit)); + done.store(true, Ordering::Relaxed); + Ok(()) + }); + drop(tx); + debug!("TX Dropped"); + let pops = pops.into_inner(); + let pushes = pushes.into_inner(); + + // Fairness + // Get total operations per thread + let ops_per_thread = { + let mut vals = vec![]; + for received in rx { + vals.push(received); + }; + vals + }; + // If a thread crashed, pad the results with zero-values + let formatted = if thread_failed.load(Ordering::Relaxed) { + format!("0,0,0,{},{},-1,{},{},{},0,-1,{}", producers, consumers, cqueue.get_id(), fifo_queue_args.benchmark_runner, bench_conf.benchmark_id, fifo_queue_args.queue_size) + } + else { + let fairness = benchmark_helpers::calc_fairness(ops_per_thread); + format!("{},{},{},{},{},{},{},{},{},{},{},{}", + (pushes + pops) as f64 / time_limit as f64, + pushes, + pops, + consumers, + producers, + -1, + cqueue.get_id(), + fifo_queue_args.benchmark_runner, + bench_conf.benchmark_id, + fairness, + -1, + fifo_queue_args.queue_size) + }; + if !bench_conf.args.write_to_stdout { + let mut file = OpenOptions::new() + .append(true) + .create(true) + .open(&bench_conf.output_filename)?; + + writeln!(file, "{}", formatted)?; + + } else { + println!("{}", formatted); + } + + Ok(()) +} + + +#[cfg(test)] +mod tests { + use super::*; + + use crate::benchmarks::test_helpers::test_queue::TestQueue; + + #[test] + fn run_basic_prod_con() { + let fifo_queue_args = FifoQueueArgs::default(); + let bench_conf = benchmark_helpers::BenchConfig { + args: fifo_queue_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + let queue: TestQueue = TestQueue::new(0); + if benchmark_prod_con(queue, &bench_conf, &fifo_queue_args).is_err() { + panic!(); + } + } + + #[test] + fn run_basic_with_string() { + let fifo_queue_args = FifoQueueArgs::default(); + let bench_conf = benchmark_helpers::BenchConfig { + args: fifo_queue_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + let queue: TestQueue = TestQueue::new(0); + if benchmark_prod_con(queue, &bench_conf, &fifo_queue_args).is_err() { + panic!(); + } + } + + #[test] + fn run_basic_with_struct() { + let fifo_queue_args = FifoQueueArgs::default(); + let bench_conf = benchmark_helpers::BenchConfig { + args: fifo_queue_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + let queue: TestQueue = TestQueue::new(0); + if benchmark_prod_con(queue, &bench_conf, &fifo_queue_args).is_err() { + panic!(); + } + } +} diff --git a/benchmark_core/src/benchmarks/priority_queue_benchmarks.rs b/benchmark_core/src/benchmarks/priority_queue_benchmarks.rs index 0b115bc..3eac921 100644 --- a/benchmark_core/src/benchmarks/priority_queue_benchmarks.rs +++ b/benchmark_core/src/benchmarks/priority_queue_benchmarks.rs @@ -1,18 +1,13 @@ #[allow(unused_imports)] use crate::arguments::{ - Args, BenchmarkTypes, PriorityQueueArgs, PriorityQueueBenchmarks, + GeneralArgs, PriorityQueueArgs, PriorityQueueBenchmarks, }; -use crate::benchmarks::benchmark_helpers; +use crate::benchmarks::benchmark_helpers::{self, BenchConfig}; #[allow(unused_imports)] use crate::traits::{ConcurrentPriorityQueue, HandlePriorityQueue}; -use chrono::Local; use clap::Parser; #[allow(unused_imports)] use log::{self, debug, error, info}; -use std::collections::hash_map::DefaultHasher; -use std::fs::OpenOptions; -use std::hash::{Hash, Hasher}; -use std::io::Write; #[allow(unused_imports)] use std::sync::atomic::AtomicBool; @@ -27,13 +22,12 @@ where T: Default, for<'a> &'a Q: Send, { - // Setup output and parse arguments - let SetupResult { - bench_conf, - pq_conf, - .. - } = setup_benchmark()?; + let (bench_conf, pq_args) = setup_benchmark()?; + + // The variables need to be references to avoid moving into closures below. + // TODO(emilbjornlinger): Find a better solution. let bench_conf = &bench_conf; + let pq_args = &pq_args; // Create a runner lambda for the different benchmarks, mainly needed for eg. BFS to load graph and so on let mut runner: Box< @@ -41,17 +35,17 @@ where Q, &benchmark_helpers::BenchConfig, ) -> Result<(), std::io::Error>, - > = match &pq_conf.benchmark_runner { + > = match &pq_args.benchmark_runner { PriorityQueueBenchmarks::ProdCon(_) => { Box::new(move |q, bench_conf| { - prod_con::benchmark_prod_con(q, bench_conf) + prod_con::benchmark_prod_con(q, bench_conf, pq_args) }) } }; for _current_iteration in 0..bench_conf.args.iterations { // Create the queue. - let test_q: Q = Q::new(pq_conf.queue_size as usize); + let test_q: Q = Q::new(pq_args.queue_size as usize); // Start memory tracking (if enabled) #[cfg(feature = "memory_tracking")] @@ -86,70 +80,30 @@ where } if bench_conf.args.print_info { - benchmark_helpers::print_info(queue_name.to_string(), bench_conf)?; + benchmark_helpers::print_info( + queue_name.to_string(), + bench_conf, + pq_args.benchmark_runner.to_string(), + )?; } Ok(()) } -pub struct SetupResult { - pub bench_conf: benchmark_helpers::BenchConfig, - pub pq_conf: PriorityQueueArgs, - pub columns: String, // Optional, but alreadyy written (TODO: have a stream of some sort here) -} - -/// Set up the actual benchmark. -/// -/// All work unrelated to the chosen benchmark is done here. -pub fn setup_benchmark() -> Result { - let args = crate::arguments::Args::parse(); - - let pq_args = match &args.benchmark { - BenchmarkTypes::PriorityQueue(queue_args) => queue_args.clone(), - _ => panic!( - "Trying to run a queue benchmark with another benchmark type" - ), - }; - - let date_time = Local::now().format("%Y%m%d%H%M%S").to_string(); - // Create benchmark hashed id - let benchmark_id = { - let mut hasher = DefaultHasher::new(); - date_time.hash(&mut hasher); - format!("{:x}", hasher.finish()) - }; +/// Parse arguments and start outputting result of benchmark +pub fn setup_benchmark( +) -> Result<(BenchConfig, PriorityQueueArgs), std::io::Error> { + let args = crate::arguments::PriorityQueueArgs::parse(); + let bench_config = + benchmark_helpers::create_bench_config(&args.general_args)?; - debug!("Benchmark ID: {}", benchmark_id); - debug!("Arguments: {:?}", args); + let columns = "Throughput,Enqueues,Dequeues,Consumers,Producers,\ + Thread Count,Queuetype,Benchmark,Test ID,Fairness,Spread,Queue Size"; - // Create dir if it doesnt already exist. - if !std::path::Path::new(&args.path_output).exists() { - std::fs::create_dir(&args.path_output)?; - } - - let output_filename = format!("{}/{}", args.path_output, date_time); - let bench_conf = benchmark_helpers::BenchConfig { - args, - date_time, - benchmark_id, - output_filename, - }; - - let columns = "Throughput,Enqueues,Dequeues,Consumers,Producers,Thread Count,Queuetype,Benchmark,Test ID,Fairness,Spread,Queue Size"; - - if bench_conf.args.write_to_stdout { - println!("{columns}") - } else { - let mut file = OpenOptions::new() - .append(true) - .create(true) - .open(&bench_conf.output_filename)?; - writeln!(file, "{columns}")?; - } + benchmark_helpers::output_result_header( + columns.to_string(), + &bench_config, + )?; - Ok(SetupResult { - bench_conf, - pq_conf: pq_args, - columns: columns.to_string(), - }) + Ok((bench_config, args)) } diff --git a/benchmark_core/src/benchmarks/priority_queue_benchmarks/prod_con.rs b/benchmark_core/src/benchmarks/priority_queue_benchmarks/prod_con.rs index 8b95288..0f35975 100644 --- a/benchmark_core/src/benchmarks/priority_queue_benchmarks/prod_con.rs +++ b/benchmark_core/src/benchmarks/priority_queue_benchmarks/prod_con.rs @@ -1,9 +1,9 @@ use core_affinity::CoreId; use log::{debug, error, info, trace}; use rand::Rng; -use crate::arguments::{BenchmarkTypes, PriorityQueueBenchmarks}; +use crate::arguments::{PriorityQueueArgs, PriorityQueueBenchmarks}; use crate::traits::{ConcurrentPriorityQueue, HandlePriorityQueue}; -use crate::benchmarks::benchmark_helpers; +use crate::benchmarks::benchmark_helpers::{self, BenchConfig}; use std::fs::OpenOptions; use std::io::Write; use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; @@ -19,37 +19,28 @@ use std::sync::{mpsc, Arc}; /// * -p Set specified amount of producers /// * -c Set specified amount of consumers #[allow(dead_code)] -pub fn benchmark_prod_con(cqueue: C, bench_conf: &benchmark_helpers::BenchConfig) -> Result<(), std::io::Error> +pub fn benchmark_prod_con(cqueue: C, bench_conf: &BenchConfig, pq_args: &PriorityQueueArgs) -> Result<(), std::io::Error> where C: ConcurrentPriorityQueue, P: Ord + From, T: Default, for<'a> &'a C: Send { - let args = match &bench_conf.args.benchmark { - BenchmarkTypes::PriorityQueue(args) => match &args.benchmark_runner { - PriorityQueueBenchmarks::ProdCon(a) => a, - } - _ => panic!(), - }; - - let queue_args = match &bench_conf.args.benchmark { - BenchmarkTypes::PriorityQueue(queue_args) => queue_args.clone(), - _ => panic!( - "Trying to run a queue benchmark with another benchmark type" - ), + // Extract specific arguments for this benchmark runner + let prod_con_args = match &pq_args.benchmark_runner { + PriorityQueueBenchmarks::ProdCon(a) => a, }; { - debug!("Prefilling priority queue with {} items.", bench_conf.args.prefill_amount); + debug!("Prefilling priority queue with {} items.", pq_args.prefill_amount); let mut tmp_handle = cqueue.register(); - for i in 0..bench_conf.args.prefill_amount { + for i in 0..pq_args.prefill_amount { let prio: usize = i.try_into().unwrap(); let _ = tmp_handle.insert(P::from(prio), Default::default()); } } - let producers = args.producers; - let consumers = args.consumers; + let producers = prod_con_args.producers; + let consumers = prod_con_args.consumers; let time_limit: u64 = bench_conf.args.time_limit; let barrier = Barrier::new(consumers + producers + 1); @@ -188,7 +179,7 @@ where }; // If a thread crashed, pad the results with zero-values let formatted = if thread_failed.load(Ordering::Relaxed) { - format!("0,0,0,{},{},-1,{},{},{},0,-1,{}", producers, consumers, cqueue.get_id(), bench_conf.args.benchmark, bench_conf.benchmark_id, queue_args.queue_size) + format!("0,0,0,{},{},-1,{},{},{},0,-1,{}", producers, consumers, cqueue.get_id(), pq_args.benchmark_runner, bench_conf.benchmark_id, pq_args.queue_size) } else { let fairness = benchmark_helpers::calc_fairness(ops_per_thread); @@ -200,11 +191,11 @@ where producers, -1, cqueue.get_id(), - bench_conf.args.benchmark, + pq_args.benchmark_runner, bench_conf.benchmark_id, fairness, -1, - queue_args.queue_size) + pq_args.queue_size) }; if !bench_conf.args.write_to_stdout { let mut file = OpenOptions::new() @@ -225,80 +216,51 @@ where mod tests { use super::*; - use crate::arguments::{Args, PQProdConArgs, PriorityQueueArgs}; + use crate::arguments::PriorityQueueArgs; + use crate::benchmarks::test_helpers::test_priority_queue::TestPriorityQueue; #[test] fn run_basic_prod_con() { - let def_args = Args::default(); - let args = Args { - benchmark: BenchmarkTypes::PriorityQueue(PriorityQueueArgs { - queue_size: 10000, - benchmark_runner: PriorityQueueBenchmarks::ProdCon(PQProdConArgs { - producers: 10, - consumers: 10, - }) - }), - ..def_args - }; - let bench_conf = benchmark_helpers::BenchConfig { - args, + let pq_args = PriorityQueueArgs::default(); + let bench_conf = BenchConfig { + args: pq_args.general_args.clone(), date_time: "".to_string(), benchmark_id: "test1".to_string(), output_filename: "".to_string() }; let queue: TestPriorityQueue = TestPriorityQueue::new(0); - if benchmark_prod_con(queue, &bench_conf).is_err() { + if benchmark_prod_con(queue, &bench_conf, &pq_args).is_err() { panic!(); } } #[test] fn run_basic_with_string() { - let def_args = Args::default(); - let args = Args { - benchmark: BenchmarkTypes::PriorityQueue(PriorityQueueArgs { - queue_size: 10000, - benchmark_runner: PriorityQueueBenchmarks::ProdCon(PQProdConArgs { - producers: 10, - consumers: 10, - }) - }), - ..def_args - }; - let bench_conf = benchmark_helpers::BenchConfig { - args, + let pq_args = PriorityQueueArgs::default(); + let bench_conf = BenchConfig { + args: pq_args.general_args.clone(), date_time: "".to_string(), benchmark_id: "test1".to_string(), output_filename: "".to_string() }; let queue: TestPriorityQueue = TestPriorityQueue::new(0); - if benchmark_prod_con(queue, &bench_conf).is_err() { + if benchmark_prod_con(queue, &bench_conf, &pq_args).is_err() { panic!(); } } #[test] fn run_basic_with_struct() { - let args = Args { - benchmark: BenchmarkTypes::PriorityQueue(PriorityQueueArgs { - queue_size: 10000, - benchmark_runner: PriorityQueueBenchmarks::ProdCon(PQProdConArgs { - producers: 10, - consumers: 10, - }) - }), - ..Default::default() - }; - let bench_conf = benchmark_helpers::BenchConfig { - args, + let pq_args = PriorityQueueArgs::default(); + let bench_conf = BenchConfig { + args: pq_args.general_args.clone(), date_time: "".to_string(), benchmark_id: "test1".to_string(), output_filename: "".to_string() }; - // TODO(emilbjornlinger): Change this struct - let queue: TestPriorityQueue = TestPriorityQueue::new(0); - if benchmark_prod_con(queue, &bench_conf).is_err() { + let queue: TestPriorityQueue = TestPriorityQueue::new(0); + if benchmark_prod_con(queue, &bench_conf, &pq_args).is_err() { panic!(); } } diff --git a/data_structures/stacks/lockfree_stack/src/main.rs b/data_structures/stacks/lockfree_stack/src/main.rs index f8b6481..dc00667 100644 --- a/data_structures/stacks/lockfree_stack/src/main.rs +++ b/data_structures/stacks/lockfree_stack/src/main.rs @@ -1,5 +1,5 @@ use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; fn main() { @@ -11,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_queue::>("lockfree_stack") { + match benchmark_fifo_queue::>("lockfree_stack") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/stacks/scc2_stack/src/main.rs b/data_structures/stacks/scc2_stack/src/main.rs index 4fa2fd8..789858b 100644 --- a/data_structures/stacks/scc2_stack/src/main.rs +++ b/data_structures/stacks/scc2_stack/src/main.rs @@ -1,5 +1,5 @@ use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; fn main() { @@ -11,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_queue::>("scc2_stack") { + match benchmark_fifo_queue::>("scc2_stack") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/data_structures/stacks/scc_stack/src/main.rs b/data_structures/stacks/scc_stack/src/main.rs index b6d7907..f407cd9 100644 --- a/data_structures/stacks/scc_stack/src/main.rs +++ b/data_structures/stacks/scc_stack/src/main.rs @@ -1,5 +1,5 @@ use log::*; -use benchmark_core::benchmarks::queue_benchmarks::benchmark_queue; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; fn main() { @@ -11,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_queue::>("scc_stack") { + match benchmark_fifo_queue::>("scc_stack") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e);