Skip to content
Snippets Groups Projects
Unverified Commit c51f8563 authored by Lioncash's avatar Lioncash
Browse files

ring_buffer: Use std::hardware_destructive_interference_size to determine...

ring_buffer: Use std::hardware_destructive_interference_size to determine alignment size for avoiding false sharing

MSVC 19.11 (A.K.A. VS 15.3)'s C++ standard library implements P0154R1
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html)
which defines two new constants within the <new> header, std::hardware_destructive_interference_size
and std::hardware_constructive_interference_size.

std::hardware_destructive_interference_size defines the minimum
recommended offset between two concurrently-accessed objects to avoid
performance degradation due to contention introduced by the
implementation (with the lower-bound being at least alignof(max_align_t)).
In other words, the minimum offset between objects necessary to avoid
false-sharing.

std::hardware_constructive_interference_size on the other hand defines
the maximum recommended size of contiguous memory occupied by two
objects accessed wth temporal locality by concurrent threads (also
defined to be at least alignof(max_align_t)). In other words the maximum
size to promote true-sharing.

So we can simply use this facility to determine the ideal alignment
size. Unfortunately, only MSVC supports this right now, so we need to
enclose it within an ifdef for the time being.
parent b33ce787
No related branches found
No related tags found
No related merge requests found
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <atomic> #include <atomic>
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>
#include <new>
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
#include "common/common_types.h" #include "common/common_types.h"
...@@ -102,8 +103,15 @@ public: ...@@ -102,8 +103,15 @@ public:
private: private:
// It is important to align the below variables for performance reasons: // It is important to align the below variables for performance reasons:
// Having them on the same cache-line would result in false-sharing between them. // Having them on the same cache-line would result in false-sharing between them.
alignas(128) std::atomic<std::size_t> m_read_index{0}; // TODO: Remove this ifdef whenever clang and GCC support
alignas(128) std::atomic<std::size_t> m_write_index{0}; // std::hardware_destructive_interference_size.
#if defined(_MSC_VER) && _MSC_VER >= 1911
alignas(std::hardware_destructive_interference_size) std::atomic_size_t m_read_index{0};
alignas(std::hardware_destructive_interference_size) std::atomic_size_t m_write_index{0};
#else
alignas(128) std::atomic_size_t m_read_index{0};
alignas(128) std::atomic_size_t m_write_index{0};
#endif
std::array<T, granularity * capacity> m_data; std::array<T, granularity * capacity> m_data;
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment