Skip to content

Commit

Permalink
Cleanup ThreadCache and LifeCycledId
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 494254080
  • Loading branch information
martijnvels authored and copybara-github committed Dec 9, 2022
1 parent a49bfa9 commit 821b073
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 32 deletions.
17 changes: 7 additions & 10 deletions src/google/protobuf/arena.cc
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,8 @@ ThreadSafeArena::SerialArenaChunk* ThreadSafeArena::SentrySerialArenaChunk() {
}


ThreadSafeArena::CacheAlignedLifecycleIdGenerator
ThreadSafeArena::lifecycle_id_generator_;
ABSL_CONST_INIT alignas(kCacheAlignment)
std::atomic<ThreadSafeArena::LifecycleId> ThreadSafeArena::lifecycle_id_{0};
#if defined(PROTOBUF_NO_THREADLOCAL)
ThreadSafeArena::ThreadCache& ThreadSafeArena::thread_cache() {
static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
Expand All @@ -451,14 +451,12 @@ ThreadSafeArena::ThreadCache& ThreadSafeArena::thread_cache() {
}
#elif defined(PROTOBUF_USE_DLLS)
ThreadSafeArena::ThreadCache& ThreadSafeArena::thread_cache() {
static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_ = {
0, static_cast<LifecycleIdAtomic>(-1), nullptr};
return thread_cache_;
static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache;
return thread_cache;
}
#else
PROTOBUF_THREAD_LOCAL ThreadSafeArena::ThreadCache
ThreadSafeArena::thread_cache_ = {0, static_cast<LifecycleIdAtomic>(-1),
nullptr};
ABSL_CONST_INIT PROTOBUF_THREAD_LOCAL
ThreadSafeArena::ThreadCache ThreadSafeArena::thread_cache_;
#endif

ThreadSafeArena::ThreadSafeArena() : first_arena_(*this) { Init(); }
Expand Down Expand Up @@ -549,8 +547,7 @@ uint64_t ThreadSafeArena::GetNextLifeCycleId() {
// On platforms that don't support uint64_t atomics we can certainly not
// afford to increment by large intervals and expect uniqueness due to
// wrapping, hence we only add by 1.
id = lifecycle_id_generator_.id.fetch_add(1, std::memory_order_relaxed) *
kInc;
id = lifecycle_id_.fetch_add(1, std::memory_order_relaxed) * kInc;
}
tc.next_lifecycle_id = id + kDelta;
return id;
Expand Down
29 changes: 7 additions & 22 deletions src/google/protobuf/arena_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,6 @@ struct ArenaBlock {
// data follows
};

using LifecycleIdAtomic = uint64_t;

enum class AllocationClient { kDefault, kArray };

class ThreadSafeArena;
Expand Down Expand Up @@ -582,28 +580,18 @@ class PROTOBUF_EXPORT ThreadSafeArena {
#pragma warning(disable : 4324)
#endif
struct alignas(kCacheAlignment) ThreadCache {
#if defined(PROTOBUF_NO_THREADLOCAL)
// If we are using the ThreadLocalStorage class to store the ThreadCache,
// then the ThreadCache's default constructor has to be responsible for
// initializing it.
ThreadCache()
: next_lifecycle_id(0),
last_lifecycle_id_seen(-1),
last_serial_arena(nullptr) {}
#endif

// Number of per-thread lifecycle IDs to reserve. Must be power of two.
// To reduce contention on a global atomic, each thread reserves a batch of
// IDs. The following number is calculated based on a stress test with
// ~6500 threads all frequently allocating a new arena.
static constexpr size_t kPerThreadIds = 256;
// Next lifecycle ID available to this thread. We need to reserve a new
// batch, if `next_lifecycle_id & (kPerThreadIds - 1) == 0`.
uint64_t next_lifecycle_id;
uint64_t next_lifecycle_id{0};
// The ThreadCache is considered valid as long as this matches the
// lifecycle_id of the arena being used.
uint64_t last_lifecycle_id_seen;
SerialArena* last_serial_arena;
uint64_t last_lifecycle_id_seen{static_cast<uint64_t>(-1)};
SerialArena* last_serial_arena{nullptr};
};

// Lifecycle_id can be highly contended variable in a situation of lots of
Expand All @@ -612,12 +600,9 @@ class PROTOBUF_EXPORT ThreadSafeArena {
#ifdef _MSC_VER
#pragma warning(disable : 4324)
#endif
struct alignas(kCacheAlignment) CacheAlignedLifecycleIdGenerator {
constexpr CacheAlignedLifecycleIdGenerator() : id{0} {}

std::atomic<LifecycleIdAtomic> id;
};
static CacheAlignedLifecycleIdGenerator lifecycle_id_generator_;
using LifecycleId = uint64_t;
ABSL_CONST_INIT alignas(
kCacheAlignment) static std::atomic<LifecycleId> lifecycle_id_;
#if defined(PROTOBUF_NO_THREADLOCAL)
// iOS does not support __thread keyword so we use a custom thread local
// storage class we implemented.
Expand All @@ -627,7 +612,7 @@ class PROTOBUF_EXPORT ThreadSafeArena {
// wrap them in static functions.
static ThreadCache& thread_cache();
#else
static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_;
ABSL_CONST_INIT static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_;
static ThreadCache& thread_cache() { return thread_cache_; }
#endif

Expand Down

0 comments on commit 821b073

Please sign in to comment.