Skip to content

Commit

Permalink
Use folly directly
Browse files Browse the repository at this point in the history
Add chunked Ring Buffer
Add benchmark for folly::DSPSCQueue and folly::USPSCQueue
Fix includes of spsc_queue.hpp
  • Loading branch information
Deaod committed Jun 16, 2019
1 parent 5ada741 commit 929198e
Show file tree
Hide file tree
Showing 5 changed files with 380 additions and 373 deletions.
6 changes: 4 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
set(BENCHMARK_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)

add_subdirectory(benchmark)
find_package(folly CONFIG REQUIRED)
find_package(ZLIB REQUIRED)

add_executable(RingBufferBenchmark
RingBufferBenchmark.cpp
Expand All @@ -14,15 +16,15 @@ add_executable(RingBufferBenchmark
spsc_queue.hpp
spsc_ring_buffer.hpp
spsc_ring_buffer_cached.hpp
spsc_ring_buffer_chunked.hpp
spsc_ring_buffer_heap.hpp
follyProducerConsumerQueue.h
rigtorpSPSCQueue.h
moodycamel/atomicops.h
moodycamel/readwriterqueue.h
)

set_property(TARGET RingBufferBenchmark PROPERTY CXX_STANDARD 17)
target_link_libraries(RingBufferBenchmark benchmark)
target_link_libraries(RingBufferBenchmark benchmark Folly::folly Folly::folly_deps)
target_compile_options(RingBufferBenchmark PRIVATE -DMOODYCAMEL_CACHE_LINE_SIZE=128)

if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
Expand Down
151 changes: 140 additions & 11 deletions RingBufferBenchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
#include "spsc_queue.hpp"
#include "spsc_ring_buffer.hpp"
#include "spsc_ring_buffer_cached.hpp"
#include "spsc_ring_buffer_chunked.hpp"
#include "spsc_ring_buffer_heap.hpp"
#include "follyProducerConsumerQueue.h"
#include <folly/ProducerConsumerQueue.h>
#include <folly/concurrency/UnboundedQueue.h>
#include <folly/concurrency/DynamicBoundedQueue.h>
#include "rigtorpSPSCQueue.h"
#include "moodycamel/readwriterqueue.h"
#include <immintrin.h>
Expand Down Expand Up @@ -113,6 +116,8 @@ static void RingBuffer(benchmark::State& state) {
counter += int(result);
}
}
state.SetItemsProcessed(state.iterations() * 10000);
state.SetBytesProcessed(state.iterations() * 10000 * state.range(0));

if (b.is_empty() == false) {
state.SkipWithError("Not Empty after test");
Expand Down Expand Up @@ -157,6 +162,8 @@ static void FollyQueue(benchmark::State& state) {
}
}
}
state.SetItemsProcessed(state.iterations() * 10000);
state.SetBytesProcessed(state.iterations() * 10000 * sizeof(typename type::value_type));

if (q.isEmpty() == false) {
state.SkipWithError("Not Empty after test");
Expand All @@ -167,6 +174,95 @@ static void FollyQueue(benchmark::State& state) {
}
}

template<typename type, typename element_type>
static void FollyUnboundedQueue(benchmark::State& state) {
static std::atomic<type*> queue = nullptr;

if (state.thread_index == 0) {
queue = new type{};
} else {
while (queue.load(std::memory_order_relaxed) == nullptr) {}
}

type& q = *queue;
if (state.thread_index == 0) {
ASSIGN_THREAD_AFFINITY(Thread1Affinity);
for (auto _ : state) {
int counter = 0;
while (counter < 10000) {
q.enqueue(element_type{});
counter += 1;
}
}
state.SetItemsProcessed(state.iterations() * 10000);
state.SetBytesProcessed(state.iterations() * 10000 * sizeof(element_type));
} else {
ASSIGN_THREAD_AFFINITY(Thread2Affinity);
element_type e;
for (auto _ : state) {
int counter = 0;
while (counter < 10000) {
if (q.try_dequeue().has_value()) {
counter += 1;
}
}
}
state.SetItemsProcessed(state.iterations() * 10000);
state.SetBytesProcessed(state.iterations() * 10000 * sizeof(element_type));

if (q.empty() == false) {
state.SkipWithError("Not Empty after test");
}

delete queue;
queue = nullptr;
}
}

template<typename type, typename element_type>
static void FollyDBQueue(benchmark::State& state) {
static std::atomic<type*> queue = nullptr;

if (state.thread_index == 0) {
queue = new type{ size_t(1) << (state.range(0) - ctu::log2_v<sizeof(element_type)>) };
} else {
while (queue.load(std::memory_order_relaxed) == nullptr) {}
}

type& q = *queue;
if (state.thread_index == 0) {
ASSIGN_THREAD_AFFINITY(Thread1Affinity);
for (auto _ : state) {
int counter = 0;
while (counter < 10000) {
counter += int(q.try_enqueue(element_type{}));
}
}
state.SetItemsProcessed(state.iterations() * 10000);
state.SetBytesProcessed(state.iterations() * 10000 * sizeof(element_type));
} else {
ASSIGN_THREAD_AFFINITY(Thread2Affinity);
element_type e;
for (auto _ : state) {
int counter = 0;
while (counter < 10000) {
if (q.try_dequeue(e)) {
counter += 1;
}
}
}
state.SetItemsProcessed(state.iterations() * 10000);
state.SetBytesProcessed(state.iterations() * 10000 * sizeof(element_type));

if (q.empty() == false) {
state.SkipWithError("Not Empty after test");
}

delete queue;
queue = nullptr;
}
}

template<typename type>
static void Queue(benchmark::State& state) {
static std::atomic<type*> queue = nullptr;
Expand Down Expand Up @@ -197,6 +293,8 @@ static void Queue(benchmark::State& state) {
counter += int(q.consume([](typename type::value_type*){ return true; }));
}
}
state.SetItemsProcessed(state.iterations() * 10000);
state.SetBytesProcessed(state.iterations() * 10000 * sizeof(typename type::value_type));

if (q.is_empty() == false) {
state.SkipWithError("Not Empty after test");
Expand Down Expand Up @@ -241,6 +339,8 @@ static void QueueMultiple(benchmark::State& state) {
counter += q.consume_all([](typename type::value_type * val) { return true; });
}
}
state.SetItemsProcessed(state.iterations() * 10000);
state.SetBytesProcessed(state.iterations() * 10000 * sizeof(typename type::value_type));

if (q.is_empty() == false) {
state.SkipWithError("Not Empty after test");
Expand Down Expand Up @@ -285,6 +385,8 @@ static void RigtorpQueue(benchmark::State& state) {
}
}
}
state.SetItemsProcessed(state.iterations() * 10000);
state.SetBytesProcessed(state.iterations() * 10000 * sizeof(typename type::value_type));

if (q.empty() == false) {
state.SkipWithError("Not Empty after test");
Expand Down Expand Up @@ -329,6 +431,8 @@ static void MoodycamelQueue(benchmark::State& state) {
}
}
}
state.SetItemsProcessed(state.iterations() * 10000);
state.SetBytesProcessed(state.iterations() * 10000 * sizeof(typename type::value_type));

if (q.size_approx() != 0) {
state.SkipWithError("Not Empty after test");
Expand Down Expand Up @@ -407,6 +511,23 @@ BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_cached_masked<28>)->Apply(config
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_cached_masked<29>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_cached_masked<30>)->Apply(configure_benchmark);

BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<15>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<16>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<17>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<18>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<19>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<20>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<21>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<22>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<23>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<24>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<25>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<26>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<27>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<28>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<29>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_chunked<30>)->Apply(configure_benchmark);

BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_heap<15>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_heap<16>)->Apply(configure_benchmark);
BENCHMARK_TEMPLATE(RingBuffer, spsc_ring_buffer_heap<17>)->Apply(configure_benchmark);
Expand Down Expand Up @@ -442,8 +563,7 @@ struct DummyContainer<56> {
DummyContainer() {
__m256 a = _mm256_setzero_ps();
_mm256_storeu_ps((float*)dummy, a);
_mm_storeu_ps((float*)(dummy + 32), _mm256_castps256_ps128(a));
*((uint64_t*)(dummy + 48)) = 0;
_mm256_storeu_ps((float*)(dummy + 24), a);
}
};

Expand Down Expand Up @@ -505,14 +625,23 @@ BENCHMARK_TEMPLATE(FollyQueue, folly::ProducerConsumerQueue<DummyContainer<48>>)
BENCHMARK_TEMPLATE(FollyQueue, folly::ProducerConsumerQueue<DummyContainer<56>>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyQueue, folly::ProducerConsumerQueue<DummyContainer<64>>)->Apply(configure_folly_queue);

BENCHMARK_TEMPLATE(FollyQueue, folly::ProducerConsumerQueueCached<DummyContainer<8>>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyQueue, folly::ProducerConsumerQueueCached<DummyContainer<16>>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyQueue, folly::ProducerConsumerQueueCached<DummyContainer<24>>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyQueue, folly::ProducerConsumerQueueCached<DummyContainer<32>>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyQueue, folly::ProducerConsumerQueueCached<DummyContainer<40>>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyQueue, folly::ProducerConsumerQueueCached<DummyContainer<48>>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyQueue, folly::ProducerConsumerQueueCached<DummyContainer<56>>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyQueue, folly::ProducerConsumerQueueCached<DummyContainer<64>>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyUnboundedQueue, folly::USPSCQueue<DummyContainer<8>, false, 12>, DummyContainer<8>)->Apply(configure_queue);
BENCHMARK_TEMPLATE(FollyUnboundedQueue, folly::USPSCQueue<DummyContainer<16>, false, 11>, DummyContainer<16>)->Apply(configure_queue);
BENCHMARK_TEMPLATE(FollyUnboundedQueue, folly::USPSCQueue<DummyContainer<24>, false, 10>, DummyContainer<24>)->Apply(configure_queue);
BENCHMARK_TEMPLATE(FollyUnboundedQueue, folly::USPSCQueue<DummyContainer<32>, false, 10>, DummyContainer<32>)->Apply(configure_queue);
BENCHMARK_TEMPLATE(FollyUnboundedQueue, folly::USPSCQueue<DummyContainer<40>, false, 9>, DummyContainer<40>)->Apply(configure_queue);
BENCHMARK_TEMPLATE(FollyUnboundedQueue, folly::USPSCQueue<DummyContainer<48>, false, 9>, DummyContainer<48>)->Apply(configure_queue);
BENCHMARK_TEMPLATE(FollyUnboundedQueue, folly::USPSCQueue<DummyContainer<56>, false, 9>, DummyContainer<56>)->Apply(configure_queue);
BENCHMARK_TEMPLATE(FollyUnboundedQueue, folly::USPSCQueue<DummyContainer<64>, false, 9>, DummyContainer<64>)->Apply(configure_queue);

BENCHMARK_TEMPLATE(FollyDBQueue, folly::DSPSCQueue<DummyContainer<8>, false, 12>, DummyContainer<8>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyDBQueue, folly::DSPSCQueue<DummyContainer<16>, false, 11>, DummyContainer<16>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyDBQueue, folly::DSPSCQueue<DummyContainer<24>, false, 10>, DummyContainer<24>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyDBQueue, folly::DSPSCQueue<DummyContainer<32>, false, 10>, DummyContainer<32>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyDBQueue, folly::DSPSCQueue<DummyContainer<40>, false, 9>, DummyContainer<40>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyDBQueue, folly::DSPSCQueue<DummyContainer<48>, false, 9>, DummyContainer<48>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyDBQueue, folly::DSPSCQueue<DummyContainer<56>, false, 9>, DummyContainer<56>)->Apply(configure_folly_queue);
BENCHMARK_TEMPLATE(FollyDBQueue, folly::DSPSCQueue<DummyContainer<64>, false, 9>, DummyContainer<64>)->Apply(configure_folly_queue);

#if 1
BENCHMARK_TEMPLATE(Queue, spsc_queue<DummyContainer<8>, 12>)->Apply(configure_queue);
Expand Down
Loading

0 comments on commit 929198e

Please sign in to comment.