Skip to content

Commit 49a6da1

Browse files
pbhandar2meta-codesync[bot]
authored andcommitted
Replace atomic_shared_ptr<EventTracker> with unique_ptr in Cache and raw ptr in NVM
Summary: Every cache operation (find, allocate, insert, remove, eviction) call recordEvent(), which calls getEventTracker(). Previously, getEventTracker() called folly::atomic_shared_ptr<EventTracker>::load(), which returns a shared_ptr — incurring an atomic refcount increment on load and an atomic decrement on destruction. On x86, each of these is a lock xadd instruction that forces cache-line synchronization across cores. This overhead occurs on every cache operation, even when the event is not sampled. Since setEventTracker() is called once during initialization (before workers start) and never again, atomic shared pointer semantics are unnecessary. This diff replaces the atomic_shared_ptr with a "cached raw pointer" pattern: - Ownership: std::unique_ptr<EventTracker> in CacheBase holds the sole owning reference, set once during init. - Navy layer: Engine, EnginePair, Driver, and AbstractCache now take and store non-owning EventTracker* pointers, since lifetime is managed by CacheBase. These are set during NVM cache initialization and invalidated by ~CacheAllocator() which destroys NVM cache before ~CacheBase() destroys the EventTracker. Reviewed By: rlyerly Differential Revision: D95646744 fbshipit-source-id: 39d2d352e3bf72bc669c9cdf5dfd3fd165178625
1 parent 7ed37d8 commit 49a6da1

11 files changed

Lines changed: 30 additions & 37 deletions

File tree

cachelib/allocator/Cache.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -630,10 +630,6 @@ void CacheBase::updateAggregatedPoolStats(const std::string& statPrefix) const {
630630
}
631631

632632
void CacheBase::setEventTracker(EventTracker::Config&& config) {
633-
eventTracker_.store(std::make_shared<EventTracker>(std::move(config)));
634-
}
635-
636-
std::shared_ptr<EventTracker> CacheBase::getEventTracker() const {
637-
return eventTracker_.load();
633+
eventTracker_ = std::make_unique<EventTracker>(std::move(config));
638634
}
639635
} // namespace facebook::cachelib

cachelib/allocator/Cache.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616

1717
#pragma once
1818

19-
#include <folly/concurrency/AtomicSharedPtr.h>
19+
#include <folly/lang/Hint.h>
2020
#include <gtest/gtest_prod.h>
2121

22+
#include <memory>
2223
#include <mutex>
2324
#include <unordered_map>
2425

@@ -230,7 +231,9 @@ class CacheBase {
230231
// Whether to aggregate pool stats to reduce ODS counter inflation
231232
bool aggregatePoolStats_{false};
232233

233-
std::shared_ptr<EventTracker> getEventTracker() const;
234+
FOLLY_ALWAYS_INLINE EventTracker* getEventTracker() const {
235+
return eventTracker_.get();
236+
}
234237
virtual void setEventTracker(EventTracker::Config&& config);
235238

236239
protected:
@@ -375,7 +378,7 @@ class CacheBase {
375378
poolResizeStrategies_;
376379
std::shared_ptr<PoolOptimizeStrategy> poolOptimizeStrategy_;
377380

378-
folly::atomic_shared_ptr<EventTracker> eventTracker_;
381+
std::unique_ptr<EventTracker> eventTracker_;
379382

380383
// Enable aggregating pool stats
381384
void enableAggregatePoolStats() { aggregatePoolStats_ = true; }

cachelib/allocator/CacheAllocator.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,7 +1246,7 @@ class CacheAllocator : public CacheBase {
12461246
folly::F14FastMap<std::string, uint64_t> getEventTrackerStatsMap()
12471247
const override {
12481248
folly::F14FastMap<std::string, uint64_t> eventTrackerStats;
1249-
if (auto eventTracker = getEventTracker()) {
1249+
if (auto* eventTracker = getEventTracker()) {
12501250
eventTracker->getStats(eventTrackerStats);
12511251
}
12521252
return eventTrackerStats;
@@ -1261,8 +1261,8 @@ class CacheAllocator : public CacheBase {
12611261

12621262
// If NVM cache is enabled, also set the event tracker there
12631263
if (nvmCache_ && nvmCache_->isEnabled()) {
1264-
if (auto eventTracker = getEventTracker()) {
1265-
nvmCache_->setEventTracker(eventTracker);
1264+
if (auto* et = getEventTracker()) {
1265+
nvmCache_->setEventTracker(et);
12661266
}
12671267
}
12681268
}
@@ -1840,7 +1840,7 @@ class CacheAllocator : public CacheBase {
18401840
Key key,
18411841
AllocatorApiResult result,
18421842
EventRecordParams params = {}) const {
1843-
if (auto eventTracker = getEventTracker()) {
1843+
if (auto* eventTracker = getEventTracker()) {
18441844
if (eventTracker->sampleKey(key)) {
18451845
EventInfo eventInfo;
18461846
eventInfo.eventTimestamp = util::getCurrentTimeSec();
@@ -2719,9 +2719,9 @@ void CacheAllocator<CacheTrait>::initNvmCache(bool dramCacheAttached) {
27192719
config_.itemDestructor, persistParam);
27202720

27212721
// Set EventTracker dynamically after NvmCache creation
2722-
if (auto eventTracker = getEventTracker()) {
2722+
if (auto* et = getEventTracker()) {
27232723
XLOG(INFO) << "Setting event tracker in NVM cache engines.";
2724-
nvmCache_->setEventTracker(eventTracker);
2724+
nvmCache_->setEventTracker(et);
27252725
}
27262726
if (!config_.cacheDir.empty()) {
27272727
nvmCacheState_.clearPrevState();

cachelib/allocator/nvmcache/CacheApiWrapper.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ class CacheAPIWrapperForNvm {
143143
return cache.getLegacyEventTracker();
144144
}
145145

146-
static std::shared_ptr<EventTracker> getEventTracker(C& cache) {
146+
static EventTracker* getEventTracker(C& cache) {
147147
return cache.getEventTracker();
148148
}
149149

cachelib/allocator/nvmcache/NvmCache.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,9 @@ class NvmCache {
274274
}
275275

276276
// Set the EventTracker for all underlying NVM engines
277-
void setEventTracker(std::shared_ptr<EventTracker> tracker) {
277+
void setEventTracker(EventTracker* tracker) {
278278
if (navyCache_) {
279-
navyCache_->setEventTracker(std::move(tracker));
279+
navyCache_->setEventTracker(tracker);
280280
}
281281
}
282282

cachelib/navy/AbstractCache.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ class AbstractCache {
5151
public:
5252
virtual ~AbstractCache() = default;
5353

54-
// Set the EventTracker for all underlying engines
55-
virtual void setEventTracker(std::shared_ptr<EventTracker> tracker) = 0;
54+
// Set the EventTracker for all underlying engines (non-owning pointer)
55+
virtual void setEventTracker(EventTracker* tracker) = 0;
5656

5757
// Return true if item is considered a "large item". This is meant to be
5858
// a very fast check to verify a key & value pair will be considered as

cachelib/navy/driver/Driver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ void Driver::updateEvictionStats(HashedKey key,
395395
enginePairs_[selectEnginePair(key)].updateEvictionStats(key, value, lifetime);
396396
}
397397

398-
void Driver::setEventTracker(std::shared_ptr<EventTracker> tracker) {
398+
void Driver::setEventTracker(EventTracker* tracker) {
399399
for (auto& enginePair : enginePairs_) {
400400
enginePair.setEventTracker(tracker);
401401
}

cachelib/navy/driver/Driver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ class Driver final : public AbstractCache {
177177
uint32_t lifetime) override;
178178

179179
// Set the EventTracker for all underlying engines
180-
void setEventTracker(std::shared_ptr<EventTracker> tracker) override;
180+
void setEventTracker(EventTracker* tracker) override;
181181

182182
private:
183183
struct ValidConfigTag {};

cachelib/navy/engine/Engine.h

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
#pragma once
1818

19-
#include <folly/concurrency/AtomicSharedPtr.h>
20-
2119
#include "cachelib/common/EventTracker.h"
2220
#include "cachelib/navy/AbstractCache.h"
2321
#include "cachelib/navy/common/Hash.h"
@@ -30,17 +28,12 @@ class Engine {
3028
public:
3129
virtual ~Engine() = default;
3230

33-
// Set the EventTracker for this engine.
34-
// Thread-safe: can be called at runtime while other threads read.
35-
void setEventTracker(std::shared_ptr<EventTracker> tracker) {
36-
eventTracker_.store(std::move(tracker));
37-
}
31+
// Set the EventTracker for this engine (non-owning pointer).
32+
// Must be called before concurrent access begins.
33+
void setEventTracker(EventTracker* tracker) { eventTracker_ = tracker; }
3834

3935
// Get the EventTracker for this engine.
40-
// Thread-safe: returns a copy of the shared_ptr atomically.
41-
std::shared_ptr<EventTracker> getEventTracker() const {
42-
return eventTracker_.load();
43-
}
36+
EventTracker* getEventTracker() const { return eventTracker_; }
4437

4538
// return the size of usable space
4639
virtual uint64_t getSize() const = 0;
@@ -104,7 +97,8 @@ class Engine {
10497
virtual void updateEvictionStats(uint32_t lifetime) = 0;
10598

10699
protected:
107-
folly::atomic_shared_ptr<EventTracker> eventTracker_;
100+
// Non-owning pointer; lifetime managed by CacheBase.
101+
EventTracker* eventTracker_{nullptr};
108102
};
109103
} // namespace navy
110104
} // namespace cachelib

cachelib/navy/engine/EnginePair.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,10 +353,10 @@ void EnginePair::updateEvictionStats(HashedKey hk,
353353
}
354354
}
355355

356-
void EnginePair::setEventTracker(std::shared_ptr<EventTracker> tracker) {
356+
void EnginePair::setEventTracker(EventTracker* tracker) {
357357
// Not setting in BigHash for now since we do not log anything there yet.
358358
if (largeItemCache_) {
359-
largeItemCache_->setEventTracker(std::move(tracker));
359+
largeItemCache_->setEventTracker(tracker);
360360
}
361361
}
362362

0 commit comments

Comments
 (0)