-
Notifications
You must be signed in to change notification settings - Fork 5.5k
[server] add unused ENVOY_BUG implementation #11503
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
Changes from 11 commits
ff7ca4f
798bb0e
8f9aba6
1ed929d
e3b47af
c5ab825
00e851e
26cbe25
1adce9f
ce70b00
aacf835
b56f27f
f84faf9
e598f28
9f036bb
4b2b808
6ba5df6
82afac3
2b1e871
3cdbc57
2d2f5ba
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,9 @@ | ||
| #include "common/common/assert.h" | ||
|
|
||
| #include "absl/container/flat_hash_map.h" | ||
| #include "absl/synchronization/mutex.h" | ||
| #include "absl/strings/str_join.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Assert { | ||
|
|
||
|
|
@@ -28,15 +32,76 @@ class ActionRegistrationImpl : public ActionRegistration { | |
| static std::function<void()> debug_assertion_failure_record_action_; | ||
| }; | ||
|
|
||
| class EnvoyBugRegistrationImpl : public ActionRegistration { | ||
| public: | ||
| EnvoyBugRegistrationImpl(std::function<void()> action) { | ||
| ASSERT(envoy_bug_failure_record_action_ == nullptr, | ||
| "An ENVOY_BUG action was already set. Currently only a single action is supported."); | ||
| envoy_bug_failure_record_action_ = action; | ||
|
asraa marked this conversation as resolved.
|
||
| counters_.clear(); | ||
| } | ||
|
|
||
| ~EnvoyBugRegistrationImpl() override { | ||
| ASSERT(envoy_bug_failure_record_action_ != nullptr); | ||
| envoy_bug_failure_record_action_ = nullptr; | ||
| } | ||
|
|
||
| static bool shouldLogAndInvoke(const char* filename, int line) { | ||
| const auto name = absl::StrCat(filename, ",", line); | ||
|
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. perf nit: I would probably pre-stringify the file+line in the macro, since I think the incremental code size is probably about 0, then you don't need to do a potential allocation here. |
||
|
|
||
| // Increment counter, inserting first if counter does not exist. | ||
|
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. I don't think I have a strong opinion on the map vs. inline static, but can you add more comments here on the trade-offs and why we chose this way? I assume it's to reduce code size and I guess per the discussion avoid cache misses on the inline atomic?
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. It's not that we're trying to avoid cache misses on the atomic; if we aren't worried about cache misses in this part of Envoy, and if we don't have benchmarks proving that atomics are significantly more efficient, then we don't have a performance argument for choosing atomics over a higher-level, easier-to-understand construct like a mutex. Quoting from an internal doc on the dangers of atomics that I've been meaning to open-source: There's a common assumption that mutexes are expensive, and that using atomic operations will be more efficient. But in reality, acquiring and releasing a mutex is cheaper than a cache miss; attention to cache behavior is usually a more fruitful way to improve performance.
Contributor
Author
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. Will do. Is the solution to have some kind of static object per file/line in the macro that holds a mutex per file/line and makes accesses to the map? Or is that starting to get too complicated.
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. IMO, a per file/line mutex/object/whatever is more complicated than is necessary at the moment. If we start seeing contention on this mutex, we'd have a lot of ENVOY_BUGs firing at once, which is worth investigation on its own. But I don't think we need to prematurely optimize this.
Contributor
Author
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. Added a comment about this.
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 would just add a comment explaining that this is not performance critical path and contention on this mutex would imply that something horribly went off the rails and caused ENVOY_BUG to fire often on multiple threads.
Contributor
Author
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. done |
||
| absl::ReleasableMutexLock lock(&mutex_); | ||
| auto counter_value = ++counters_[name]; | ||
| lock.Release(); | ||
|
asraa marked this conversation as resolved.
Outdated
|
||
|
|
||
| // Check if counter is power of two by its bitwise representation. | ||
| if ((counter_value & (counter_value - 1)) == 0) { | ||
|
asraa marked this conversation as resolved.
Outdated
|
||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| static void invokeAction() { | ||
| if (envoy_bug_failure_record_action_ != nullptr) { | ||
| envoy_bug_failure_record_action_(); | ||
| } | ||
| } | ||
|
|
||
| private: | ||
| // This implementation currently only handles one action being set at a time. This is currently | ||
| // sufficient. If multiple actions are ever needed, the actions should be chained when | ||
| // additional actions are registered. | ||
| static std::function<void()> envoy_bug_failure_record_action_; | ||
|
|
||
| using EnvoyBugMap = absl::flat_hash_map<std::string, uint64_t>; | ||
| static absl::Mutex mutex_; | ||
| static EnvoyBugMap counters_ GUARDED_BY(mutex_); | ||
| }; | ||
|
|
||
| std::function<void()> ActionRegistrationImpl::debug_assertion_failure_record_action_; | ||
| std::function<void()> EnvoyBugRegistrationImpl::envoy_bug_failure_record_action_; | ||
| EnvoyBugRegistrationImpl::EnvoyBugMap EnvoyBugRegistrationImpl::counters_; | ||
| absl::Mutex EnvoyBugRegistrationImpl::mutex_; | ||
|
|
||
| ActionRegistrationPtr setDebugAssertionFailureRecordAction(const std::function<void()>& action) { | ||
| return std::make_unique<ActionRegistrationImpl>(action); | ||
| } | ||
|
|
||
| void invokeDebugAssertionFailureRecordAction_ForAssertMacroUseOnly() { | ||
| ActionRegistrationPtr setEnvoyBugFailureRecordAction(const std::function<void()>& action) { | ||
| return std::make_unique<EnvoyBugRegistrationImpl>(action); | ||
| } | ||
|
|
||
| void invokeDebugAssertionFailureRecordActionForAssertMacroUseOnly() { | ||
| ActionRegistrationImpl::invokeAction(); | ||
| } | ||
|
|
||
| void invokeEnvoyBugFailureRecordActionForEnvoyBugMacroUseOnly() { | ||
| EnvoyBugRegistrationImpl::invokeAction(); | ||
| } | ||
|
|
||
| bool shouldLogAndInvokeEnvoyBugForEnvoyBugMacroUseOnly(const char* filename, int line) { | ||
| return EnvoyBugRegistrationImpl::shouldLogAndInvoke(filename, line); | ||
| } | ||
|
|
||
| } // namespace Assert | ||
| } // 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.
I don't think this is going to mean anything to a normal user. Should we link somewhere that describes this in a bit more detail and what to do if this increments? Presumably open an issue as there is a serious issue, etc.?
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.
done -- I also added some more doc string explanation in
assert.habout its contrast with ASSERT.I'd like to link that in, is that an appropriate place? Or link this PR?