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
refactor: Replace sets of txiter with CTxMemPoolEntryRefs #28886
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code CoverageFor detailed information about the code coverage, see the test coverage report. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. 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. |
EXCLUSIVE_LOCKS_REQUIRED(m_mempool->cs, ::cs_main) { | ||
AssertLockHeld(m_mempool->cs); | ||
AssertLockHeld(::cs_main); | ||
const CTransaction& tx = it->GetTx(); | ||
const CTransaction& tx = entry.GetTx(); |
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.
thanks! really think entry is much better.
fee19f9
to
14023c2
Compare
14023c2
to
b37ec7f
Compare
|
b37ec7f
to
7248c0a
Compare
@@ -468,10 +465,10 @@ void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAnces | |||
// to clean up the mess we're leaving here. | |||
|
|||
// Update ancestors with information about this tx | |||
for (const auto& pit : GetIterSet(setParentTransactions)) { | |||
UpdateParent(newit, pit, true); | |||
for (const CTxMemPoolEntry& pentry : GetEntrySet(setParentTransactions)) { |
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.
for (const CTxMemPoolEntry& pentry : GetEntrySet(setParentTransactions)) { | |
for (const CTxMemPoolEntry& entry : GetEntrySet(setParentTransactions)) { |
nit: Not a pointer?
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.
The p
is for parent
? Just like before in pit
?
I wonder if it is possible to avoid copies of the entry. Currently one one copy is created when inserting into mapTx. However, now that things are moving toward references, which are easy to copy accidentally. It may lead to bugs such as the one mentioned in the boost docs:
So disallowing copies would be a good belt-and-suspenders? |
Thanks for highlighting this.
I did a quick POC where |
There shouldn't be any conflicts, so maybe a separate/independent/parallel pull? |
Concept ACK on avoiding exposing iterators externally. Exposing references instead seems like a bit of a lateral move though, and I think it's going to take a good bit of convincing to prove that this is at least as safe than what we have now. Are references guaranteed by Boost to stay valid the same as iters are? |
We're using the references now to keep track of the parents and children. I don't see what new assumption this patch is introducing compared to this existing practice.
I'd be interested in getting an answer to this though. I'm guessing, since we can pass objects without copy or move ctors to the multiindex map, they can't be moved in memory, so the references should be safe, right? |
7248c0a
to
fe8c85e
Compare
Rebased 7248c0a -> fe8c85e (setEntryRefs_0 -> setEntryRefs_1, compare)
|
Though #28676 is still in draft (and likely will remain that way for a while), my plan is to completely rewrite most of the mempool logic. To minimize rebase effort, I wonder if it would be reasonable to defer mempool refactors for the time being, and just try to ensure that these goals are reflected in that work when it becomes ready for full review? |
I was thinking about this issue of ownership and safety semantics some more -- it seems like that most of the issues around iterators exist with CTxMemPoolEntryRefs as well, which is that they are only valid to hold onto as long as the mempool is locked. Once the lock is released, it's no longer safe to use mapTx iterators or CTxMemPoolEntryRef's, because they can be deleted out from under you. So if we really want to address ownership and safety semantics, I think we need to do something a bit different? (Unfortunately I don't have any great suggestions.) |
54f0dc5
to
c34dcea
Compare
Rebased 54f0dc5 -> c34dcea (setEntryRefs_3 -> setEntryRefs_4, compare)
|
Currently the mempool returns and consumes sets of multiindex iterators in its public API. A likely motivation for this over working with references to the actual values is that the multi index interface works with these iterators and not with pointers or references to the actual values. However, the iterator type provides little benefit in practice as applied currently. Its purpose, ownership, and safety semantics often remain ambiguous, and it is hardly used for actually iterating through the data structures. So replace it where possible with CTxMemPoolEntryRefs. Since CTxMemPoolEntry itself refers to its Parents and Children by CTxMemPoolEntryRef and not txiter, this allowed for an overall reduction of calls to iterator_to. This also makes the long term goal of eliminating boost types from the headers more feasible.
c34dcea
to
7882748
Compare
Rebased c34dcea -> 7882748 (setEntryRefs_4 -> setEntryRefs_5, compare)
|
Going to close this while work on cluster mempool is happening. Hopefully a solution for leaking the boost types can be found there. Will keep the parent #28335 open. |
Currently the mempool returns and consumes sets of multiindex iterators in its public API. A likely motivation for this over working with references to the actual values is that the multi index interface works with these iterators and not with pointers or references to the actual values.
However, using the iterator type in the
setEntries
set provides little benefit in practice as applied currently. Its purpose, ownership, and safety semantics often remain ambiguous, and it is hardly used for actually iterating through the data structures. So replace it where possible withCTxMemPoolEntryRef
s.Since
CTxMemPoolEntry
itself refers to its Parents and Children byCTxMemPoolEntryRef
and nottxiter
, this allowed for an overall reduction of calls toiterator_to
. See the docs oniterator_to
for more guidance.No change in the performance of the mempool code was observed in my benchmarks.
This also makes the goal of eliminating boost types from the headers as done in #28335 more feasible.