Commit 6f9321c4 authored by Giuseppe Ottaviano's avatar Giuseppe Ottaviano Committed by Facebook GitHub Bot

Improve cpu id caching in DigestBuilder

Summary:
`DigestBuilder` caches the cpu id and invalidates it when it detects contention, but the critical section is small enough that it is possible for two thread to end up on a conflicting slot but not detect it for some time, causing cache-line pingponging in the meantime.

Switch to `cachedCurrent()` instead, which uses the number of accesses to invalidate the cache, and is successfully adopted by other high-concurrency primitives.

Reviewed By: yfeldblum

Differential Revision: D27726518

fbshipit-source-id: 05d70ad9f101df4a8797e44cc3cbe94cbd1cb7b8
parent d5bf7f5a
...@@ -23,8 +23,6 @@ ...@@ -23,8 +23,6 @@
namespace folly { namespace folly {
namespace detail { namespace detail {
static thread_local uint32_t tls_lastCpuBufferSlot = 0;
template <typename DigestT> template <typename DigestT>
DigestBuilder<DigestT>::DigestBuilder(size_t bufferSize, size_t digestSize) DigestBuilder<DigestT>::DigestBuilder(size_t bufferSize, size_t digestSize)
: bufferSize_(bufferSize), digestSize_(digestSize) { : bufferSize_(bufferSize), digestSize_(digestSize) {
...@@ -71,14 +69,9 @@ DigestT DigestBuilder<DigestT>::build() { ...@@ -71,14 +69,9 @@ DigestT DigestBuilder<DigestT>::build() {
template <typename DigestT> template <typename DigestT>
void DigestBuilder<DigestT>::append(double value) { void DigestBuilder<DigestT>::append(double value) {
auto& which = tls_lastCpuBufferSlot; auto cpuLocalBuf = &cpuLocalBuffers_[AccessSpreader<>::cachedCurrent(
auto cpuLocalBuf = &cpuLocalBuffers_[which]; cpuLocalBuffers_.size())];
std::unique_lock<SpinLock> g(cpuLocalBuf->mutex, std::try_to_lock_t()); std::unique_lock<SpinLock> g(cpuLocalBuf->mutex);
if (!g.owns_lock()) {
which = AccessSpreader<>::current(cpuLocalBuffers_.size());
cpuLocalBuf = &cpuLocalBuffers_[which];
g = std::unique_lock<SpinLock>(cpuLocalBuf->mutex);
}
cpuLocalBuf->buffer.push_back(value); cpuLocalBuf->buffer.push_back(value);
if (cpuLocalBuf->buffer.size() == bufferSize_) { if (cpuLocalBuf->buffer.size() == bufferSize_) {
if (!cpuLocalBuf->digest) { if (!cpuLocalBuf->digest) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment