Skip to content

Conversation

@willcl-ark
Copy link
Member

@willcl-ark willcl-ark commented Nov 8, 2022

Fixes #9526

When -blocksonly has been set reduce default mempool size to avoid surprising resource usage via sharing un-used mempool cache space with dbcache.

In comparison to #9569 which either set maxmempool size to 0 when -blocksonly was set or else errored on startup, this change will permit maxmempool options being set.

This preserves the current (surprising?) behaviour of having a functional mempool in -blocksonly mode, to permit whitelisted peer transaction relay, whilst reducing average runtime memory usage for blocksonly nodes which either use the default settings or have otherwise configured a maxmempool size.

To use the previous old defaults node operators can configure their node with: -blocksonly -maxmempool=300.

Copy link
Contributor

@stickies-v stickies-v left a comment

Choose a reason for hiding this comment

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

It took me a surprisingly long time to figure out the rationale here. I'll write down my understanding both to have it validated/corrected, as well as hopefully to inform other people looking at this.


My understanding:

Users running with -blocksonly expect to have a near zero-sized mempool, because it'll only contain transactions broadcasted by their own wallet (disabled by default) or transactions received from whitelisted peers (non-default). As such, when provisioning their system, a user would expect to only have to allocate dbcache amount of memory, instead of currently actually requiring dbcache + maxmempool, which could lead to stability issues.

Without -blocksonly, a user needs to ensure that his system is provisioned to support both the full dbcache and mempool. Since it's provisioned anyway, we might as well use the unused mempool space for dbcache, which is especially helpful during IBD.

The misunderstanding for me was that the resource sharing between dbcache and maxmempool is not a resource optimization (in which case "we would benefit even more with -blocksonly, so why disable the optimization?!") but rather an accounting trick. Users running in -blocksonly should just increase their dbcache by whatever size maxmempool is for a similar effect (but not entirely, as explained below)


If my understanding is correct, I'm Concept ACK (i.e. making resource usage less surprising) but not yet Approach ACK, because:

  • this would be a performance degradation for users running -blocksonly that don't realize they should update their -dbcache. Users running -blocksonly could get higher default dbcache defaults, but that seems messy too.
  • users can't really replicate current behaviour even if they're aware of the change. The intuitive solution would be to increase -dbcache by -maxmempool, however, dbcache is shared by multiple caches, of which the coins cache receives 25-50%. It seems there's no way to allocate an extra 300MB (assuming default) to just the coins cache without increasing the dbcache by a total of 600MB - 1.2GB?

@willcl-ark
Copy link
Member Author

Thanks for your review at this conceptual stage @stickies-v. Your understanding of the problem and solution matches my own, although I had not fully considered the knock-on effect that:

users can't really replicate current behaviour even if they're aware of the change ... without increasing the dbcache by a total of 600MB - 1.2GB?

I also concur with you that altering default dbcache size for users who enable blocksonly seems kind of messy, although it could be made to work.

Therefore I see x options available from here:

  1. Keep current behaviour, document it better, and close -blocksonly should disable sharing of mempool with dbcache #9526 as wontfix
  2. Implement (something like) this change which introduces the performance reduction in IBD for blocksonly nodes and document it
  3. Add special-casing for dbcache size when nodes are run in blocksonly mode.

In writing the options out like that, my first preference might actually be 1), followed by 3) and last 2).

@stickies-v
Copy link
Contributor

Therefore I see x options available from here:

I think I'm not in favour of 1 & 3. Imo the direction should always be to reduce exceptional behaviour, if the short-term cost of that change is not exorbitant. I think in this case, the cost (potentially slower IBD which can be fixed with user config) is not exorbitant and increased stability (because of reduction of unexpected behaviour) is a worthwhile improvement.

I can think of two other alternatives, both building on top of what you've currently implemented:

  1. add a -increase-coins-cache=<n> parameter to allow users keeping the current behaviour (and maybe even set it to 300 by default if -blocksonly in the first release to give users time to transition, and then change it to 0 in the release after. Pretty user-friendly/straightforward option, but it introduces another kinda one-off parameter.

  2. Allowing users to manually define sub-cache allocations (overriding the defaults), e.g. through -dbcache.coins=<n|f> where n is an absolute amount and f a 0-1 float indicating a percentage of total dbcache. This seems like the most transparent and generic solution, but probably at the cost of reduced user-friendliness. It would also be a significantly bigger code change introducing the new parameters as well as a bunch of validation, and allowing the auto-allocation to deal with partial specification (e.g. only coins and tx_index are specified but not the other ones)

@willcl-ark
Copy link
Member Author

Yes 4) is a possible solution.

IMO by the time we hit 5), we're probably almost talking about people who have such an understanding of the system (developers) that they can most likely make the change to the source themselves before compiling if they truely need such fine-grained settings changes.

Will leave it as is to see if we get any other suggestions, and mull it over myself...

@luke-jr
Copy link
Member

luke-jr commented Nov 14, 2022

The intuitive solution would be to increase -dbcache by -maxmempool, however, dbcache is shared by multiple caches, of which the coins cache receives 25-50%. It seems there's no way to allocate an extra 300MB (assuming default) to just the coins cache without increasing the dbcache by a total of 600MB - 1.2GB?

FWIW, I have a related thought process for Knots, where it makes sense to leave the coins cache unlimited (and let memory pressure trigger flushing), yet it isn't sane to just increase -dbcache to the system memory size, because that would also increase other cache sizes which aren't handled when under memory pressure.

Therefore I see x options available from here:

  1. support specifying "+mempool" on the end of the -dbcache option to get the current behaviour even in blocksonly mode.

@glozow
Copy link
Member

glozow commented Jan 12, 2023

It seems the key issue is "surprising memory usage," i.e. -dbcache=n -blocksonly can use n+300 while the user may have expected n. The trick of using -blocksonly to add mempool's memory to the coins cache seems quite esoteric (lmk if I'm mistaken), so preserving it would be a bit less important imo.

the current (surprising) behaviour of having a functional mempool in -blocksonly mode

Given how surprising this is to so many people (including those affected by this problem), I can see how disabling mempool in blocksonly would be the easiest option. But can also see how it's not acceptable for users that rely on the current whitelist relay behavior according to #9569.

  1. Perhaps setting a very small mempool m_max_size_bytes when in blocksonly mode unless overridden by -maxmempool, would be one solution? That seems to preserve the trick for those using it intentionally, while reducing the amount of "surprising memory usage" for those that assume 0 memory for -blocksonly. Those who benefit from the extra 300MB by accident can perhaps get their answer from the release notes if they see a performance reduction. If they want to continue doing what they were doing, they just need to set -maxmempool.

@DrahtBot
Copy link
Contributor

DrahtBot commented Jan 12, 2023

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 ajtowns
Stale ACK aureleoules
Ignored review stickies-v

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

@willcl-ark
Copy link
Member Author

willcl-ark commented Jan 13, 2023

  1. Perhaps setting a very small mempool m_max_size_bytes when in blocksonly mode unless overridden by -maxmempool, would be one solution? That seems to preserve the trick for those using it intentionally, while reducing the amount of "surprising memory usage" for those that assume 0 memory for -blocksonly. Those who benefit from the extra 300MB by accident can perhaps get their answer from the release notes if they see a performance reduction. If they want to continue doing what they were doing, they just need to set -maxmempool.

I think this is a neat solution which covers all requirements so implemented it in this second branch (it's also much cleaner implementation-wise).

The only question I had was how small is "smaller"? I opted for 5MB in blocksonly mode as this should be enough for quite a few transactions to be relayed for whitelisted peers, I think...

If this is preferred I will move it over to this branch...?

@glozow
Copy link
Member

glozow commented Jan 16, 2023

The only question I had was how small is "smaller"? I opted for 5MB in blocksonly mode as this should be enough for quite a few transactions to be relayed for whitelisted peers, I think...

That definitely seems sufficient, and they can still make it higher if they need to. 5MB is the minimum -maxmempool config allowed as well, as the smaller the mempool size, the easier it is for your mempool min feerate to get driven up really high. Thinking out loud I guess this isn't as much of a concern for -blocksonly since you won't consider any transactions from strangers, so maybe smaller would be okay... but I can't say a different number with confidence.

If this is preferred I will move it over to this branch...?

I think it's a relatively simple change to lessen this problem with minimal side effects? 🤷 though I don't know if we could say we've completely fixed it. fwiw I think it's sensible regardless since we're probably unlikely to need 300MB in blocksonly mode.

@willcl-ark willcl-ark force-pushed the blocksonly_mempool_cache branch 2 times, most recently from ab64a8a to dd43259 Compare January 16, 2023 21:32
@willcl-ark willcl-ark changed the title Don't share mempool with dbcache in -blocksonly mode Reduce default mempool size in -blocksonly mode Jan 17, 2023
@willcl-ark willcl-ark marked this pull request as ready for review January 17, 2023 09:09
@willcl-ark
Copy link
Member Author

OK I have moved the commits across, and updated the PR title and description. I also added a new release note commit which I thought was worth it, but happy to be persuaded otherwise.

@willcl-ark willcl-ark force-pushed the blocksonly_mempool_cache branch from dd43259 to 931924f Compare January 17, 2023 10:51
Copy link
Contributor

@aureleoules aureleoules left a comment

Choose a reason for hiding this comment

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

ACK 931924f5cc1dd9c82306a0ce59b62cf5c9276565
Tested with -blocksonly and -blocksonly -maxmempool=n and verified the logs, seems to work as intended.

(Please avoid rebasing when there is no need.)

Copy link
Contributor

@stickies-v stickies-v left a comment

Choose a reason for hiding this comment

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

Approach ACK 931924f5cc1dd9c82306a0ce59b62cf5c9276565, except for setting mempool_opts.max_size_bytes in two different locations and times.

I think this approach tackles a nice balance between addressing the most important issue (node crashing because of unexpected resource usage), reducing additional code overhead (compared to the other approaches considered) and allowing users to maintain existing performance profile without too much admin overhead. The biggest (but manageable) downside is that everyone that upgrades and doesn't manually override -maxmempool will silently experience a performance degradation, especially during IBD. I expect this performance degradation to be manageable, especially since most users that have the resources available, will probably have manually increased their dbcache anyway for IBD, lowering the relative impact of this change.

@willcl-ark willcl-ark force-pushed the blocksonly_mempool_cache branch 2 times, most recently from 2789dcd to ed5ce6d Compare January 17, 2023 15:31
@glozow glozow added the Mempool label Jan 17, 2023
Copy link
Contributor

@aureleoules aureleoules left a comment

Choose a reason for hiding this comment

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

reACK ed5ce6d0c911ac66bd5870a1711edef03a18ebeb - Wording updated and logic cleaned up since my last review.

Copy link
Contributor

@stickies-v stickies-v left a comment

Choose a reason for hiding this comment

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

ACK ed5ce6d0c

Copy link
Contributor

@ajtowns ajtowns left a comment

Choose a reason for hiding this comment

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

Approach ACK

When -blockonly is set, reduce mempool size to 5MB unless -maxmempool
is also set.

See bitcoin#9569
Changes to the default mempool allocation size now documented.

Provides users with guidance on the mempool implications of -blocksonly
mode, along with instructions on how to re-enable old behaviour.
@willcl-ark willcl-ark force-pushed the blocksonly_mempool_cache branch from ed5ce6d to dceef81 Compare January 20, 2023 13:31
Adds a release note detailing the new mempool sizing behaviour when
running in blocksonly mode, and instruction on how to override the new
defaults.
@willcl-ark willcl-ark force-pushed the blocksonly_mempool_cache branch from dceef81 to 8e85164 Compare January 20, 2023 13:54
@willcl-ark
Copy link
Member Author

Thanks for the comments, I've updated the branch taking them into consideration.

Copy link
Contributor

@ajtowns ajtowns left a comment

Choose a reason for hiding this comment

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

ACK 8e85164

Copy link
Contributor

@stickies-v stickies-v left a comment

Choose a reason for hiding this comment

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

re-ACK 8e85164


/** Default for -maxmempool, maximum megabytes of mempool memory usage */
static constexpr unsigned int DEFAULT_MAX_MEMPOOL_SIZE_MB{300};
//** Default for -maxmempool when blocksonly is set */
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
//** Default for -maxmempool when blocksonly is set */
/** Default for -maxmempool when blocksonly is set */

@fanquake fanquake merged commit ad09b76 into bitcoin:master Jan 22, 2023
@fanquake fanquake added this to the 25.0 milestone Jan 22, 2023
@willcl-ark willcl-ark deleted the blocksonly_mempool_cache branch January 22, 2023 20:52
- Since `0.14.0`, unused memory allocated to the mempool (default: 300MB) is shared with the UTXO cache, so when trying to reduce memory usage you should limit the mempool, with the `-maxmempool` command line argument.

- Do not use this when using the client to broadcast transactions as any transaction sent will stick out like a sore thumb, affecting privacy. When used with the wallet it should be combined with `-walletbroadcast=0` and `-spendzeroconfchange=0`. Another mechanism for broadcasting outgoing transactions (if any) should be used.
- To disable most of the mempool functionality there is the `-blocksonly` option. This will reduce the default memory usage to 5MB and make the client opt out of receiving (and thus relaying) transactions, except from whitelisted peers and as part of blocks.
Copy link
Member

Choose a reason for hiding this comment

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

nit: Instead of whitelisted, it would be good to mention the exact permission flag.

sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Jan 23, 2023
8e85164 doc: release note on mempool size in -blocksonly (willcl-ark)
ae79746 doc: Update blocksonly behaviour in reduce-memory (willcl-ark)
1134686 mempool: Don't share mempool with dbcache in blocksonly (willcl-ark)

Pull request description:

  Fixes bitcoin#9526

  When `-blocksonly` has been set reduce default mempool size to avoid surprising resource usage via sharing un-used mempool cache space with dbcache.

  In comparison to bitcoin#9569 which either set `maxmempool` size to 0 when `-blocksonly` was set or else errored on startup, this change will permit `maxmempool` options being set.

  This preserves the current (surprising?) behaviour of having a functional mempool in `-blocksonly` mode, to permit whitelisted peer transaction relay, whilst reducing average runtime memory usage for blocksonly nodes which either use the default settings or have otherwise configured a `maxmempool` size.

  To use the previous old defaults node operators can configure their node with: `-blocksonly -maxmempool=300`.

ACKs for top commit:
  ajtowns:
    ACK 8e85164
  stickies-v:
    re-ACK bitcoin@8e85164

Tree-SHA512: 1c461c24b6f14ba02cfe4e2cde60dc629e47485db5701bca3003b8df79e3aa311c0c967979f6a1dca3ba69f5b1e45fa2db6ff83352fdf2d4349d5f8d120e740d
@glozow
Copy link
Member

glozow commented Jan 30, 2023

@willcl-ark will you be taking the followups #26471 (comment) and #26471 (comment)?

@willcl-ark
Copy link
Member Author

Yes I can do those @glozow

glozow added a commit that referenced this pull request Feb 1, 2023
47c174d doc: NetPermissionFlags for tx relay in blocksonly (willcl-ark)
e325e0f doc: Fix comment syntax error (willcl-ark)

Pull request description:

  Fix syntax error and specify `NetPermissionFlags` for whitelisted tx relay

ACKs for top commit:
  w0xlt:
    ACK 47c174d

Tree-SHA512: eb579dc599a96a3ea79c01ac3e76160ec59cf71c2486c9401da8fbbd96ae756ba647aa9ba874835946bc76ba02782729da788617f982ae5a852139e10e7dfd75
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Feb 1, 2023
47c174d doc: NetPermissionFlags for tx relay in blocksonly (willcl-ark)
e325e0f doc: Fix comment syntax error (willcl-ark)

Pull request description:

  Fix syntax error and specify `NetPermissionFlags` for whitelisted tx relay

ACKs for top commit:
  w0xlt:
    ACK bitcoin@47c174d

Tree-SHA512: eb579dc599a96a3ea79c01ac3e76160ec59cf71c2486c9401da8fbbd96ae756ba647aa9ba874835946bc76ba02782729da788617f982ae5a852139e10e7dfd75
@bitcoin bitcoin locked and limited conversation to collaborators Jan 30, 2024
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.

-blocksonly should disable sharing of mempool with dbcache

10 participants