Skip to content

Commit

Permalink
optimize bits of HistogramWrapper::add
Browse files Browse the repository at this point in the history
Summary:
* Move deferred initialization in `ensureApplySpec` from the fast-path to the slow-path.
* Use `ThreadLocalPtr<TLHistogram>` v.s. `ThreadLocal<shared_ptr<TLHistogram>>` to reduce object size and to remove one level of indirection. `ThreadLocalPtr<T>` has special support for being assigned `shared_ptr<T>`.
* Put spec on heap and delete it after deferred init to reduce its memory consumption.

Reviewed By: Gownta

Differential Revision: D66590811

fbshipit-source-id: 10ed7c5219bd6cfde0ca7d6d18ce52040ab239bb
  • Loading branch information
yfeldblum authored and facebook-github-bot committed Dec 3, 2024
1 parent ec0310d commit ebc0a7b
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 22 deletions.
13 changes: 13 additions & 0 deletions fb303/ThreadCachedServiceData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,19 @@ SubminuteMinuteOnlyTimeseriesWrapper::templateExportedStat() {
return *obj.get();
}

FOLLY_NOINLINE void HistogramWrapper::doApplySpecLocked() {
std::exchange(spec_, {})->apply(key_, ServiceData::get());
}

FOLLY_NOINLINE ThreadCachedServiceData::TLHistogram*
HistogramWrapper::tcHistogramSlow() {
folly::call_once(once_, &HistogramWrapper::doApplySpecLocked, this);
auto& local = ThreadCachedServiceData::getStatsThreadLocal();
auto const histogram = local->getHistogramSafe(key_);
tlHistogram_.reset(histogram);
return histogram.get();
}

ThreadCachedServiceData::StatsThreadLocal&
ThreadCachedServiceData::getStatsThreadLocal() {
static folly::Indestructible<ThreadCachedServiceData::StatsThreadLocal>
Expand Down
35 changes: 13 additions & 22 deletions fb303/ThreadCachedServiceData.h
Original file line number Diff line number Diff line change
Expand Up @@ -1204,39 +1204,30 @@ class HistogramWrapper {
int64_t min,
int64_t max,
const Args&... args)
: key_(key), spec_(bucketWidth, min, max, args...) {}
: key_(key),
spec_(std::make_unique<internal::HistogramSpec>(
bucketWidth,
min,
max,
args...)) {}

void add(int64_t value = 1) {
ensureApplySpec();
tcHistogram()->addValue(value);
}

protected:
void doApplySpecLocked() {
spec_.apply(key_, ThreadCachedServiceData::get());
}
FOLLY_ALWAYS_INLINE void ensureApplySpec() {
// minimize inline slow path size by passing the callback this way
folly::call_once(once_, &HistogramWrapper::doApplySpecLocked, this);
}

inline ThreadCachedServiceData::TLHistogram* tcHistogram() {
ThreadCachedServiceData::TLHistogram* cached = tlHistogram_->get();
if (cached) {
return cached;
}
void doApplySpecLocked();

auto histogram =
ThreadCachedServiceData::getStatsThreadLocal()->getHistogramSafe(key_);
*tlHistogram_ = histogram;
return histogram.get();
FOLLY_ALWAYS_INLINE ThreadCachedServiceData::TLHistogram* tcHistogram() {
ThreadCachedServiceData::TLHistogram* cached = tlHistogram_.get();
return FOLLY_LIKELY(!!cached) ? cached : tcHistogramSlow();
}
ThreadCachedServiceData::TLHistogram* tcHistogramSlow();

folly::once_flag once_;
std::string key_;
internal::HistogramSpec spec_;
folly::ThreadLocal<std::shared_ptr<ThreadCachedServiceData::TLHistogram>>
tlHistogram_;
std::unique_ptr<internal::HistogramSpec> spec_; // ptr for memory-size
folly::ThreadLocalPtr<ThreadCachedServiceData::TLHistogram> tlHistogram_;
};

class MinuteOnlyHistogram : public HistogramWrapper {
Expand Down

0 comments on commit ebc0a7b

Please sign in to comment.