LCOV - code coverage report
Current view: top level - src/node - caches.cpp (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 70.0 % 30 21
Test Date: 2026-07-17 06:52:43 Functions: 100.0 % 4 4
Branches: 38.2 % 34 13

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2021-present 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 <node/caches.h>
       6                 :             : 
       7                 :             : #include <common/args.h>
       8                 :             : #include <common/system.h>
       9                 :             : #include <index/txindex.h>
      10                 :             : #include <index/txospenderindex.h>
      11                 :             : #include <kernel/caches.h>
      12                 :             : #include <node/interface_ui.h>
      13                 :             : #include <tinyformat.h>
      14                 :             : #include <util/byte_units.h>
      15                 :             : #include <util/log.h>
      16                 :             : #include <util/overflow.h>
      17                 :             : #include <util/translation.h>
      18                 :             : 
      19                 :             : #include <algorithm>
      20                 :             : #include <cstdint>
      21                 :             : #include <limits>
      22                 :             : #include <string>
      23                 :             : 
      24                 :             : // Unlike for the UTXO database, for the txindex scenario the leveldb cache make
      25                 :             : // a meaningful difference: https://github.com/bitcoin/bitcoin/pull/8273#issuecomment-229601991
      26                 :             : //! Max memory allocated to tx index DB specific cache in bytes.
      27                 :             : static constexpr uint64_t MAX_TX_INDEX_CACHE{1_GiB};
      28                 :             : //! Max memory allocated to all block filter index caches combined in bytes.
      29                 :             : static constexpr uint64_t MAX_FILTER_INDEX_CACHE{1_GiB};
      30                 :             : //! Max memory allocated to tx spenderindex DB specific cache in bytes.
      31                 :             : static constexpr uint64_t MAX_TXOSPENDER_INDEX_CACHE{1_GiB};
      32                 :             : //! Maximum dbcache size on 32-bit systems.
      33                 :             : static constexpr uint64_t MAX_32BIT_DBCACHE{1_GiB};
      34                 :             : //! Larger default dbcache on 64-bit systems with enough RAM.
      35                 :             : static constexpr uint64_t HIGH_DEFAULT_DBCACHE{1_GiB};
      36                 :             : //! Minimum detected RAM required for HIGH_DEFAULT_DBCACHE.
      37                 :             : static constexpr uint64_t HIGH_DEFAULT_DBCACHE_MIN_TOTAL_RAM{4_GiB};
      38                 :             : 
      39                 :             : namespace node {
      40                 :         857 : uint64_t GetDefaultDBCache()
      41                 :             : {
      42                 :         857 :     if constexpr (sizeof(void*) >= 8) {
      43   [ +  -  +  - ]:         857 :         if (GetTotalRAM().value_or(0) >= HIGH_DEFAULT_DBCACHE_MIN_TOTAL_RAM) {
      44                 :         857 :             return HIGH_DEFAULT_DBCACHE;
      45                 :             :         }
      46                 :             :     }
      47                 :             :     return DEFAULT_DB_CACHE;
      48                 :             : }
      49                 :             : 
      50                 :         165 : uint64_t CalculateDbCacheBytes(const ArgsManager& args)
      51                 :             : {
      52         [ -  + ]:         330 :     if (auto db_cache{args.GetIntArg("-dbcache")}) {
      53         [ #  # ]:           0 :         if (*db_cache < 0) db_cache = 0;
      54         [ #  # ]:           0 :         const uint64_t db_cache_bytes{SaturatingLeftShift<uint64_t>(*db_cache, 20)};
      55                 :           0 :         constexpr uint64_t max_db_cache{sizeof(void*) == 4 ? MAX_32BIT_DBCACHE : std::numeric_limits<uint64_t>::max()};
      56         [ #  # ]:           0 :         return std::max<uint64_t>(MIN_DB_CACHE, std::min<uint64_t>(db_cache_bytes, max_db_cache));
      57                 :             :     }
      58                 :         165 :     return GetDefaultDBCache();
      59                 :             : }
      60                 :             : 
      61                 :         164 : CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes)
      62                 :             : {
      63                 :         164 :     uint64_t total_cache{CalculateDbCacheBytes(args)};
      64                 :             : 
      65                 :             :     // Allocate proportional to usage pattern benefit:
      66                 :             :     // - txindex (10%): serves getrawtransaction RPCs with mostly unique,
      67                 :             :     //   non-repetitive lookups across the entire blockchain.
      68                 :             :     // - blockfilterindex (5%): serves BIP 157 light clients that repeatedly
      69                 :             :     //   query recent blocks, benefiting from LevelDB cache, but the
      70                 :             :     //   working set for a typical 2-week offline gap is ~200kiB, well within 5%
      71                 :             :     //   of the total cache.
      72                 :             :     // - txospenderindex (5%): serves gettxspendingprevout RPCs with very
      73                 :             :     //   specific, rarely repeated outpoint queries.
      74                 :             :     // - coinstatsindex: intentionally not included here, since usage pattern
      75                 :             :     //   does not seem to suggest it would be necessary to cache.
      76                 :         164 :     IndexCacheSizes index_sizes;
      77   [ +  -  +  -  :         328 :     index_sizes.tx_index = std::min(total_cache * 10 / 100, args.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? MAX_TX_INDEX_CACHE : 0);
                   -  + ]
      78   [ +  -  +  -  :         328 :     index_sizes.txospender_index = std::min(total_cache * 5 / 100, args.GetBoolArg("-txospenderindex", DEFAULT_TXOSPENDERINDEX) ? MAX_TXOSPENDER_INDEX_CACHE : 0);
                   -  + ]
      79         [ -  + ]:         164 :     if (n_indexes > 0) {
      80         [ #  # ]:           0 :         uint64_t max_cache = std::min(total_cache * 5 / 100, MAX_FILTER_INDEX_CACHE);
      81                 :           0 :         index_sizes.filter_index = max_cache / n_indexes;
      82                 :           0 :         total_cache -= index_sizes.filter_index * n_indexes;
      83                 :             :     }
      84                 :         164 :     total_cache -= index_sizes.tx_index;
      85                 :         164 :     total_cache -= index_sizes.txospender_index;
      86                 :         164 :     return {index_sizes, kernel::CacheSizes{total_cache}};
      87                 :             : }
      88                 :             : 
      89                 :           1 : void LogOversizedDbCache(const ArgsManager& args) noexcept
      90                 :             : {
      91         [ +  - ]:           1 :     if (const auto total_ram{GetTotalRAM()}) {
      92                 :           1 :         const uint64_t db_cache{CalculateDbCacheBytes(args)};
      93   [ -  +  -  + ]:           1 :         if (ShouldWarnOversizedDbCache(db_cache, *total_ram)) {
      94                 :           0 :             InitWarning(bilingual_str{tfm::format(_("A %zu MiB dbcache may be too large for a system memory of only %zu MiB."),
      95                 :           0 :                         db_cache >> 20, *total_ram >> 20)});
      96                 :             :         }
      97                 :             :     }
      98                 :           1 : }
      99                 :             : } // namespace node
        

Generated by: LCOV version 2.0-1