caches.cpp raw
1 // Copyright (c) 2021-2022 The Limenka 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_ram.h>
9 #include <index/txindex.h>
10 #include <kernel/caches.h>
11 #include <logging.h>
12 #include <node/dbcache.h>
13 #include <node/interface_ui.h>
14 #include <tinyformat.h>
15 #include <util/byte_units.h>
16
17 #include <algorithm>
18 #include <string>
19
20 // Unlike for the UTXO database, for the txindex scenario the leveldb cache make
21 // a meaningful difference: https://github.com/limenka/limenka/pull/8273#issuecomment-229601991
22 //! Max memory allocated to tx index DB specific cache in bytes.
23 static constexpr size_t MAX_TX_INDEX_CACHE{1024_MiB};
24 //! Max memory allocated to all block filter index caches combined in bytes.
25 static constexpr size_t MAX_FILTER_INDEX_CACHE{1024_MiB};
26
27 namespace node {
28 size_t CalculateDbCacheBytes(const ArgsManager& args)
29 {
30 if (auto db_cache{args.GetIntArg("-dbcache")}) {
31 if (*db_cache < 0) db_cache = 0;
32 uint64_t db_cache_bytes = SaturatingLeftShift<uint64_t>(*db_cache, 20);
33 return std::max<size_t>(MIN_DBCACHE_BYTES, std::min(db_cache_bytes, MAX_DBCACHE_BYTES));
34 }
35 return GetDefaultDBCache();
36 }
37
38 CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes)
39 {
40 size_t total_cache{CalculateDbCacheBytes(args)};
41
42 IndexCacheSizes index_sizes;
43 index_sizes.tx_index = std::min(total_cache / 8, args.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? MAX_TX_INDEX_CACHE : 0);
44 total_cache -= index_sizes.tx_index;
45 if (n_indexes > 0) {
46 size_t max_cache = std::min(total_cache / 8, MAX_FILTER_INDEX_CACHE);
47 index_sizes.filter_index = max_cache / n_indexes;
48 total_cache -= index_sizes.filter_index * n_indexes;
49 }
50 return {index_sizes, kernel::CacheSizes{total_cache}};
51 }
52
53 void LogOversizedDbCache(const ArgsManager& args) noexcept
54 {
55 if (const auto total_ram{TryGetTotalRam()}) {
56 const size_t db_cache{CalculateDbCacheBytes(args)};
57 if (ShouldWarnOversizedDbCache(db_cache, *total_ram)) {
58 InitWarning(bilingual_str{tfm::format(_("A %s MiB dbcache may be too large for a system with only %s MiB of memory."),
59 db_cache / 1_MiB, *total_ram / 1_MiB)});
60 }
61 }
62 }
63
64 void LogAutoDbCacheSettings() noexcept
65 {
66 LogInfo("Automatically selected -dbcache=%s MiB based on %s system memory of %s MiB.",
67 GetDefaultDBCache(GetTotalRam()) / 1_MiB,
68 TryGetTotalRam() ? "detected" : "assumed",
69 GetTotalRam() / 1_MiB);
70 }
71 } // namespace node
72