-
Notifications
You must be signed in to change notification settings - Fork 36.6k
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
Dedup and RAII-fy the creation of a copy of CConnman::vNodes #21943
Conversation
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. |
Concept ACK |
6447261
to
92f62d9
Compare
|
Concept ACK |
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.
concept ACK, some thoughts & questions as I familiarize myself with the code
92f62d9
to
00a8c94
Compare
|
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.
Code review ACK 00a8c94.
00a8c94
to
072896b
Compare
|
Concept ACK, particularly if this can reduce It looks like the CI stalled out on the last push. In any case, it rebases cleanly onto current master, the debug build is clean, and the unit/functional test suite is green for me locally. Reviewing. |
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.
Tested ACK 072896b rebased to current master. Reviewed, debug built, and ran unit tests on each commit. Ran a node with this branch rebased to master on mainnet for a day (edit: 3 days) with -debug=lock and 30-40 peers and seeing an impressive reduction in the frequent vNodes lock contentions with grep "lock contention cs_vNodes" ~/.bitcoin/debug.log
and very few contentions with grep "connman.cs_vNodes" ~/.bitcoin/debug.log
Nice work!
concept ACK |
072896b
to
a4fbf1b
Compare
Invalidates ACK from @jonatack. |
Diff-review ACK a4fbf1b per |
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.
Code review ACK a4fbf1b.
a4fbf1b
to
40e0bc8
Compare
40e0bc8
to
99c1af5
Compare
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.
re-ACK 99c1af5 per git range-diff 927586 40e0bc8 99c1af5
following my earlier full review #21943 (review), only change is rebase
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.
Near ACK with one suggestion for clarifying the logic sequence.
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.
Perhaps this is outside the scope of the PR, but I'd like:
void Release()
{
+ assert(nRefCount > 0);
nRefCount--;
}
99c1af5
to
8589c55
Compare
Accepting new connections does not require the snapshot of the existing connected nodes, so make this explicit by accepting new connections after the snapshot has been destroyed, at the end of Invalidates ACK from @jonatack Previously invalidated ACK from @promag |
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.
Code review ACK 8589c55.
8589c55
to
db0a01e
Compare
Invalidates ACK from @promag Previously invalidated ACK from @jonatack |
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.
Code review ACK db0a01e, moved the early return to a loop where it makes more sense.
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.
Following up on my feedback #21943 (comment), as of db0a01e the commits are now out of order. The last commit
style: remove unnecessary braces
They were needed to define the scope of `LOCK(cs_vNodes)` which was
removed in the previous commit.
should be after the second commit net: keep reference to each node during socket wait
(or squashed).
Almost-ACK db0a01e with some suggestions below if you retouch.
if (interruptNet) return; | ||
std::set<SOCKET> recv_set; | ||
std::set<SOCKET> send_set; | ||
std::set<SOCKET> error_set; |
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.
4097d14 unneeded style change, would leave as-is (and as currently exists in both of the SocketEvents()
functions)
- std::set<SOCKET> recv_set;
- std::set<SOCKET> send_set;
- std::set<SOCKET> error_set;
-
+ std::set<SOCKET> recv_set, send_set, error_set;
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 it is good to always declare one variable per line.
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.
Consider:
struct SocketSets {
std::set<SOCKET> recv;
std::set<SOCKET> send;
std::set<SOCKET> error;
}
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.
@LarryRuane, something like this is coming as a subsequent change from #21878 (see commit net: introduce Sock::WaitMany()
and the structures WaitEvents
and WaitData
introduced in that commit).
The current combination of sets stores the sockets in "one pile of sockets that are ready for read" and "one pile of sockets that are ready for write" (notice that a given socket may be in both). It is more convenient to have just one pile of sockets each one with attached ready-for-read and ready-for-write flags.
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 like the idea of abstracting this but it seems out of scope of this PR.
It is more convenient to have just one pile of sockets each one with attached ready-for-read and ready-for-write flags.
Eventually it depends on the selection mechanism used isn't it? When it's abstracted, might as well store it in a format ready to feed to say, poll()
or select()
whatever is used.
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.
Yes, those 3 sets are dragged around as parameters to functions and as local variables. It is an obvious improvement to pack them together somehow. Not the purpose of this PR. Once this is PR is merged I will chop off another piece from #21878 into a smaller/manageable PR that will contain the commit which introduces such a packing net: introduce Sock::WaitMany()
. We can discuss it there, I don't have a strong opinion on how they are packed exactly. Or if this PR is stuck we can move the discussion to #21878 where WaitData
is introduced.
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.
Once this is PR is merged I will chop off another piece from #21878 into a smaller/manageable PR that will contain the commit which introduces such a packing
net: introduce Sock::WaitMany()
There are too many conflicts if I try to cherry-pick the WaitMany()
stuff on top of bare master
- it touches the same areas of code as the preceding commits from #21878. I chopped off those preceding commits in separate PRs instead: #23601 and #23604.
WaitMany | net: use Sock::WaitMany() instead of CConnman::SocketEvents()
stuff | net: introduce Sock::WaitMany()
| net: also wait for exceptional events in Sock::Wait()
#23601 | net: don't check if the listening socket is valid
| scripted-diff: rename CNode::cs_hSocket to CNode::m_sock_mutex
#23604 | net: use Sock in CNode
| fuzz: move FuzzedSock earlier in src/test/fuzz/util.h
| net: change CreateNodeFromAcceptedSocket() to take Sock
#21879 | net: use Sock in CConnman::ListenSocket
| net: add new method Sock::Accept() that wraps accept()
The following pattern was duplicated in CConnman: ```cpp lock create a copy of vNodes, add a reference to each one unlock ... use the copy ... lock release each node from the copy unlock ``` Put that code in a RAII helper that reduces it to: ```cpp create snapshot "snap" ... use the copy ... // release happens when "snap" goes out of scope ```
Create the snapshot of `CConnman::vNodes` to operate on earlier in `CConnman::SocketHandler()`, before calling `CConnman::SocketEvents()` and pass the `vNodes` copy from the snapshot to `SocketEvents()`. This will keep the refcount of each node incremented during `SocketEvents()` so that the `CNode` object is not destroyed before `SocketEvents()` has finished. Currently in `SocketEvents()` we only remember file descriptor numbers (when not holding `CConnman::cs_vNodes`) which is safe, but we will change this to remember pointers to `CNode::m_sock`.
They were needed to define the scope of `LOCK(cs_vNodes)` which was removed in the previous commit. Re-indent in a separate commit to ease review (use `--ignore-space-change`).
`CConnman::SocketHandler()` does 3 things: 1. Check sockets for readiness 2. Process ready listening sockets 3. Process ready connected sockets Split the processing (2. and 3.) into separate methods to make the code easier to grasp. Also, move the processing of listening sockets after the processing of connected sockets to make it obvious that there is no dependency and also explicitly release the snapshot before dealing with listening sockets - it is only necessary for the connected sockets part.
db0a01e
to
f52b6b2
Compare
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.
code review ACK f52b6b2
comments are optional
if (interruptNet) return; | ||
std::set<SOCKET> recv_set; | ||
std::set<SOCKET> send_set; | ||
std::set<SOCKET> error_set; |
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.
Consider:
struct SocketSets {
std::set<SOCKET> recv;
std::set<SOCKET> send;
std::set<SOCKET> error;
}
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.
Code review ACK f52b6b2, only format changes and comment tweaks since last review.
ACK f52b6b2 changes since last review are reordered commits, removing an unneeded local variable, and code formatting and documentation improvements |
… of CConnman::vNodes f52b6b2 net: split CConnman::SocketHandler() (Vasil Dimov) c7eb19e style: remove unnecessary braces (Vasil Dimov) 664ac22 net: keep reference to each node during socket wait (Vasil Dimov) 75e8bf5 net: dedup and RAII-fy the creation of a copy of CConnman::vNodes (Vasil Dimov) Pull request description: _This is a piece of bitcoin/bitcoin#21878, chopped off to ease review._ The following pattern was duplicated in CConnman: ```cpp lock create a copy of vNodes, add a reference to each one unlock ... use the copy ... lock release each node from the copy unlock ``` Put that code in a RAII helper that reduces it to: ```cpp create snapshot "snap" ... use the copy ... // release happens when "snap" goes out of scope ACKs for top commit: jonatack: ACK f52b6b2 changes since last review are reordered commits, removing an unneeded local variable, and code formatting and documentation improvements LarryRuane: code review ACK f52b6b2 promag: Code review ACK f52b6b2, only format changes and comment tweaks since last review. Tree-SHA512: 5ead7b4c641ebe5b215e7baeb7bc0cdab2a588b2871d9a343a1d518535c55c0353d4e46de663f41513cdcc79262938ccea3232f6d5166570fc2230286c985f68
Looks like github didn't detect the merge, closing. |
This is a piece of #21878, chopped off to ease review.
The following pattern was duplicated in CConnman:
Put that code in a RAII helper that reduces it to: