8000 refactor: Nuke policy/fees->mempool circular dependencies by hebasto · Pull Request #17786 · bitcoin/bitcoin · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

refactor: Nuke policy/fees->mempool circular dependencies #17786

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

Merged
merged 2 commits into from
Nov 19, 2022

Conversation

hebasto
Copy link
Member
@hebasto hebasto commented Dec 21, 2019

This PR:

@DrahtBot
Copy link
Contributor
DrahtBot commented Dec 21, 2019

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

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK ryanofsky, theStack, glozow
Concept ACK practicalswift, JeremyRubin, Empact
Stale ACK promag

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #26153 (Reduce wasted pseudorandom bytes in ChaCha20 + various improvements by sipa)
  • #25361 (BIP324: Cipher suite by dhruv)
  • #25325 (Add pool based memory resource by martinus)
  • #24545 (BIP324: Enable v2 P2P encrypted transport by dhruv)
  • #23962 (Use int32_t type for transaction size/weight consistently by hebasto)
  • #23561 (BIP324: Handshake prerequisites by dhruv)
  • #23233 (BIP324: Add encrypted p2p transport {de}serializer by dhruv)

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.

@promag
Copy link
Contributor
promag commented Dec 21, 2019

Concept ACK.

Copy link
Contributor
@promag promag left a comment

Choose a reason for hiding this comment

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

ACK fbf6b75.

I'd squash 1st and 2nd commits. 3rd commit is unrelated but is a nice cleanup.

@practicalswift
Copy link
Contributor

Concept ACK: thanks for nuking circular dependencies

@hebasto hebasto force-pushed the 20191221-mempool-circ-dep branch from fbf6b75 to 045794b Compare December 22, 2019 12:46
@hebasto
Copy link
Member Author
hebasto commented Dec 22, 2019

@promag

I'd squash 1st and 2nd commits. 3rd commit is unrelated but is a nice cleanup.

Done.

@hebasto
Copy link
Member Author
hebasto commented Dec 22, 2019

I stumble on UB sanitizer. How could a move-only change cause an error?

Is this a side effect of circular dependencies resolving? nm

@hebasto hebasto force-pushed the 20191221-mempool-circ-dep branch 2 times, most recently from f2cb595 to 1e540cd Compare December 22, 2019 14:03
@hebasto
Copy link
Member Author
hebasto commented Dec 22, 2019

Travis is happy now ;)

@JeremyRubin
Copy link
Contributor

Generally agree with this change, I've thought about doing it myself a few times myself. It also seems to be a good alternative to the observer pattern mentioned as we change far fewer things to get the same circular dependency break. So a slight code review ACK that this seems correct.

Slightly short of concept ack for a few reasons:

  1. Needs a simple benchmark to show that we haven't made functions calling the CTxMemPoolEntry's non-header functions slower because they are no longer within the same compilation unit
  2. Some other changes I've been working on lately w.r.t. epoch mempool introduce some new classes & move code between the CTxMemPool and CTxMemPoolEntry classes; while those can be rebased, it's not clear where some of the shared code should live (perhaps in a third additional header, or a new circular dependency). We already have some things which are inherent circular dependencies (that won't get picked up by the linter, maps of MemPoolChildren/MemPoolParents) that will deliver a big performance win to get rid of (I think it will at least), so I'd rather kill those circular dependencies first so that it doesn't become harder to do later -- I'm happy to open up a PR for that once the first step of my Epoch Mempool #17268 Project, Improve UpdateTransactionsFromBlock with Epochs #17925, goes through.

@hebasto
Copy link
Member Author
hebasto commented Jan 22, 2020

@JeremyRubin

... to show that we haven't made functions calling the CTxMemPoolEntry's non-header functions slower because they are no longer within the same compilation unit

How is it possible?

@JeremyRubin
Copy link
Contributor

It's annoying, but because these functions were previously in the same translation unit then it's possible they can get completely inlined, but now they're in separate units they will definitely trigger function calls.

Because these updater functions get called in hot loops you have possibly replaced something optimized previously with something slow.

This matters a bit because we may expect these loops/regions to get even hotter if we increase mempool limits.

One way of addressing this would be to make CTxMemPoolEntry header only...

@hebasto
Copy link
Member Author
hebasto commented Jan 24, 2020

@JeremyRubin

It's annoying, but because these functions were previously in the same translation unit then it's possible they can get completely inlined, but now they're in separate units they will definitely trigger function calls.

IIUC, making function inline depends on compiler and its optimization settings. The bitcoind compiled with GCC 7.4.0 was checked with nm tool, and CTxMemPoolEntry member function symbols are present, therefore those functions are not inlined (except those which are defined in class declaration, as expected).

It seems runtime performance issues and circular dependency resolving are orthogonal. And "yes", we could

... make CTxMemPoolEntry header only...

@JeremyRubin
Copy link
Contributor

Correct; this is compiler dependent behavior. But we happen to compile with optimizations enabled for release builds -- not sure if we do different flags for non release builds (I think it's the same?).

Presence of the symbols doesn't prove that they aren't also inlined. An inline function is a hint to inline, not a mandate, and the function can be either called or or inlined depending on context, you would need to check the actual call sites.

I agree it's not a large issue; but specifically code organization does affect emitted code (this is what LTO is intended, in a sense, to get around, but I don't think we do that other than experimentally)

@hebasto
Copy link
Member Author
hebasto commented Jan 24, 2020

Presence of the symbols doesn't prove that they aren't also inlined. An inline function is a hint to inline, not a mandate, and the function can be either called or or inlined depending on context, you would need to check the actual call sites.

I mean if a function is inlined in all call sites, there is no dedicated assembly code and no symbol. Could a compiler inline a function in some call sites and make a standard function call of the same function in other call sites?

@gmaxwell
Copy link
Contributor

Unless the symbol isn't exported there will be a separate copy of it included in the object for external callers. That extra copy will persist in the final binary so long as there are any non-inlined callers.

For a quick check, just look at the size of all functions in dump of the binary. If they're all the same size then it's very likely that all you did was move things around.

@sipa
Copy link
Member
sipa commented Jan 24, 2020

In C++, inline is more than a hint, and actually has a meaning: it's a function that may be defined (and exported from) multiple translation units without conflicting with itself (it's only well defined if all definitions are identical, though). This is what allows having code in .h files. In practice it means the linker will merge all the definitions into one symbol.

@JeremyRubin
Copy link
Contributor

I think what @gmaxwell says is correct with my question.

@sipa that sounds correct. These weren't previously marked inline either, so I guess what I meant to capture is that not marking inline is a hint not to inline but not a mandate to not inline. E.g., if some function F is called by G, F may or may not be inlined depending on the compiler if they are in the same translation unit, but certainly won't be if F is in a different translation unit, is non inline, and LTO is not enabled.

@JeremyRubin
Copy link
Contributor

I think if you were to just put all the mempool entry functions into the header I wouldn't have any concerns. It doesn't seem to me like there's a really strong reason for them to be separate, and any time you change the initializers you've likely also changed the class definition so it doesn't seem like it would trigger recompilation explosions.

It also (maybe I'm wrong here) looks like you have some unneeded dependencies in the cpp (e.g., memusage), so that can be pruned out to keep the header small.

@hebasto hebasto force-pushed the 20191221-mempool-circ-dep branch from 1e540cd to 13a4a68 Compare January 29, 2020 19:43
@hebasto
Copy link
Member Author
hebasto commented Jan 29, 2020

@JeremyRubin Thank you for your review.

I think if you were to just put all the mempool entry functions into the header I wouldn't have any concerns.

Done.

It also (maybe I'm wrong here) looks like you have some unneeded dependencies in the cpp (e.g., memusage), so that can be pruned out to keep the header small.

All #includes are checked again. They all are needed, e.g., core_memusage.h is needed for RecursiveDynamicUsage.

@hebasto hebasto force-pushed the 20191221-mempool-circ-dep branch from 13a4a68 to ac83af8 Compare January 30, 2020 16:51
@hebasto
Copy link
Member Author
hebasto commented Jan 30, 2020

Rebased after #17261 has been merged.

@maflcko
Copy link
Member
maflcko commented Jan 30, 2020

Looking at the (currently) 9 conflicts, maybe it makes sense to postpone this changeset until after some of the other user-facing/features got merged to the mempool code?

@hebasto
Copy link
Member Author
hebasto commented Oct 14, 2022

Rebased 11d885b -> f140f94 (pr17786.22 -> pr17786.23) due to the conflict with #25667.

Copy link
Contributor
@ryanofsky ryanofsky 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 f140f94. This seems like an improvement over status quo to remove a circular dependency and improve code organization.

I agree with Gloria in #17786 (comment) other improvements could also be made which remove the circular dependency, but they seem complimentary and could build on this.

I think all the other discussion about code inlining and runtime performance and build performance makes sense, but I don't think those issues are a lot more pertinent to this PR than a lot of other PRs. So it just seems unlucky for this PR that they were brought up here. It would be good if we could think of a standard approach to avoiding performance regressions that could apply more fairly.

One other suggestion to make the PR more reviewable might be to split it into two commits: a move-only commit that just moved the CTxMemPoolEntry class definition without changing it, followed by a commit inlining its various methods. (This PR has been open a while and I probably would have reviewed it earlier if the bigger moveonly change didn't include other changes and was easier to verify.)

@hebasto hebasto force-pushed the 20191221-mempool-circ-dep branch from f140f94 to fed9e8e Compare November 16, 2022 20:11
@hebasto
Copy link
Member Author
hebasto commented Nov 16, 2022

@ryanofsky

Thank you for your review!

One other suggestion to make the PR more reviewable might be to split it into two commits: a move-only commit that just moved the CTxMemPoolEntry class definition without changing it, followed by a commit inlining its various methods.

Done.

This change nukes the policy/fees->mempool circular dependency.

Easy to review using `diff --color-moved=dimmed-zebra`.
@hebasto hebasto force-pushed the 20191221-mempool-circ-dep branch from fed9e8e to c8dc0e3 Compare November 16, 2022 20:17
Copy link
Contributor
@ryanofsky ryanofsky 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 c8dc0e3. Just include and whitespace changes since last review, and there's a moveonly commit now so it's very easy to review

Copy link
Contributor
@theStack theStack 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 c8dc0e3

Nice to see another circular dependency gone 💯

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.

utACK c8dc0e3, agree these changes are an improvement.

@glozow glozow merged commit d0b1f61 into bitcoin:master Nov 19, 2022
@hebasto hebasto deleted the 20191221-mempool-circ-dep branch November 19, 2022 15:50
@JeremyRubin
Copy link
Contributor

the reason it was brought up historically is that circa 2019/early 2020 I thought we might be able to increase mempool limits, and these functions end up being relatively hot, especially with larger workloads, so it made sense to be careful with them.

@jamesob would probably be the guy to ask about tracking perf regressions....

sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Nov 20, 2022
@@ -261,6 +261,7 @@ BITCOIN_CORE_H = \
torcontrol.h \
txdb.h \
txmempool.h \
txmempool_entry.h \
Copy link
Member

Choose a reason for hiding this comment

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

If this is moved, why not move it to the right place, that is to kernel/txmempool_entry.h?

Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -62,6 +63,7 @@ implicit-integer-sign-change:script/bitcoinconsensus.cpp
implicit-integer-sign-change:script/interpreter.cpp
implicit-integer-sign-change:serialize.h
implicit-integer-sign-change:txmempool.cpp
implicit-integer-sign-change:txmempool_entry.h
Copy link
Member

Choose a reason for hiding this comment

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

Are they still needed?

Copy link
Member Author
@hebasto hebasto Nov 21, 2022

Choose a reason for hiding this comment

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

Apparently, they do not. Removed in needless #26542 #26545.

Thank you!

maflcko pushed a commit to bitcoin-core/gui that referenced this pull request Dec 6, 2022
…kernel/mempool_entry.h`

38941a7 refactor: Move `txmempool_entry.h` --> `kernel/mempool_entry.h` (Hennadii Stepanov)

Pull request description:

  This PR addresses the bitcoin/bitcoin#17786 (comment):
  > why not move it to the right place, that is to `kernel/txmempool_entry.h`?

ACKs for top commit:
  MarcoFalke:
    review ACK 38941a7 📊

Tree-SHA512: 0145974b63b67ca1d9d89af2dd9d4438beca480c16a563f330da05fec49b8394d7ba20ed83cf7d50b2e19454e006978ebed42b0e07887b98d00210f3201ce9ba
@bitcoin bitcoin locked and limited conversation to collaborators Nov 30, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

0