Skip to content

Commit

Permalink
no key copies in TLStatNameSet
Browse files Browse the repository at this point in the history
Summary: Instead of copying the stat names into the map keys, use a set with specialized key-hash and key-equal functions.

Reviewed By: Gownta

Differential Revision: D68386450

fbshipit-source-id: 4994ab45c9f4d47fb42fd54739763c69ab95ac98
  • Loading branch information
yfeldblum authored and facebook-github-bot committed Jan 31, 2025
1 parent dcfc88d commit 91ab256
Showing 1 changed file with 37 additions and 5 deletions.
42 changes: 37 additions & 5 deletions fb303/ThreadLocalStats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,37 @@ class TLStatNameSet::Impl {
}
};

using Set = folly::F14FastMap<std::string, Wp>;
/// typical layout of std::shared_ptr and std::weak_ptr
/// need controlled access to address of object even from weak_ptr
///
/// layout consistent with libstdc++, libc++, microsoft-stl
template <typename T>
struct WpLayout {
T* const object{};
void const* const control{};

explicit WpLayout(std::weak_ptr<T> const& wp) noexcept
: WpLayout(reinterpret_cast<WpLayout const&>(wp)) {}
};

struct Key {
Wp weak;
/* implicit */ operator std::string_view() const noexcept {
return *WpLayout(weak).object; // assume lockable - not-null, still-alive
}
};

struct KeyHash : std::hash<std::string_view> {
using is_transparent = void;
using std::hash<std::string_view>::operator();
};

struct KeyEqual : std::equal_to<std::string_view> {
using is_transparent = void;
using std::equal_to<std::string_view>::operator();
};

using Set = folly::F14FastSet<Key, KeyHash, KeyEqual>;

/// split to reduce potential lock contention at startup for threads looking
/// up distinct names
Expand All @@ -94,7 +124,8 @@ class TLStatNameSet::Impl {
void clean(std::string const& name) {
auto const wlock = set(name).wlock();
if (auto const it = wlock->find(name); it != wlock->end()) {
if (!it->second.lock()) {
if (WpLayout(it->weak).object == &name) {
assert(!it->weak.lock());
wlock->erase(it);
}
}
Expand All @@ -103,19 +134,20 @@ class TLStatNameSet::Impl {
Sp getSlow(std::string_view const name) {
auto const wlock = set(name).wlock();
if (auto const it = wlock->find(name); it != wlock->end()) {
if (auto sp = it->second.lock()) {
if (auto sp = it->weak.lock()) {
return sp;
}
wlock->erase(it); // in case this call races with corresponding clean()
}
auto sp = Sp{new std::string(name), SpDeleter{}};
(*wlock)[std::string(name)] = sp;
wlock->insert(Key{sp});
return sp;
}

Sp getFast(std::string_view const name) {
auto const rlock = set(name).rlock();
if (auto const it = rlock->find(name); it != rlock->end()) {
if (auto sp = it->second.lock()) {
if (auto sp = it->weak.lock()) {
return sp;
}
}
Expand Down

0 comments on commit 91ab256

Please sign in to comment.