-
Notifications
You must be signed in to change notification settings - Fork 38.6k
Put lock contention logging behind DEBUG_LOCKCONTENTION preprocessor directive
#24734
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
Put lock contention logging behind DEBUG_LOCKCONTENTION preprocessor directive
#24734
Conversation
|
Alternatively, we could keep the lock category only when Obvious concept ACK. |
Agree! This would allow leaving the flag defined for development while being able to switch it off at runtime. All the benefits without the drawbacks. Will update. |
DEBUG_LOCKCONTENTION preprocessor directive
0d1248b to
73759f8
Compare
shaavan
left a comment
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.
ACK 73759f88537e472dc443318a16545d63e6c22024
Let me summarize how I understood this PR:
- This PR introduced (back) the
DEBUG_LOCKCONTENTIONcompile-time processor directive to allow the user to opt-out of potentially costly and dangerous run time locking log usingBase::try_lock().
If my understanding of this PR is correct, I agree with its concept of it:
- I like the prudent approach in case we find out using
Base::try_lock()was not the efficient way of logging. - This keeps the earlier benefits introduced with run-time logging, so we are not losing a beneficial feature.
Considering the comments of @laanwj and @ajtowns
- The reduced diff looks much cleaner than the earlier version of this PR.
- As per @laanwj suggestion, the updated code keeps the benefits of run-time logging instead of completely reverting them, which I agree with.
|
Mind that updating the checkqueue_tests setup doesn't seem needed, but can do if people prefer. -> Edit: done, as the test without |
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
|
With this change, if which is better than being silently inactive. |
73759f8 to
22bbd84
Compare
|
So this will be disabled for all CI tasks? If yes, could enable it for some, or by default in Otherwise the code is never compiled, which makes me wonder if it ever was compiled before the changes? |
I was thinking about that, as personally I would always want to define |
|
If it was never enabled previously, it can also be done as a follow-up. Just wanted to raise the point. |
|
Follow-up SGTM. Right, the previous situation AFAIK was that it was only compiled if manually defined by the user. |
22bbd84 to
fd56ee1
Compare
|
Made the |
2a439ea to
b2f3bf4
Compare
Among these includes, src/net.{h,cpp} is relying on src/sync.h for <logging.h>
and in turn on src/logging.h for <list>. The compiler raises when they are
removed from src/sync.h in the last commit of this PR, so they need to be added.
which allows dropping `#include <logging>` in the header file.
b2f3bf4 to
e859ef4
Compare
|
Added developer notes documentation. |
|
Concept and code review ACK 2623fb4ff235b199e167695fe304a689b072c560 (reasoning for adding backport label is that it removes the |
Agree, really happy that this change avoids unnecessary risk while preserving the benefits of the recent improvements. |
2623fb4 to
f5257c4
Compare
|
Updated per |
f5257c4 to
523e7b3
Compare
523e7b3 to
7ea951d
Compare
fanquake
left a comment
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 think you could just drop the first two commits, and add 2 missing includes to the 3rd commit, i.e https://github.com/fanquake/bitcoin/tree/simplfied_24734. That would seem to achieve the same outcome with less code changes, and is simpler if this is meant to be backported.
shaavan
left a comment
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.
Changes since my last review:
- Added documentation for
DEBUG_LOCKCONTENTIONin developer notes. - Added missing include headers.
- Moved
StartExtraBlockRelayPeersfrom net.h to the net.cpp
I like the added developer documentation for its clear and concise writing. It explains the purpose of the DEBUG_LOCKCONTENTION macro and describes how to use it effectively.
However, I am not able to reason with the following added changes:
- Keeping all the included headers into a separate commit.
- Though it makes reviewing easier. I don’t feel it needs to be in a separate commit.
- Moving
StartExtraBlockRelayPeersfrom net.h to the net.cpp- Though it is mentioned in this comment to refer to the first commit message, I can still not completely understand the reasoning. Hence, for now, I am concept 0 on this particular change.
I took a look into #24770, which has all the changes I agree with from this PR, and hence I think we can focus on getting that merged first.
|
@shaavan thanks for having a look.
The missing headers are an unrelated issue, apart from needing to be fixed for the object of this pull. Missing headers are generally done in a separate commit, see https://github.com/bitcoin/bitcoin/pull/24740/commits for a recent example.
Moving the function definition into the implementation (cpp) allows dropping an include header. Doing so can speed up compilation for the many files that include net.h. It's not strictly needed for backport but is trivial to review. |
|
This should be closed or rebased on top of #24770 if that's what you're now intending to get merged... |
|
Yes, this is my preferred version and plan to update or close whichever ones aren't merged. |
shaavan
left a comment
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.
ACK 7ea951d
Missing headers are generally done in a separate commit.
Though I am not 100% convinced, I cannot think of any blocking points for this change. Hence I am Concept 0 on this and will allow fellow reviewers to decide the optimal way forward on this particular change.
Moving the function definition into the implementation (cpp) allows dropping an include header. Doing so can speed up compilation for the many files that include the net.h.
That is acceptable reasoning, and I find it to be logically sound. Hence, I agree with this change.
…TION preprocessor directive 4394733 Add DEBUG_LOCKCONTENTION documentation to the developer notes (Jon Atack) 39a34b6 Put lock logging behind DEBUG_LOCKCONTENTION preprocessor directive (Jon Atack) Pull request description: This is a more minimal, no-frills version of #24734 for backport. The other fixes and improvements in that pull can be done after. *Copy of the PR 24734 description:* PRs #22736, #22904 and #23223 changed lock contention logging from a `DEBUG_LOCKCONTENTION` compile-time preprocessor directive to a runtime `lock` log category and improved the logging output. This changed the locking from using `lock()` to `try_lock()`: - `void Mutex::UniqueLock::lock()` acquires the mutex and blocks until it gains access to it - `bool Mutex::UniqueLock::try_lock()` doesn't block but instead immediately returns whether it acquired the mutex; it may be used by `lock()` internally as part of the deadlock-avoidance algorithm In theory the cost of `try_lock` might be essentially the [same](https://www.erisian.com.au/bitcoin-core-dev/log-2022-03-31.html#l-697) relative to `lock`. The test-and-set logic of these calls is purported to be ~ constant time, optimised and light/quick if used carefully (i.e. no mutex convoying), compared to system calls, memory/cache coherency and fences, wait queues, and (particularly) lock contentions. See the discussion around bitcoin/bitcoin#22736 (comment) and after with respect to performance/cost aspects. However, there are reasonable concerns (see [here](bitcoin/bitcoin#22736 (comment)) and [here](https://www.erisian.com.au/bitcoin-core-dev/log-2022-03-31.html#l-620)) that `Base::try_lock()` may be potentially [costly](https://www.erisian.com.au/bitcoin-core-dev/log-2022-03-31.html#l-700) or [risky](bitcoin/bitcoin#22904 (comment)) compared to `Base::lock()` in this very frequently called code. One alternative to keep the run-time lock logging would be to gate the `try_lock` call behind the logging conditional, for example as proposed in bitcoin/bitcoin@ccd73de and ACKed [here](bitcoin/bitcoin#22736 (comment)). However, this would add the [cost](bitcoin/bitcoin#22736 (comment)) of `if (LogAcceptCategory(BCLog::LOCK))` to the hotspot, instead of replacing `lock` with `try_lock`, for the most frequent happy path (non-contention). It turns out we can keep the advantages of the runtime lock contention logging (the ability to turn it on/off at runtime) while out of prudence putting the `try_lock()` call and `lock` logging category behind a `DEBUG_LOCKCONTENTION` compile-time preprocessor directive, and also still retain the lock logging enhancements of the mentioned PRs, as suggested in bitcoin/bitcoin#24734 (comment) by W. J. van der Laan, in bitcoin/bitcoin#22736 (comment), and in the linked IRC discussion. Proposed here and for backport to v23. ACKs for top commit: laanwj: Code review ACK 4394733 Tree-SHA512: 89b1271cae1dca0eb251914b1a60fc5b68320aab4a3939c57eec3a33a3c8f01688f05d95dfc31f91d71a6ed80cfe2d67b77ff14742611cc206175e47b2e5d3b1
|
Closing as this has been merged |
PRs #22736, #22904 and #23223 changed lock contention logging from a
DEBUG_LOCKCONTENTIONcompile-time preprocessor directive to a runtimelocklog category and improved the logging output. This changed the locking from usinglock()totry_lock():void Mutex::UniqueLock::lock()acquires the mutex and blocks until it gains access to itbool Mutex::UniqueLock::try_lock()doesn't block but instead immediately returns whether it acquired the mutex; it may be used bylock()internally as part of the deadlock-avoidance algorithmIn theory the cost of
try_lockmight be essentially the same relative tolock. The test-and-set logic of these calls is purported to be ~ constant time, optimised and light/quick if used carefully (i.e. no mutex convoying), compared to system calls, memory/cache coherency and fences, wait queues, and (particularly) lock contentions. See the discussion around #22736 (comment) and after with respect to performance/cost aspects. However, there are reasonable concerns (see here and here) thatBase::try_lock()may be potentially costly or risky compared toBase::lock()in this very frequently called code.One alternative to keep the run-time lock logging would be to gate the
try_lockcall behind the logging conditional, for example as proposed in ccd73de and ACKed here. However, this would add the cost ofif (LogAcceptCategory(BCLog::LOCK))to the hotspot, instead of replacinglockwithtry_lock, for the most frequent happy path (non-contention).It turns out we can keep the advantages of the runtime lock contention logging (the ability to turn it on/off at runtime) while out of prudence putting the
try_lock()call andlocklogging category behind aDEBUG_LOCKCONTENTIONcompile-time preprocessor directive, and also still retain the lock logging enhancements of the mentioned PRs, as suggested in #24734 (comment) by W. J. van der Laan, in #22736 (comment), and in the linked IRC discussion.Proposed here and for backport to v23.