-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Stats no vector #17909
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stats no vector #17909
Changes from all commits
a57e03a
9154c94
8325266
d556414
f91bb29
db248ad
5be8b36
c847d1c
6e38658
291a2ff
b9039ac
e5a8a82
b2e5d5f
cb7750f
e4615c1
66bfed4
915ea77
6f6ce30
bb3306b
a85a887
3eeb986
d7b5ed5
58bd2ba
3e71e1a
9166754
f6a456b
65b2c78
f92e178
4a5572d
7cad621
b10d6e1
0f9ea87
d6116e8
263205e
801190f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| #include "source/common/stats/allocator_impl.h" | ||
|
|
||
| #include <algorithm> | ||
| #include <cstdint> | ||
|
|
||
| #include "envoy/stats/stats.h" | ||
|
|
@@ -25,6 +26,25 @@ const char AllocatorImpl::DecrementToZeroSyncPoint[] = "decrement-zero"; | |
| AllocatorImpl::~AllocatorImpl() { | ||
| ASSERT(counters_.empty()); | ||
| ASSERT(gauges_.empty()); | ||
|
|
||
| #ifndef NDEBUG | ||
| // Move deleted stats into the sets for the ASSERTs in removeFromSetLockHeld to function. | ||
| for (auto& counter : deleted_counters_) { | ||
| auto insertion = counters_.insert(counter.get()); | ||
| // Assert that there were no duplicates. | ||
| ASSERT(insertion.second); | ||
| } | ||
| for (auto& gauge : deleted_gauges_) { | ||
| auto insertion = gauges_.insert(gauge.get()); | ||
| // Assert that there were no duplicates. | ||
| ASSERT(insertion.second); | ||
| } | ||
| for (auto& text_readout : deleted_text_readouts_) { | ||
| auto insertion = text_readouts_.insert(text_readout.get()); | ||
| // Assert that there were no duplicates. | ||
| ASSERT(insertion.second); | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
| #ifndef ENVOY_CONFIG_COVERAGE | ||
|
|
@@ -316,5 +336,77 @@ Counter* AllocatorImpl::makeCounterInternal(StatName name, StatName tag_extracte | |
| return new CounterImpl(name, *this, tag_extracted_name, stat_name_tags); | ||
| } | ||
|
|
||
| void AllocatorImpl::forEachCounter(std::function<void(std::size_t)> f_size, | ||
jmarantz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| std::function<void(Stats::Counter&)> f_stat) const { | ||
| Thread::LockGuard lock(mutex_); | ||
| if (f_size != nullptr) { | ||
| f_size(counters_.size()); | ||
| } | ||
| for (auto& counter : counters_) { | ||
| f_stat(*counter); | ||
| } | ||
| } | ||
|
|
||
| void AllocatorImpl::forEachGauge(std::function<void(std::size_t)> f_size, | ||
| std::function<void(Stats::Gauge&)> f_stat) const { | ||
jmarantz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Thread::LockGuard lock(mutex_); | ||
| if (f_size != nullptr) { | ||
| f_size(gauges_.size()); | ||
| } | ||
| for (auto& gauge : gauges_) { | ||
| f_stat(*gauge); | ||
| } | ||
| } | ||
|
|
||
| void AllocatorImpl::forEachTextReadout(std::function<void(std::size_t)> f_size, | ||
| std::function<void(Stats::TextReadout&)> f_stat) const { | ||
| Thread::LockGuard lock(mutex_); | ||
| if (f_size != nullptr) { | ||
| f_size(text_readouts_.size()); | ||
| } | ||
| for (auto& text_readout : text_readouts_) { | ||
| f_stat(*text_readout); | ||
| } | ||
| } | ||
|
|
||
| void AllocatorImpl::markCounterForDeletion(const CounterSharedPtr& counter) { | ||
| Thread::LockGuard lock(mutex_); | ||
| auto iter = counters_.find(counter->statName()); | ||
| if (iter == counters_.end()) { | ||
| // This has already been marked for deletion. | ||
| return; | ||
| } | ||
| ASSERT(counter.get() == *iter); | ||
| // Duplicates are ASSERTed in ~AllocatorImpl. | ||
| deleted_counters_.emplace_back(*iter); | ||
| counters_.erase(iter); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought of a concern with this tactic for this class: if someone allocates a counter with the same name as one that was marked for deletion, we'll wind with two different counter objects with the same name. That might be OK but we might want to add a test. It won't actually happen with ThreadLocalStore because it only calls markCounterForDeletion on stats that are rejected by the matcher, and the matcher can't be changed once it's added. The reason that this is needed is that the matcher can be added after some stats are created, and we need to effectively get rid of the now-rejected stats without causing references to freed memory. Possible remedies I thought of include:
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This approach sounds good to me, fwiw. Stepping back though, I'm trying to understand why this logic was moved into the allocator versus where it used to be in thread local store? Can you help me understand that? |
||
| } | ||
|
|
||
| void AllocatorImpl::markGaugeForDeletion(const GaugeSharedPtr& gauge) { | ||
| Thread::LockGuard lock(mutex_); | ||
| auto iter = gauges_.find(gauge->statName()); | ||
| if (iter == gauges_.end()) { | ||
| // This has already been marked for deletion. | ||
| return; | ||
| } | ||
| ASSERT(gauge.get() == *iter); | ||
| // Duplicates are ASSERTed in ~AllocatorImpl. | ||
| deleted_gauges_.emplace_back(*iter); | ||
| gauges_.erase(iter); | ||
| } | ||
|
|
||
| void AllocatorImpl::markTextReadoutForDeletion(const TextReadoutSharedPtr& text_readout) { | ||
| Thread::LockGuard lock(mutex_); | ||
| auto iter = text_readouts_.find(text_readout->statName()); | ||
| if (iter == text_readouts_.end()) { | ||
| // This has already been marked for deletion. | ||
| return; | ||
| } | ||
| ASSERT(text_readout.get() == *iter); | ||
| // Duplicates are ASSERTed in ~AllocatorImpl. | ||
| deleted_text_readouts_.emplace_back(*iter); | ||
| text_readouts_.erase(iter); | ||
| } | ||
|
|
||
| } // namespace Stats | ||
| } // namespace Envoy | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note here the surprising behavior that if you allocate a stat after having done this, you'll get a new one, and that callers should seek to avoid this situation (as ThreadLocalStore does).