kernel,node: add `dbcache` setter and clarify defaults #35205

pull l0rinc wants to merge 8 commits into bitcoin:master from l0rinc:l0rinc/share-dbcache-defaults changing 15 files +73 −48
  1. l0rinc commented at 12:09 PM on May 4, 2026: contributor

    Problem: Since #34692, the node chooses a 450 MiB or 1 GiB database cache from detected RAM, while Kernel always uses 450 MiB. The shared names obscure the difference between the node's automatic policy and Kernel's fixed fallback, and Kernel callers cannot set their own cache budget.

    Fix: Cache RAM detection as uint64_t, keep the node's two-tier default unchanged, and make the fixed Kernel fallback explicit. Add a chainstate-manager option setter that accepts a total database cache budget and applies the shared bounds and cache split.

  2. DrahtBot commented at 12:09 PM on May 4, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/35205.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process.

    Type Reviewers
    ACK sedited, maflcko, stringintech
    Stale ACK w0xlt

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #35852 (scripted-diff: Use inline const(expr) over static constexpr in headers by maflcko)
    • #35322 (logging: streamline Logger state and drop redundant methods by ryanofsky)
    • #26022 (Add util::ResultPtr class by ryanofsky)
    • #25665 (refactor: Add util::Result failure types and ability to merge result values by ryanofsky)
    • #17783 (common: Disallow calling IsArgSet() on ALLOW_LIST options by ryanofsky)
    • #17581 (refactor: Remove settings merge reverse precedence code by ryanofsky)
    • #17580 (refactor: Add ALLOW_LIST flags and enforce usage in CheckArgFlags by ryanofsky)
    • #17493 (util: Forbid ambiguous multiple assignments in config file by ryanofsky)

    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.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  3. DrahtBot added the label CI failed on May 4, 2026
  4. DrahtBot commented at 1:00 PM on May 4, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task i686, no IPC: https://github.com/bitcoin/bitcoin/actions/runs/25318144859/job/74220316972</sub> <sub>LLM reason (✨ experimental): CI failed because the Bitcoin Core Test Suite had failing CTest results—sock_tests failed.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  5. in src/common/system_ram.cpp:23 in 56a8728519
      18 | +std::optional<size_t> GetTotalRAM()
      19 | +{
      20 | +    [[maybe_unused]] auto clamp{[](uint64_t v) { return size_t(std::min(v, uint64_t{std::numeric_limits<size_t>::max()})); }};
      21 | +#ifdef WIN32
      22 | +    if (MEMORYSTATUSEX m{}; (m.dwLength = sizeof(m), GlobalMemoryStatusEx(&m))) return clamp(m.ullTotalPhys);
      23 | +#elif defined(__APPLE__) || \
    


    kevkevinpal commented at 2:56 PM on May 4, 2026:

    One thing I noticed here is that in Apple's man page for sysconf, _SC_PHYS_PAGES and _SC_PAGESIZE are not listed at all. There is a chance that on OSX systems they may not be defined as seen in this post.

    The intended api for RAM on __APPLE__ looks to be sysctlbyname, which is used in crc32c and src/crypto/sha256.cpp

    ./src/crc32c/src/crc32c_arm64_check.h:57:  return sysctlbyname("hw.optional.armv8_crc32", &val, &len, nullptr, 0) == 0
    ./src/crypto/sha256.cpp:673:        if (sysctlbyname("hw.optional.arm.FEAT_SHA256", &val, &len, nullptr, 0) == 0) {
    

    l0rinc commented at 6:19 PM on May 4, 2026:

    This was introduced in https://github.com/bitcoin/bitcoin/pull/33333/changes/6c720459beead5c825b354a1d5c11969b6e3a170, it's not strictly related to the change, the code is just moved here.

    It's a valid observation though: for some reason the Apple man page doesn't list these two, but they are defined in their own open-source Libc tree and are working in reality:

    If it ever becomes a problem we can apply the alternative you're suggesting.


    kevkevinpal commented at 6:46 PM on May 4, 2026:

    Awesome, they must have forgotten to update their docs.

    Sounds like a plan, hopefully it is never an issue!

  6. l0rinc closed this on May 5, 2026

  7. l0rinc reopened this on May 5, 2026

  8. DrahtBot removed the label CI failed on May 5, 2026
  9. l0rinc force-pushed on May 5, 2026
  10. stickies-v commented at 4:13 PM on May 6, 2026: contributor

    Kernel shouldn't have any dependencies on common, so I think this approach is a regression. Generally, I think we should move towards kernel having less system dependencies instead of more, so approach nack for me

    edited: my concern seems to be addressed

  11. l0rinc marked this as a draft on May 7, 2026
  12. l0rinc renamed this:
    node,kernel: share `dbcache` default sizing
    kernel,node: clean up `dbcache` helpers and add kernel API
    on May 18, 2026
  13. l0rinc force-pushed on May 18, 2026
  14. l0rinc commented at 8:36 PM on May 18, 2026: contributor

    Thanks @stickies-v, I rewrote the kernel part based on your feedback.

    The latest push no longer makes bitcoinkernel depend on common/system_ram or node/dbcache, but keeps DEFAULT_KERNEL_CACHE as the kernel fallback and adds an explicit database-cache setter to the C API, so callers can pass the cache budget from outside.

  15. l0rinc marked this as ready for review on May 18, 2026
  16. DrahtBot added the label CI failed on May 18, 2026
  17. DrahtBot removed the label CI failed on May 19, 2026
  18. sedited commented at 8:44 PM on May 20, 2026: contributor

    Concept ACK

  19. DrahtBot added the label Needs rebase on May 22, 2026
  20. l0rinc force-pushed on May 22, 2026
  21. l0rinc commented at 7:05 AM on May 22, 2026: contributor

    Rebased, ready for review again.

  22. DrahtBot removed the label Needs rebase on May 22, 2026
  23. in src/node/dbcache.h:17 in c24ed5892a
      12 | +#include <limits>
      13 | +
      14 | +//! min. -dbcache (bytes)
      15 | +static constexpr uint64_t MIN_DBCACHE_BYTES{4_MiB};
      16 | +//! -dbcache default (bytes)
      17 | +static constexpr uint64_t DEFAULT_DBCACHE_BYTES{450_MiB};
    


    sedited commented at 9:48 AM on June 8, 2026:

    Why is this decoupled from the DEFAULT_KERNEL_CACHE?


    l0rinc commented at 3:15 PM on June 18, 2026:

    Good point, this was leftover from a previous version, thanks. It had become just an alias for DEFAULT_KERNEL_CACHE, so it added another name without representing distinct node policy. I dropped it and now use DEFAULT_KERNEL_CACHE directly everywhere.

  24. in src/qt/optionsmodel.cpp:735 in c24ed5892a
     731 | @@ -732,7 +732,7 @@ void OptionsModel::checkAndMigrate()
     732 |          // see https://github.com/bitcoin/bitcoin/pull/8273
     733 |          // force people to upgrade to the new value if they are using 100MB
     734 |          if (settingsVersion < 130000 && settings.contains("nDatabaseCache") && settings.value("nDatabaseCache").toLongLong() == 100)
     735 | -            settings.setValue("nDatabaseCache", (qint64)(DEFAULT_DB_CACHE >> 20));
     736 | +            settings.setValue("nDatabaseCache", qint64(node::GetDefaultDBCache() / 1_MiB));
    


    sedited commented at 10:02 AM on June 8, 2026:

    Is changing this to GetDefaultDBCache a bug fix?


    l0rinc commented at 3:13 PM on June 18, 2026:

    Not sure it matters much - I changed it back to the fixed DEFAULT_KERNEL_CACHE fallback since it's simpler here.

  25. sedited commented at 10:03 AM on June 8, 2026: contributor

    Approach ACK

    Took me a moment to follow along, but I do think now that what you call a "policy" split is probably a good thing and the changes seem fine.

  26. w0xlt commented at 8:08 AM on June 14, 2026: contributor

    Concept ACK

  27. l0rinc force-pushed on Jun 18, 2026
  28. in src/CMakeLists.txt:221 in 3172d54152
     217 | @@ -217,6 +218,7 @@ add_library(bitcoin_node STATIC EXCLUDE_FROM_ALL
     218 |    node/blockmanager_args.cpp
     219 |    node/blockstorage.cpp
     220 |    node/caches.cpp
     221 | +  node/dbcache.cpp
    


    sedited commented at 8:09 PM on June 18, 2026:

    Nit: alphabetical ordering

  29. in src/common/system_ram.cpp:2 in 3172d54152 outdated
       0 | @@ -0,0 +1,30 @@
       1 | +// Copyright (c) 2009-2010 Satoshi Nakamoto
       2 | +// Copyright (c) 2009-present The Bitcoin Core developers
    


    sedited commented at 8:11 PM on June 18, 2026:

    I think we don't need to transfer the dates over from the file this is moved from. Does this move to the new file still make sense in the context of the current patch? Afaict this made more sense in the earlier version of the pull request.


    l0rinc commented at 9:38 PM on June 18, 2026:

    Done both, thanks

  30. sedited approved
  31. sedited commented at 8:23 PM on June 18, 2026: contributor

    ACK 3172d54152dc73633d93bc618f7891fabb650d40

  32. DrahtBot requested review from stickies-v on Jun 18, 2026
  33. l0rinc force-pushed on Jun 18, 2026
  34. in src/common/system.cpp:28 in 6d5a3bbeba


    w0xlt commented at 12:58 AM on June 19, 2026:

    Are those includes stale ?

    diff --git a/src/common/system.cpp b/src/common/system.cpp
    index 0b1f05e02c..306b17d87e 100644
    --- a/src/common/system.cpp
    +++ b/src/common/system.cpp
    @@ -25,12 +25,8 @@
     #include <malloc.h>
     #endif
     
    -#include <algorithm>
    -#include <cstddef>
    -#include <cstdint>
     #include <cstdlib>
     #include <locale>
    -#include <optional>
     #include <stdexcept>
     #include <string>
     #include <thread>
    

    l0rinc commented at 2:43 AM on June 24, 2026:

    Done, thanks


    maflcko commented at 7:30 AM on July 6, 2026:

    I don't understand this pull request? What is the point of splitting this header up further? The size is only 29 lines before this pull request, and after this pull request there are several dbcache modules (caches and dbcache, both concerning the cache sizes of the dbs, where it is not clear why they are different).

    Not sure what the goal of this pull is, but I presume it is to remove the confusing DEFAULT_DB_CACHE? If yes, I presume it would be trivial to remove in a single simple commit.


    l0rinc commented at 6:48 PM on July 9, 2026:

    What is the point of splitting this header up further? @sipa explicitly asked for the dbcache declaration and definition to be colocated and the RAM declaration to move with its implementation.

    it is not clear why they are different

    node/dbcache holds the -dbcache policy, node/caches applies and splits the selected budget. I don't mind folding them back together if this separation is not useful.

    Not sure what the goal of this pull is, but I presume it is to remove the confusing DEFAULT_DB_CACHE

    Partially - the kernel setter is the functional addition, the remaining commits clean up units, types, and tests around the existing two-tier default.


    maflcko commented at 9:48 AM on July 14, 2026:

    What is the point of splitting this header up further?

    sipa explicitly asked for the dbcache declaration and definition to be colocated and the RAM declaration to move with its implementation.

    Right. Though, this is just a rule from the dev notes:

    doc/developer-notes.md:807:  - *Rationale*: Include files define the interface for the code in implementation files.  
    

    I don't think sipa asked for the split itself?

    Also, the commit is co-authored by an email that doesn't exist?

    Co-authored-by: sipa <sipa@bitcoincore.org>
    

    I wonder where that email is from? I couldn't find it in the git logs or the pgp keys, or any other public source.

    it is not clear why they are different

    node/dbcache holds the -dbcache policy, node/caches applies and splits the selected budget. I don't mind folding them back together if this separation is not useful.

    Ok, I see. No strong opinion. I guess it is just me not seeing the point. If other reviewers are happy, then it should be fine.


    l0rinc commented at 6:15 PM on July 14, 2026:

    I don't think sipa asked for the split itself?

    Hah, looks like I misunderstood what he meant originally, thanks for persisting! I dropped the commit changing node/dbcache files + CMake entry.

    Also, the commit is co-authored by an email that doesn't exist

    Yeah, that was bullshit - I couldn't find a source for that, it's not visible in my IDE either - thanks for noticing! <img width="642" height="103" alt="image" src="https://github.com/user-attachments/assets/45ac607b-7bb0-4b52-a1e2-534f7f1e5c39" />

    I guess it is just me not seeing the point

    I didn't mean to imply that - I went over the changes again, dropped the node/dbcache split, split one commit to two smaller ones, and simplified the commit messages and PR description based on the feedback. I also removed duplicated derived cache state from the kernel options.


    stringintech commented at 9:34 AM on July 24, 2026:

    iwyu is suggesting to also include kernel/caches.h.


    stringintech commented at 9:40 AM on July 24, 2026:

    Seems #include <unistd.h> was only needed for the syscalls in GetTotalRAM and can be dropped now. Also suggested by iwyu.

  35. in src/common/system_ram.h:2 in 6d5a3bbeba outdated
       0 | @@ -0,0 +1,17 @@
       1 | +// Copyright (c) 2009-2010 Satoshi Nakamoto
       2 | +// Copyright (c) 2009-present The Bitcoin Core developers
    


    w0xlt commented at 1:00 AM on June 19, 2026:

    micro-nit: the copyright texts are different in src/common/system_ram.h and src/common/system_ram.cpp.


    l0rinc commented at 2:43 AM on June 24, 2026:

    done, thanks

  36. in src/test/kernel/test_kernel.cpp:780 in 6d5a3bbeba outdated
     776 | @@ -776,6 +777,7 @@ BOOST_AUTO_TEST_CASE(btck_chainman_tests)
     777 |  
     778 |      ChainstateManagerOptions chainman_opts{context, PathToString(test_directory.m_directory), PathToString(test_directory.m_directory / "blocks")};
     779 |      chainman_opts.SetWorkerThreads(4);
     780 | +    chainman_opts.SetDatabaseCacheBytes(1000_MiB);
    


    w0xlt commented at 1:25 AM on June 19, 2026:

    nit: This can be ignored or left for a follow-up. The test could also assert that the configured cache budget reaches the chainstate cache split for stronger coverage.

    <details> <summary>diff</summary>

    diff --git a/src/kernel/bitcoinkernel.cpp b/src/kernel/bitcoinkernel.cpp
    index c26d2a98c7..36360fcdd9 100644
    --- a/src/kernel/bitcoinkernel.cpp
    +++ b/src/kernel/bitcoinkernel.cpp
    @@ -1071,6 +1071,16 @@ btck_ChainstateManager* btck_chainstate_manager_create(
         return btck_ChainstateManager::create(std::move(chainman), opts.m_context);
     }
     
    +btck_ChainstateManagerCacheSizes btck_chainstate_manager_get_cache_sizes(
    +    const btck_ChainstateManager* chainman)
    +{
    +    const auto& manager{*btck_ChainstateManager::get(chainman).m_chainman};
    +    return {
    +        .coins_db_cache_bytes = manager.m_total_coinsdb_cache,
    +        .coins_tip_cache_bytes = manager.m_total_coinstip_cache,
    +    };
    +}
    +
     const btck_BlockTreeEntry* btck_chainstate_manager_get_block_tree_entry_by_hash(const btck_ChainstateManager* chainman, const btck_BlockHash* block_hash)
     {
         auto block_index = WITH_LOCK(btck_ChainstateManager::get(chainman).m_chainman->GetMutex(),
    diff --git a/src/kernel/bitcoinkernel.h b/src/kernel/bitcoinkernel.h
    index 3c9e34fe72..02ee7a5269 100644
    --- a/src/kernel/bitcoinkernel.h
    +++ b/src/kernel/bitcoinkernel.h
    @@ -226,6 +226,12 @@ typedef struct btck_ChainstateManagerOptions btck_ChainstateManagerOptions;
      */
     typedef struct btck_ChainstateManager btck_ChainstateManager;
     
    +/** Cache sizes selected for a chainstate manager. */
    +typedef struct {
    +    size_t coins_db_cache_bytes;  //!< LevelDB cache reserved for the coins database.
    +    size_t coins_tip_cache_bytes; //!< In-memory coins cache.
    +} btck_ChainstateManagerCacheSizes;
    +
     /**
      * Opaque data structure for holding a block.
      */
    @@ -1249,6 +1255,15 @@ BITCOINKERNEL_API void btck_chainstate_manager_options_destroy(btck_ChainstateMa
     BITCOINKERNEL_API btck_ChainstateManager* BITCOINKERNEL_WARN_UNUSED_RESULT btck_chainstate_manager_create(
         const btck_ChainstateManagerOptions* chainstate_manager_options) BITCOINKERNEL_ARG_NONNULL(1);
     
    +/**
    + * [@brief](/bitcoin-bitcoin/contributor/brief/) Get the cache sizes selected for a chainstate manager.
    + *
    + * [@param](/bitcoin-bitcoin/contributor/param/)[in] chainstate_manager Non-null.
    + * [@return](/bitcoin-bitcoin/contributor/return/)                      The chainstate cache sizes in bytes.
    + */
    +BITCOINKERNEL_API btck_ChainstateManagerCacheSizes btck_chainstate_manager_get_cache_sizes(
    +    const btck_ChainstateManager* chainstate_manager) BITCOINKERNEL_ARG_NONNULL(1);
    +
     /**
      * [@brief](/bitcoin-bitcoin/contributor/brief/) Get the btck_BlockTreeEntry whose associated btck_BlockHeader has the most
      * known cumulative proof of work.
    diff --git a/src/kernel/bitcoinkernel_wrapper.h b/src/kernel/bitcoinkernel_wrapper.h
    index a2b0ceaf9c..752ff4165b 100644
    --- a/src/kernel/bitcoinkernel_wrapper.h
    +++ b/src/kernel/bitcoinkernel_wrapper.h
    @@ -1165,6 +1165,11 @@ public:
         }
     };
     
    +struct ChainstateManagerCacheSizes {
    +    size_t coins_db;
    +    size_t coins_tip;
    +};
    +
     class ChainView : public View<btck_Chain>
     {
     public:
    @@ -1302,6 +1307,12 @@ public:
         {
         }
     
    +    ChainstateManagerCacheSizes GetCacheSizes() const
    +    {
    +        const auto sizes{btck_chainstate_manager_get_cache_sizes(get())};
    +        return {sizes.coins_db_cache_bytes, sizes.coins_tip_cache_bytes};
    +    }
    +
         bool ImportBlocks(const std::span<const std::string> paths)
         {
             std::vector<const char*> c_paths;
    diff --git a/src/test/kernel/test_kernel.cpp b/src/test/kernel/test_kernel.cpp
    index 780164cfcd..e11f1cefa5 100644
    --- a/src/test/kernel/test_kernel.cpp
    +++ b/src/test/kernel/test_kernel.cpp
    @@ -783,6 +783,9 @@ BOOST_AUTO_TEST_CASE(btck_chainman_tests)
         BOOST_CHECK(chainman_opts.SetWipeDbs(/*wipe_block_tree=*/false, /*wipe_chainstate=*/true));
         BOOST_CHECK(chainman_opts.SetWipeDbs(/*wipe_block_tree=*/false, /*wipe_chainstate=*/false));
         ChainMan chainman{context, chainman_opts};
    +    const auto cache_sizes{chainman.GetCacheSizes()};
    +    BOOST_CHECK_EQUAL(cache_sizes.coins_db, 8_MiB);
    +    BOOST_CHECK_EQUAL(cache_sizes.coins_tip, 990_MiB);
     }
     
     std::unique_ptr<ChainMan> create_chainman(TestDirectory& test_directory,
    

    </details>


    l0rinc commented at 2:42 AM on June 24, 2026:

    Thanks, given that the current PR already barely received any review I'll leave this for a follow-up.

  37. w0xlt commented at 1:25 AM on June 19, 2026: contributor

    ACK 6d5a3bbeba515d8c39e22732f116ff238b490e04

    Some non-blocking nits:

  38. DrahtBot requested review from sedited on Jun 19, 2026
  39. l0rinc force-pushed on Jun 24, 2026
  40. l0rinc commented at 2:43 AM on June 24, 2026: contributor

    rebased and applied nits. @stickies-v, I'd appreciate your reevaluation.

  41. w0xlt commented at 3:59 AM on June 24, 2026: contributor

    reACK ce12cd6a1c602658d2ef70cf9b26d7f727ef4af0

  42. sedited approved
  43. sedited commented at 8:42 AM on June 24, 2026: contributor

    ACK ce12cd6a1c602658d2ef70cf9b26d7f727ef4af0

  44. maflcko commented at 7:34 AM on July 6, 2026: member

    ce12cd6a1c602658d2ef70cf9b26d7f727ef4af0~5

  45. DrahtBot added the label Needs rebase on Jul 9, 2026
  46. l0rinc force-pushed on Jul 9, 2026
  47. DrahtBot removed the label Needs rebase on Jul 9, 2026
  48. l0rinc commented at 6:55 PM on July 9, 2026: contributor

    Rebased on current master, adapted the stack to the upstream size_t -> uint64_t changes, folded the final type-cleanup commit into the earlier ones.

  49. DrahtBot added the label Needs rebase on Jul 14, 2026
  50. l0rinc renamed this:
    kernel,node: clean up `dbcache` helpers and add kernel API
    kernel,node: add `dbcache` setter and clarify defaults
    on Jul 14, 2026
  51. l0rinc force-pushed on Jul 14, 2026
  52. DrahtBot removed the label Needs rebase on Jul 14, 2026
  53. in src/test/kernel/test_kernel.cpp:804 in dc2bc256c2
     800 | @@ -800,6 +801,7 @@ BOOST_AUTO_TEST_CASE(btck_chainman_tests)
     801 |  
     802 |      ChainstateManagerOptions chainman_opts{context, PathToString(test_directory.m_directory), PathToString(test_directory.m_directory / "blocks")};
     803 |      chainman_opts.SetWorkerThreads(4);
     804 | +    chainman_opts.SetDatabaseCacheBytes(1_GiB);
    


    w0xlt commented at 8:50 PM on July 14, 2026:

    btck_chainstate_manager_options_set_database_cache_bytes() accepts 0 and 1, but these produce an empty coins or coins-DB cache and later abort in node/chainstate.cpp. Should the setter reject these values before mutating the options?

    Suggestion:

    <details> <summary>diff</summary>

    diff --git a/src/kernel/bitcoinkernel.cpp b/src/kernel/bitcoinkernel.cpp
    index a5c163502c..da6f33fed0 100644
    --- a/src/kernel/bitcoinkernel.cpp
    +++ b/src/kernel/bitcoinkernel.cpp
    @@ -1032,12 +1032,19 @@ void btck_chainstate_manager_options_set_worker_threads_num(btck_ChainstateManag
         btck_ChainstateManagerOptions::get(opts).m_chainman_options.worker_threads_num = worker_threads;
     }
     
    -void btck_chainstate_manager_options_set_database_cache_bytes(btck_ChainstateManagerOptions* chainman_opts, size_t database_cache_bytes)
    +int btck_chainstate_manager_options_set_database_cache_bytes(btck_ChainstateManagerOptions* chainman_opts, size_t database_cache_bytes)
     {
    +    const kernel::CacheSizes cache_sizes{database_cache_bytes};
    +    if (cache_sizes.coins_db == 0 || cache_sizes.coins == 0) {
    +        LogError("Failed to set database cache: size must be at least 2 bytes.");
    +        return -1;
    +    }
    +
         auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};
         LOCK(opts.m_mutex);
         opts.m_db_cache_bytes = database_cache_bytes;
    -    opts.m_blockman_options.block_tree_db_params.cache_bytes = kernel::CacheSizes{database_cache_bytes}.block_tree_db;
    +    opts.m_blockman_options.block_tree_db_params.cache_bytes = cache_sizes.block_tree_db;
    +    return 0;
     }
     
     void btck_chainstate_manager_options_destroy(btck_ChainstateManagerOptions* options)
    diff --git a/src/kernel/bitcoinkernel.h b/src/kernel/bitcoinkernel.h
    index 73475e47e4..d0219ece6f 100644
    --- a/src/kernel/bitcoinkernel.h
    +++ b/src/kernel/bitcoinkernel.h
    @@ -1203,9 +1203,10 @@ BITCOINKERNEL_API void btck_chainstate_manager_options_set_worker_threads_num(
      * called, the total cache defaults to 450 MiB.
      *
      * [@param](/bitcoin-bitcoin/contributor/param/)[in] chainstate_manager_options Non-null, options to be set.
    - * [@param](/bitcoin-bitcoin/contributor/param/)[in] database_cache_bytes       The total database cache size in bytes.
    + * [@param](/bitcoin-bitcoin/contributor/param/)[in] database_cache_bytes       The total database cache size in bytes. Values below 2 are rejected.
    + * [@return](/bitcoin-bitcoin/contributor/return/)                               0 if the set was successful, non-zero if the set failed.
      */
    -BITCOINKERNEL_API void btck_chainstate_manager_options_set_database_cache_bytes(
    +BITCOINKERNEL_API int BITCOINKERNEL_WARN_UNUSED_RESULT btck_chainstate_manager_options_set_database_cache_bytes(
         btck_ChainstateManagerOptions* chainstate_manager_options,
         size_t database_cache_bytes) BITCOINKERNEL_ARG_NONNULL(1);
     
    diff --git a/src/kernel/bitcoinkernel_wrapper.h b/src/kernel/bitcoinkernel_wrapper.h
    index 42d19e4a22..9783c3aba1 100644
    --- a/src/kernel/bitcoinkernel_wrapper.h
    +++ b/src/kernel/bitcoinkernel_wrapper.h
    @@ -1200,9 +1200,9 @@ public:
             btck_chainstate_manager_options_set_worker_threads_num(get(), worker_threads);
         }
     
    -    void SetDatabaseCacheBytes(size_t database_cache_bytes)
    +    bool SetDatabaseCacheBytes(size_t database_cache_bytes)
         {
    -        btck_chainstate_manager_options_set_database_cache_bytes(get(), database_cache_bytes);
    +        return btck_chainstate_manager_options_set_database_cache_bytes(get(), database_cache_bytes) == 0;
         }
     
         bool SetWipeDbs(bool wipe_block_tree, bool wipe_chainstate)
    diff --git a/src/test/kernel/test_kernel.cpp b/src/test/kernel/test_kernel.cpp
    index 2ac48b6746..c72c8a995a 100644
    --- a/src/test/kernel/test_kernel.cpp
    +++ b/src/test/kernel/test_kernel.cpp
    @@ -801,7 +801,10 @@ BOOST_AUTO_TEST_CASE(btck_chainman_tests)
     
         ChainstateManagerOptions chainman_opts{context, PathToString(test_directory.m_directory), PathToString(test_directory.m_directory / "blocks")};
         chainman_opts.SetWorkerThreads(4);
    -    chainman_opts.SetDatabaseCacheBytes(1_GiB);
    +    BOOST_CHECK(chainman_opts.SetDatabaseCacheBytes(2));
    +    BOOST_CHECK(chainman_opts.SetDatabaseCacheBytes(1_GiB));
    +    BOOST_CHECK(!chainman_opts.SetDatabaseCacheBytes(0));
    +    BOOST_CHECK(!chainman_opts.SetDatabaseCacheBytes(1));
         BOOST_CHECK(!chainman_opts.SetWipeDbs(/*wipe_block_tree=*/true, /*wipe_chainstate=*/false));
         BOOST_CHECK(chainman_opts.SetWipeDbs(/*wipe_block_tree=*/true, /*wipe_chainstate=*/true));
         BOOST_CHECK(chainman_opts.SetWipeDbs(/*wipe_block_tree=*/false, /*wipe_chainstate=*/true));
    

    </details>


    l0rinc commented at 2:08 AM on July 15, 2026:

    Hmm, and move MIN_DBCACHE_BYTES to src/kernel/caches.h? Sure, pushed, let me know what you think.

  54. in src/test/system_ram_tests.cpp:15 in dc2bc256c2 outdated
      22 | -        return;
      23 | -    }
      24 | -
      25 | -    BOOST_CHECK_GE(*total, 1000_MiB);
      26 | +    const auto total{TryGetTotalRam()};
      27 | +    BOOST_REQUIRE(total);
    


    w0xlt commented at 9:12 PM on July 14, 2026:

    Given the Try name and std::optional return type, I assume RAM detection may legitimately fail on some supported environments. Or do we expect successful detection on every test platform?

    Suggestion (for the former case):

    <details> <summary>diff</summary>

    diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
    index 0e4e4fd1fb..b5a12f7277 100644
    --- a/src/test/CMakeLists.txt
    +++ b/src/test/CMakeLists.txt
    @@ -199,6 +199,7 @@ function(add_boost_test source_file)
           SKIP_REGULAR_EXPRESSION
             "no test cases matching filter"
             "skipping script_assets_test"
    +        "skipping total_ram"
         )
       endforeach()
     endfunction()
    diff --git a/src/test/system_ram_tests.cpp b/src/test/system_ram_tests.cpp
    index 16da6d1065..60f6361472 100644
    --- a/src/test/system_ram_tests.cpp
    +++ b/src/test/system_ram_tests.cpp
    @@ -12,7 +12,11 @@ BOOST_AUTO_TEST_SUITE(system_ram_tests)
     BOOST_AUTO_TEST_CASE(total_ram)
     {
         const auto total{TryGetTotalRam()};
    -    BOOST_REQUIRE(total);
    +    if (!total) {
    +        BOOST_WARN_MESSAGE(false, "skipping total_ram: total RAM unknown");
    +        return;
    +    }
    +
         BOOST_CHECK_GE(*total, 1_GiB);
         BOOST_CHECK_LT(*total, 10'000_GiB); // ~10 TiB memory is unlikely
     }
    

    </details>


    l0rinc commented at 1:58 AM on July 15, 2026:

    You mean to drop https://github.com/bitcoin/bitcoin/pull/35205/changes/dc2bc256c26a6fb2977b2fc47a113c4f906655b4? Since we depend on this for more than just the warning I think we should support every CI agent that we run this on.


    maflcko commented at 2:38 PM on August 3, 2026:

    Yeah, I don't see either how this change is related to this pull request. How does this pull request change how callers depend on this function. I had the impression this pull is a refactor.

    Maybe this commit makes sense, but a test failure here doesn't seem actionable: What should a user do when this fails, not run Bitcoin Core or something else?


    l0rinc commented at 7:02 PM on August 3, 2026:

    The intended action is to report the unsupported environment so we can extend RAM detection, as explained in the commit message. TryGetTotalRam() can fail at runtime, but on our test platforms I want this to fail instead of silently skipping. Let me know if you feel strongly about it, I can drop it, but it was a deliberate choice on my part.


    maflcko commented at 1:19 PM on August 4, 2026:

    As a suggestion, to make it actionable, and avoid having to look up the commit message while reading the test:

        BOOST_REQUIRE(total); // If this fails, automatic -dbcache selection may be broken, please report
    

    (Feel free to drop the , please report)


    l0rinc commented at 6:21 PM on August 4, 2026:

    Isn't that the general recommendation for failing tests, to report them to us? I can of course add this comment, but I explicitly wanted to make sure this fails loudly so that we get notified, maximizing our chance of finding out what other infra we need to cover.

  55. in src/test/system_ram_tests.cpp:16 in dc2bc256c2 outdated
      23 | -    }
      24 | -
      25 | -    BOOST_CHECK_GE(*total, 1000_MiB);
      26 | +    const auto total{TryGetTotalRam()};
      27 | +    BOOST_REQUIRE(total);
      28 | +    BOOST_CHECK_GE(*total, 1_GiB);
    


    w0xlt commented at 9:54 PM on July 14, 2026:

    1_GiB is 24 MiB higher than the original test with 1000_MiB. Is this change intentional ?


    l0rinc commented at 1:59 AM on July 15, 2026:

    Yes, I don't think we can have total memory of 1000_MiB (hence BOOST_CHECK_GE and not BOOST_CHECK_GT)

  56. l0rinc force-pushed on Jul 15, 2026
  57. w0xlt commented at 5:56 PM on July 15, 2026: contributor

    reACK 88dd7786b23ccf919f4046d5b3814d237d67a31a

  58. DrahtBot requested review from sedited on Jul 15, 2026
  59. in src/common/system_ram.cpp:20 in 88dd7786b2
      15 | +#include <limits>
      16 | +
      17 | +std::optional<size_t> TryGetTotalRam()
      18 | +{
      19 | +    static const auto total_ram{[]() -> std::optional<size_t> {
      20 | +        [[maybe_unused]] auto clamp{[](uint64_t v) { return size_t(std::min(v, uint64_t{std::numeric_limits<size_t>::max()})); }};
    


    stringintech commented at 9:10 AM on July 24, 2026:

    Perhaps out of scope for this PR, but it's not clear to me why we clamp to size_t here. AFAIK this exists so callers could safely consume a size_t, but after #35616 moved the cache arithmetic to uint64_t, none of the current callers need size_t anymore. So could this just return uint64_t directly and drop the clamp?


    maflcko commented at 1:32 PM on August 4, 2026:

    The docs say:

           These values also exist, but may not be standard.
    
            - _SC_PHYS_PAGES
                  The number of pages of physical memory.  Note that it is
                  possible for the product of this value and the value of
                  _SC_PAGESIZE to overflow.
    

    But there is a cast to ULL, so it should be fine

  60. in src/kernel/bitcoinkernel.h:1212 in 88dd7786b2
    1207 | + *                                       On 32-bit systems, values above 1 GiB are also rejected.
    1208 | + * @return                               0 if the set was successful, non-zero if the set failed.
    1209 | + */
    1210 | +BITCOINKERNEL_API int BITCOINKERNEL_WARN_UNUSED_RESULT btck_chainstate_manager_options_set_database_cache_bytes(
    1211 | +    btck_ChainstateManagerOptions* chainstate_manager_options,
    1212 | +    size_t database_cache_bytes) BITCOINKERNEL_ARG_NONNULL(1);
    


    stringintech commented at 9:16 AM on July 24, 2026:

    nit: still going back and forth on whether database_cache_bytes should be uint64_t instead of size_t here, to match the internal arithmetic (which is all uint64_t), or whether size_t is fine as-is since it's genuinely bounding process-addressable memory...

  61. in src/common/system_ram.h:1 in 88dd7786b2
       0 | @@ -0,0 +1,16 @@
       1 | +// Copyright (c) 2009-present The Bitcoin Core developers
    


    stringintech commented at 9:21 AM on July 24, 2026:

    Is carrying the 2009 from system.h intentional here? (First time reading #35205 (review) i thought it is suggesting to just use 2026 instead)


    stringintech commented at 9:17 AM on July 25, 2026:

    First I was confused by the dropped year in the latest force push, then found out it is a recent convention (e.g. #24539 (review)). Might be worth documenting it somewhere explicitly in a follow-up, but I wasn't sure how exactly.

  62. stringintech commented at 9:44 AM on July 24, 2026: contributor

    Approach ACK

  63. l0rinc force-pushed on Jul 24, 2026
  64. l0rinc commented at 6:28 PM on July 24, 2026: contributor

    Thanks @stringintech! The rebase also exposed the issues you flagged because the affected cache types had changed since this PR was opened, good catch. I addressed all of your comments and added you as co-author.

  65. stringintech commented at 9:16 AM on July 25, 2026: contributor

    ACK 1df4b56b

  66. DrahtBot requested review from w0xlt on Jul 25, 2026
  67. in src/common/system_ram.cpp:5 in 15cdf19826
       0 | @@ -0,0 +1,31 @@
       1 | +// Copyright (c) The Bitcoin Core developers
       2 | +// Distributed under the MIT software license, see the accompanying
       3 | +// file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4 | +
       5 | +#include <common/system_ram.h>
    


    maflcko commented at 2:34 PM on August 3, 2026:

    15cdf198269f03aa726e10c59950556cbb815ac4: Not sure about splitting this up. This is very much system related, just like GetNumCores. Also, the rationale in the commit message doesn't apply, because the system header is extremely thin, so there shouldn't be any overhead from including it.

    Otherwise, someone is going to split up the GetNumCores function into system_nproc.cpp, etc ...


    l0rinc commented at 7:28 PM on August 3, 2026:

    Good catch, the split was only needed by an earlier version where bitcoinkernel used the RAM helper directly. The current version no longer does, so I folded it back into common/system.{h,cpp}.

  68. node, qt: use `1_MiB` for dbcache conversions 41c44f5588
  69. scripted-diff: use `TryGetTotalRam`
    Use the `Try` prefix to make failed RAM detection visible at call sites.
    
    -BEGIN VERIFY SCRIPT-
    git grep -q 'TryGetTotalRam' -- src && echo "Error: TryGetTotalRam already exists in src" && exit 1
    git grep -l 'GetTotalRAM' -- src | xargs perl -pi -e 's/\bGetTotalRAM\b/TryGetTotalRam/g'
    -END VERIFY SCRIPT-
    031fa402c8
  70. common: cache total RAM as `uint64_t`
    Detect total RAM once so automatic cache selection and the oversized-cache warning use the same value.
    Database cache arithmetic now uses `uint64_t`, so return the byte count directly and remove the 32-bit `size_t` clamp.
    
    Co-authored-by: stringintech <stringintech@gmail.com>
    ab63432576
  71. scripted-diff: use `MIN_DBCACHE_BYTES`
    -BEGIN VERIFY SCRIPT-
    git grep -q '\bMIN_DBCACHE_BYTES\b' -- src && echo "Error: renamed dbcache byte constant already exists in src" && exit 1
    git grep -l 'MIN_DB_CACHE' -- src | xargs perl -pi -e 's/\bMIN_DB_CACHE\b/MIN_DBCACHE_BYTES/g'
    -END VERIFY SCRIPT-
    
    Co-authored-by: optout <13562139+optout21@users.noreply.github.com>
    7cfa21d60a
  72. kernel, node: colocate dbcache bounds
    Keep the total database cache bounds with `kernel::CacheSizes` so node and Kernel callers validate against the same range.
    8aa21e119b
  73. kernel: allow setting chainstate `dbcache`
    Add `btck_chainstate_manager_options_set_database_cache_bytes()` so Kernel callers can set the total database cache budget.
    Use `uint64_t` for a fixed-width C API, reject values outside the architecture-specific range, and keep `DEFAULT_KERNEL_CACHE` as the fallback.
    Apply the selected split to the block tree database and `LoadChainstate()`.
    
    Co-authored-by: stickies-v <stickies-v@protonmail.com>
    Co-authored-by: w0xlt <94266259+w0xlt@users.noreply.github.com>
    Co-authored-by: stringintech <stringintech@gmail.com>
    8bd9f46082
  74. node, qt: inline `DEFAULT_DB_CACHE`
    The alias is misleading because automatic selection can also return `HIGH_DEFAULT_DBCACHE`.
    cd086c16dd
  75. test: require `TryGetTotalRam()` detection
    RAM detection controls automatic `-dbcache` selection, so fail the test when it is unavailable.
    6a2de55a0d
  76. l0rinc force-pushed on Aug 3, 2026
  77. l0rinc commented at 7:29 PM on August 3, 2026: contributor

    Thanks, addressed the concerns, the PR is a lot simpler without the extraction.

  78. sedited approved
  79. sedited commented at 12:18 PM on August 4, 2026: contributor

    ACK 6a2de55a0d8b62255f84a8cd1f20715aaf6a8764

  80. DrahtBot requested review from stringintech on Aug 4, 2026
  81. sedited requested review from kevkevinpal on Aug 4, 2026
  82. maflcko commented at 1:44 PM on August 4, 2026: member

    review ACK 6a2de55a0d8b62255f84a8cd1f20715aaf6a8764 🚵

    <details><summary>Show signature</summary>

    Signature:

    untrusted comment: signature from minisign secret key on empty file; verify via: minisign -Vm "${path_to_any_empty_file}" -P RWTRmVTMeKV5noAMqVlsMugDDCyyTSbA3Re5AkUrhvLVln0tSaFWglOw -x "${path_to_this_whole_four_line_signature_blob}"
    RUTRmVTMeKV5npGrKx1nqXCw5zeVHdtdYURB/KlyA/LMFgpNCs+SkW9a8N95d+U4AP1RJMi+krxU1A3Yux4bpwZNLvVBKy0wLgM=
    trusted comment: review ACK 6a2de55a0d8b62255f84a8cd1f20715aaf6a8764 🚵
    11PZ/kApJOX1b4JK5FmOrrG+WdPpU+nl3kecTe+D7U3Xy5fN50nSom59Vhdf7iYSMWK+D2f8blyJoRbXq0KrCQ==
    

    </details>

  83. stringintech commented at 6:38 PM on August 4, 2026: contributor

    re-ACK 6a2de55a

  84. sedited merged this on Aug 4, 2026
  85. sedited closed this on Aug 4, 2026


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-08-11 09:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me