Skip to content
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

Mempool Update Cut-Through Optimization #21464

Merged

Conversation

JeremyRubin
Copy link
Contributor

Often when we're updating mempool entries we update entries that we ultimately end up removing the updated entries shortly thereafter. This patch makes it so that we filter for such entries a bit earlier in processing, which yields a mild improvement for these cases, and is negligible overhead otherwise.

There's potential for a better -- but more sophisticated -- algorithm that can be used taking advantage of epochs, but I figured it is better to do something that is simple and works first and upgrade it later as the other epoch mempool work proceeds as it makes the patches for the epoch algorithm simpler to understand, so you can consider this as preparatory work. It could either go in now if it is not controversial, or we could wait until the other patch is ready to go.

@jonatack
Copy link
Contributor

Interesting on first look, will review.

@JeremyRubin JeremyRubin force-pushed the epoch-mempool-cut-through-optimized branch from 5f98973 to a4aef7a Compare April 6, 2021 22:29
@JeremyRubin
Copy link
Contributor Author

pushed an update to simplify setRemove to hold txids instead of tx reference_wrappers, which eliminated the confusing ownership thing. should make review simpler.

@laanwj laanwj added this to Blockers in High-priority for review Apr 7, 2021
Copy link
Member

@instagibbs instagibbs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some comments, logic looks right from manual inspection of other limits code

will test

src/txmempool.cpp Outdated Show resolved Hide resolved
src/txmempool.cpp Outdated Show resolved Hide resolved
src/txmempool.cpp Outdated Show resolved Hide resolved
src/txmempool.cpp Outdated Show resolved Hide resolved
src/txmempool.cpp Outdated Show resolved Hide resolved
@JeremyRubin JeremyRubin force-pushed the epoch-mempool-cut-through-optimized branch 2 times, most recently from 2be4f77 to e8dafeb Compare April 12, 2021 02:00
@instagibbs
Copy link
Member

utACK e8dafeb

going to dive into tests next to upgrade to tACK

Copy link
Member

@glozow glozow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK e8dafeb Code looks correct to me. I'm mostly just suggesting some docs if you retouch.

I wonder if (in addition to this) it would be worth changing ATMP to take a bool check_for_children param where, if true, looks for descendants in mempool and includes them when applying ancestor/descendant limits. Technically, ATMP is currently not enforcing these rules properly for reorgs by assuming no children in the mempool. That way we can probably remove them in UpdateMempoolForReorg() before even calling UpdateTransactionsFromBlock().

src/txmempool.h Outdated Show resolved Hide resolved
src/txmempool.h Outdated Show resolved Hide resolved
src/txmempool.cpp Show resolved Hide resolved
@rebroad
Copy link
Contributor

rebroad commented Apr 16, 2021

@JeremyRubin could you explain what this does in more layman's terms please? Is this pull anything to do with helping to fill the mempool in a way that reduces filling it with TXs that will get deleted later (due to mempool becoming full)?

@instagibbs
Copy link
Member

This is an optimization for the case where a reorg puts an ancestor transaction(package) back into the mempool, thus temporarily busting the transaction chain limits of the mempool.

Copy link
Contributor

@jnewbery jnewbery left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. A few style comments inline, including a suggested change to minimize the diff in the CTxMemPool interface and in the calling code.

I think the two commits can be squashed.

src/txmempool.h Outdated Show resolved Hide resolved
src/txmempool.h Outdated Show resolved Hide resolved
src/txmempool.cpp Outdated Show resolved Hide resolved
src/txmempool.cpp Outdated Show resolved Hide resolved
src/txmempool.cpp Outdated Show resolved Hide resolved
src/txmempool.cpp Outdated Show resolved Hide resolved
src/txmempool.cpp Outdated Show resolved Hide resolved
@DrahtBot
Copy link
Contributor

DrahtBot commented May 3, 2021

🕵️ @hebasto @sipa have been requested to review this pull request as specified in the REVIEWERS file.

Copy link
Member

@ariard ariard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK

Looking to test this a bit more.

There's potential for a better -- but more sophisticated -- algorithm that can be used taking advantage of epochs, but I figured it is better to do something that is simple and works first and upgrade it later as the other epoch mempool work proceeds as it makes the patches for the epoch algorithm simpler to understand, so you can consider this as preparatory work. It could either go in now if it is not controversial, or we could wait until the other patch is ready to go.

I don't have an opinion on patch ordering but I would be glad if we can land the Epoch changes (#17628) at some point. Either as it is, or after a bit of txmempool internals cleaning/encapsulation :)

src/txmempool.cpp Outdated Show resolved Hide resolved
src/txmempool.cpp Outdated Show resolved Hide resolved
src/validation.cpp Outdated Show resolved Hide resolved
@DrahtBot
Copy link
Contributor

DrahtBot commented Jul 10, 2021

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #23962 (Use int32_t type for transaction size/weight consistently by hebasto)
  • #21436 (doc: Fix several references in txmempool comments by kiminuo)
  • #17786 (refactor: Nuke policy/fees->mempool circular dependencies by hebasto)

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.

@JeremyRubin JeremyRubin force-pushed the epoch-mempool-cut-through-optimized branch from 03d1cae to f0d8236 Compare July 10, 2021 19:35
@JeremyRubin
Copy link
Contributor Author

Addressed style/doc stuff in a separate commit to preserve ACKs (squashable)

I also introcuded a new removal reason in a separate commit, this should not be squashed as it is ortho to the main change.

@laanwj anything else you'd like to see here?

@jnewbery
Copy link
Contributor

Addressed style/doc stuff in a separate commit to preserve ACKs (squashable)

I don't understand this. The head commit is what needs ACKs, and that's changed now that there are new commits. I'm very happy to re-review once you've squashed commits and rebased on master.

@JeremyRubin JeremyRubin force-pushed the epoch-mempool-cut-through-optimized branch from f0d8236 to 2820b04 Compare July 15, 2021 22:59
@JeremyRubin
Copy link
Contributor Author

Ok, made changes requested by @jnewbery and squashed. Will open a followup PR with the validation interface after as requested by @ariard. Thanks.

Copy link
Member

@darosior darosior left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 2820b04

Copy link
Contributor

@jnewbery jnewbery left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be better to squash the test commit into the first commit, so the changes are atomic.

src/txmempool.h Show resolved Hide resolved
src/txmempool.h Outdated Show resolved Hide resolved
src/txmempool.h Outdated Show resolved Hide resolved
src/txmempool.cpp Show resolved Hide resolved
src/txmempool.h Outdated Show resolved Hide resolved
@JeremyRubin JeremyRubin force-pushed the epoch-mempool-cut-through-optimized branch from 2820b04 to 81efedb Compare September 12, 2021 18:50
@JeremyRubin
Copy link
Contributor Author

Addressed all feedback; keeping tests separate from changes for easier A/B comparison. However, I have reordered them so Tests come first which is more practical.

@Talkless
Copy link

Talkless commented Nov 6, 2021

Weak ACK 81efedb. Weak because of my limited mempool knowledge, though code looks OK, and I successfully ran unit and extended functional tests.

@mjdietzx
Copy link
Contributor

mjdietzx commented Nov 15, 2021

When I read the commit:

Often when we're updating mempool entries we update entries that we
ultimately end up removing the updated entries shortly thereafter. This
patch makes it so that we filter for such entries a bit earlier in
processing

based on the wording, I assumed that we were "filtering" these entries out before adding them to the mempool. However, after reviewing the PR it seems that these entries are still added to the mempool, state is still calculated/updated and cached, it's just that we are now (pre-emptively) removing descendants_to_remove right away at the end of UpdateTransactionsFromBlock

Is my understanding correct? If so, it makes me wonder where the performance improvement is coming from. To me it seems all the same work is done before/after this PR, just earlier.


Re: my review comment 9264766, mempool_updatefromblock.py (which I agree is a great benchmark test for this optimization) is running in the ~same time before/after this PR. So I am curious if we are actually seeing any speedup from this optimization

@laanwj
Copy link
Member

laanwj commented Dec 2, 2021

Code review ACK 81efedb
Thanks for clarifying doc comments to UpdateTransactionsFromBlock and UpdateForDescendants.

@laanwj
Copy link
Member

laanwj commented Dec 2, 2021

Looks like there has been a silent merge conflict though. Local compilation results in:

/…/bitcoin/src/validation.cpp:351:79: error: reference to type 'const std::string' (aka 'const basic_string<char>') could not bind to an lvalue of type 'const unsigned int'
    const uint64_t ancestor_count_limit = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
                                                                              ^~~~~~~~~~~~~~~~~~~~~~
/…/bitcoin/src/util/system.h:327:70: note: passing argument to parameter 'strDefault' here
    std::string GetArg(const std::string& strArg, const std::string& strDefault) const;
                                                                     ^
/…/bitcoin/src/validation.cpp:351:20: error: no viable conversion from 'std::string' (aka 'basic_string<char>') to 'const uint64_t' (aka 'const unsigned long')
    const uint64_t ancestor_count_limit = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
                   ^                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/basic_string.h:816:7: note: candidate function
      operator __sv_type() const noexcept
      ^
/…/bitcoin/src/validation.cpp:352:77: error: reference to type 'const std::string' (aka 'const basic_string<char>') could not bind to an lvalue of type 'const unsigned int'
    const uint64_t ancestor_size_limit = gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT) * 1000;
                                                                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~
/…/bitcoin/src/util/system.h:327:70: note: passing argument to parameter 'strDefault' here
    std::string GetArg(const std::string& strArg, const std::string& strDefault) const;
                                                                     ^
/…/bitcoin/src/validation.cpp:352:106: error: invalid operands to binary expression ('std::string' (aka 'basic_string<char>') and 'int')
    const uint64_t ancestor_size_limit = gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT) * 1000;
                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~
/usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/complex:391:5: note: candidate template ignored: could not match 'complex' against 'basic_string'
    operator*(const complex<_Tp>& __x, const complex<_Tp>& __y)
    ^
/usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/complex:400:5: note: candidate template ignored: could not match 'complex' against 'basic_string'
    operator*(const complex<_Tp>& __x, const _Tp& __y)
    ^
/usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/complex:409:5: note: candidate template ignored: could not match 'complex<type-parameter-0-0>' against 'int'
    operator*(const _Tp& __x, const complex<_Tp>& __y)
    ^

I think it's simply a matter of changing GetArg to GetIntArg for these.

@JeremyRubin JeremyRubin force-pushed the epoch-mempool-cut-through-optimized branch from 81efedb to a1b6371 Compare December 7, 2021 16:41
Often when we're updating mempool entries we update entries that we
ultimately end up removing the updated entries shortly thereafter. This
patch makes it so that we filter for such entries a bit earlier in
processing, which yields a mild improvement for these cases, and is
negligible overhead otherwise.
@JeremyRubin JeremyRubin force-pushed the epoch-mempool-cut-through-optimized branch from a1b6371 to c5b36b1 Compare December 9, 2021 07:08
@JeremyRubin
Copy link
Contributor Author

rebased, test failures are unrelated it looks like (this PR doesn't touch secp?)

@maflcko
Copy link
Member

maflcko commented Jan 3, 2022

reran ci (was unrelated failure)

@JeremyRubin
Copy link
Contributor Author

requesting re-acks from:

@instagibbs
@glozow
@ariard
@laanwj
@Talkless

@instagibbs
Copy link
Member

reACK c5b36b1

@sipa
Copy link
Member

sipa commented Jan 7, 2022

utACK c5b36b1

Copy link
Contributor

@mzumsande mzumsande left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review ACK c5b36b1
The change looks correct to me, the doc rework for the touched functions is an improvement.

@instagibbs
Copy link
Member

RFM?

@fanquake fanquake merged commit 0147278 into bitcoin:master Jan 25, 2022
@fanquake fanquake removed this from Blockers in High-priority for review Jan 25, 2022
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Jan 28, 2022
c5b36b1 Mempool Update Cut-Through Optimization (Jeremy Rubin)
c49daf9 [TESTS] Increase limitancestorcount in tournament RPC test to showcase improved algorithm (Jeremy Rubin)

Pull request description:

  Often when we're updating mempool entries we update entries that we ultimately end up removing the updated entries shortly thereafter. This patch makes it so that we filter for such entries a bit earlier in processing, which yields a mild improvement for these cases, and is negligible overhead otherwise.

  There's potential for a better -- but more sophisticated -- algorithm that can be used taking advantage of epochs, but I figured it is better to do something that is simple and works first and upgrade it later as the other epoch mempool work proceeds as it makes the patches for the epoch algorithm simpler to understand, so you can consider this as preparatory work. It could either go in now if it is not controversial, or we could wait until the other patch is ready to go.

ACKs for top commit:
  instagibbs:
    reACK c5b36b1
  sipa:
    utACK c5b36b1
  mzumsande:
    Code Review ACK c5b36b1

Tree-SHA512: 78b16864f77a637d8a68a65e23c019a9757d8b2243486728ef601d212ae482f6084cf8e69d810958c356f1803178046e4697207ba40d6d10529ca57de647fae6
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Nov 24, 2022
Summary:
Often when we're updating mempool entries we update entries that we
ultimately end up removing the updated entries shortly thereafter. This
patch makes it so that we filter for such entries a bit earlier in
processing, which yields a mild improvement for these cases, and is
negligible overhead otherwise.

Increase limitancestorcount in tournament RPC test to showcase improved algorithm

This is a backport of [[bitcoin/bitcoin#21464 | core#21464]]

Notes:
 - I did not see a significant gain for this functional test. If there is any improvement, it is less than the usual variability (+- 10 seconds for a test that takes 220 seconds).
 - the `policy/mempool.h` include is needed for `DEFAULT_ANCESTOR_LIMIT` and `DEFAULT_ANCESTOR_SIZE_LIMIT`

Test Plan: `ninja && ninja check check-functional-extended`

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Subscribers: Fabien

Differential Revision: https://reviews.bitcoinabc.org/D12589
@bitcoin bitcoin locked and limited conversation to collaborators Jan 25, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet