diff --git a/.clippy.toml b/.clippy.toml index 12d47fd1eae7..7d445b272a1c 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -44,6 +44,18 @@ reason = """use `crate::utils::new_uuid_v4` instead.""" path = "tempfile::NamedTempFile::new" reason = """The temporary files created by this method are not persistable if the temporary directory lives on a different filesystem than the target directory. While it is valid in other contexts (if not persisting files), it was misused many times and so we are banning it. Consider using `tempfile::NamedTempFile::new_in` or `tempfile::NamedTempFile::Builder""" +[[disallowed-methods]] +path = "lru::LruCache::new" +reason = """Use SizeTrackingLruCache instead.""" + +[[disallowed-methods]] +path = "lru::LruCache::with_hasher" +reason = """Use SizeTrackingLruCache instead.""" + [[disallowed-methods]] path = "lru::LruCache::unbounded" -reason = """Avoid unbounded lru cache for potential memory leak""" +reason = """Avoid unbounded lru cache for potential memory leak, use SizeTrackingLruCache instead.""" + +[[disallowed-methods]] +path = "lru::LruCache::unbounded_with_hasher" +reason = """Avoid unbounded lru cache for potential memory leak, use SizeTrackingLruCache instead.""" diff --git a/interop-tests/tests/dhat_get_size_beacon_entry.rs b/interop-tests/tests/dhat_get_size_beacon_entry.rs index a03fef17b46f..4ef881842ca2 100644 --- a/interop-tests/tests/dhat_get_size_beacon_entry.rs +++ b/interop-tests/tests/dhat_get_size_beacon_entry.rs @@ -49,7 +49,7 @@ fn test_get_size_beacon_entry() { assert_eq!(v.capacity(), v.len()); dhat::assert_eq!( stats.curr_bytes, - size_of::() * v.capacity() + 60 + size_of::() * v.capacity() + inner_bytes ); dhat::assert_eq!(stats.curr_bytes, v.get_heap_size()); } diff --git a/src/beacon/drand.rs b/src/beacon/drand.rs index 1ad5942587cb..66bc59eee32d 100644 --- a/src/beacon/drand.rs +++ b/src/beacon/drand.rs @@ -262,7 +262,7 @@ impl DrandBeacon { fil_round_time: interval, fil_gen_time: genesis_ts, verified_beacons: SizeTrackingLruCache::new_with_default_metrics_registry( - "verified_beacons_cache".into(), + "verified_beacons".into(), NonZeroUsize::new(CACHE_SIZE).expect("Infallible"), ), } diff --git a/src/blocks/election_proof.rs b/src/blocks/election_proof.rs index 64b166ec22d4..75c8500468d8 100644 --- a/src/blocks/election_proof.rs +++ b/src/blocks/election_proof.rs @@ -5,6 +5,7 @@ use crate::blocks::VRFProof; use crate::shim::clock::BLOCKS_PER_EPOCH; use crate::utils::encoding::blake2b_256; use fvm_ipld_encoding::tuple::*; +use get_size2::GetSize; use num::{ BigInt, Integer, bigint::{ParseBigIntError, Sign}, @@ -134,7 +135,17 @@ impl Poiss { /// This is generated from hashing a partial ticket and using the hash to /// generate a value. #[derive( - Clone, Debug, PartialEq, PartialOrd, Eq, Default, Ord, Serialize_tuple, Deserialize_tuple, Hash, + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Default, + Ord, + Serialize_tuple, + Deserialize_tuple, + Hash, + GetSize, )] pub struct ElectionProof { pub win_count: i64, diff --git a/src/blocks/header.rs b/src/blocks/header.rs index ed70529f8a2a..3ebcf24711ad 100644 --- a/src/blocks/header.rs +++ b/src/blocks/header.rs @@ -14,12 +14,13 @@ use crate::{ address::Address, clock::ChainEpoch, crypto::Signature, econ::TokenAmount, sector::PoStProof, version::NetworkVersion, }, - utils::{encoding::blake2b_256, multihash::MultihashCode}, + utils::{encoding::blake2b_256, get_size::big_int_heap_size_helper, multihash::MultihashCode}, }; use cid::Cid; use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::CborStore as _; use fvm_ipld_encoding::tuple::*; +use get_size2::GetSize; use multihash_derive::MultihashDigest as _; use num::BigInt; use serde::{Deserialize, Serialize}; @@ -197,11 +198,46 @@ impl RawBlockHeader { } } +// The derive macro does not compile for some reason +impl GetSize for RawBlockHeader { + fn get_heap_size(&self) -> usize { + let Self { + miner_address, + ticket, + election_proof, + beacon_entries, + winning_post_proof, + parents, + weight, + epoch: _, + state_root: _, + message_receipts: _, + messages: _, + bls_aggregate, + timestamp: _, + signature, + fork_signal: _, + parent_base_fee, + } = self; + miner_address.get_heap_size() + + ticket.get_heap_size() + + election_proof.get_heap_size() + + beacon_entries.get_heap_size() + + winning_post_proof.get_heap_size() + + parents.get_heap_size() + + big_int_heap_size_helper(weight) + + bls_aggregate.get_heap_size() + + signature.get_heap_size() + + parent_base_fee.get_heap_size() + } +} + /// A [`RawBlockHeader`] which caches calls to [`RawBlockHeader::cid`] and [`RawBlockHeader::verify_signature_against`] #[cfg_attr(test, derive(Default))] -#[derive(Debug)] +#[derive(Debug, GetSize)] pub struct CachingBlockHeader { uncached: RawBlockHeader, + #[get_size(ignore)] cid: OnceLock, has_ever_been_verified_against_any_signature: AtomicBool, } diff --git a/src/blocks/ticket.rs b/src/blocks/ticket.rs index b9c88b78cc4c..86339446b084 100644 --- a/src/blocks/ticket.rs +++ b/src/blocks/ticket.rs @@ -3,12 +3,23 @@ use crate::blocks::VRFProof; use fvm_ipld_encoding::tuple::*; +use get_size2::GetSize; /// A Ticket is a marker of a tick of the blockchain's clock. It is the source /// of randomness for proofs of storage and leader election. It is generated /// by the miner of a block using a `VRF` and a `VDF`. #[derive( - Clone, Debug, PartialEq, Eq, Default, Serialize_tuple, Deserialize_tuple, Hash, PartialOrd, Ord, + Clone, + Debug, + PartialEq, + Eq, + Default, + Serialize_tuple, + Deserialize_tuple, + Hash, + PartialOrd, + Ord, + GetSize, )] pub struct Ticket { /// A proof output by running a `VRF` on the `VDFResult` of the parent diff --git a/src/blocks/tipset.rs b/src/blocks/tipset.rs index b8bc31de8597..b01964dfdfc0 100644 --- a/src/blocks/tipset.rs +++ b/src/blocks/tipset.rs @@ -11,7 +11,7 @@ use crate::{ cid_collections::SmallCidNonEmptyVec, networks::{calibnet, mainnet}, shim::clock::ChainEpoch, - utils::cid::CidCborExt, + utils::{cid::CidCborExt, get_size::nunny_vec_heap_size_helper}, }; use ahash::HashMap; use anyhow::Context as _; @@ -146,9 +146,10 @@ impl IntoIterator for TipsetKey { /// /// Represents non-null tipsets, see the documentation on [`crate::state_manager::apply_block_messages`] /// for more. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, GetSize)] pub struct Tipset { /// Sorted + #[get_size(size_fn = nunny_vec_heap_size_helper)] headers: NonEmpty, // key is lazily initialized via `fn key()`. key: OnceLock, diff --git a/src/blocks/vrf_proof.rs b/src/blocks/vrf_proof.rs index b5ce17f92f40..70c30c2f1160 100644 --- a/src/blocks/vrf_proof.rs +++ b/src/blocks/vrf_proof.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0, MIT use crate::utils::encoding::{blake2b_256, serde_byte_array}; +use get_size2::GetSize; use serde::{Deserialize, Serialize}; /// The output from running a VRF proof. @@ -25,3 +26,9 @@ impl VRFProof { blake2b_256(&self.0) } } + +impl GetSize for VRFProof { + fn get_heap_size(&self) -> usize { + self.0.get_heap_size() + } +} diff --git a/src/chain/store/chain_store.rs b/src/chain/store/chain_store.rs index 337d1160c451..34b7636ce3d5 100644 --- a/src/chain/store/chain_store.rs +++ b/src/chain/store/chain_store.rs @@ -6,7 +6,6 @@ use super::{ index::{ChainIndex, ResolveNullTipset}, tipset_tracker::TipsetTracker, }; -use crate::fil_cns; use crate::interpreter::{BlockMessages, VMTrace}; use crate::libp2p_bitswap::{BitswapStoreRead, BitswapStoreReadWrite}; use crate::message::{ChainMessage, Message as MessageTrait, SignedMessage}; @@ -27,6 +26,7 @@ use crate::{ chain_sync::metrics, db::{EthMappingsStore, EthMappingsStoreExt, IndicesStore, IndicesStoreExt}, }; +use crate::{fil_cns, utils::cache::SizeTrackingLruCache}; use ahash::{HashMap, HashMapExt, HashSet}; use anyhow::Context as _; use cid::Cid; @@ -34,8 +34,7 @@ use fil_actors_shared::fvm_ipld_amt::Amtv0 as Amt; use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::CborStore; use itertools::Itertools; -use lru::LruCache; -use parking_lot::{Mutex, RwLock}; +use parking_lot::Mutex; use serde::{Serialize, de::DeserializeOwned}; use std::{num::NonZeroUsize, sync::Arc}; use tokio::sync::broadcast::{self, Sender as Publisher}; @@ -554,27 +553,28 @@ where /// use-cases. This cache is intended to be used with a complementary function; /// [`messages_for_tipset_with_cache`]. pub struct MsgsInTipsetCache { - cache: RwLock>>, + cache: SizeTrackingLruCache>, } impl MsgsInTipsetCache { - pub fn new(cap: usize) -> anyhow::Result { - Ok(Self { - cache: RwLock::new(LruCache::new( - NonZeroUsize::new(cap).context("cache capacity must be greater than 0")?, - )), - }) + pub fn new(capacity: NonZeroUsize) -> Self { + Self { + cache: SizeTrackingLruCache::new_with_default_metrics_registry( + "msg_in_tipset".into(), + capacity, + ), + } } pub fn get(&self, key: &TipsetKey) -> Option> { - self.cache.write().get(key).cloned() + self.cache.get_cloned(key) } pub fn get_or_insert_with(&self, key: &TipsetKey, f: F) -> anyhow::Result> where F: FnOnce() -> anyhow::Result>, { - if self.cache.read().contains(key) { + if self.cache.contains(key) { Ok(self.get(key).expect("cache entry disappeared!")) } else { let v = f()?; @@ -584,21 +584,23 @@ impl MsgsInTipsetCache { } pub fn insert(&self, key: TipsetKey, value: Vec) { - self.cache.write().put(key, value); + self.cache.push(key, value); } /// Reads the intended cache size for this process from the environment or uses the default. - fn read_cache_size() -> usize { + fn read_cache_size() -> NonZeroUsize { + // Arbitrary number, can be adjusted + const DEFAULT: NonZeroUsize = NonZeroUsize::new(100).expect("infallible"); std::env::var("FOREST_MESSAGES_IN_TIPSET_CACHE_SIZE") .ok() .and_then(|s| s.parse().ok()) - .unwrap_or(100) // Arbitrary number, can be adjusted + .unwrap_or(DEFAULT) } } impl Default for MsgsInTipsetCache { fn default() -> Self { - Self::new(Self::read_cache_size()).expect("failed to create default cache") + Self::new(Self::read_cache_size()) } } @@ -796,7 +798,7 @@ mod tests { #[test] fn test_messages_in_tipset_cache() { - let cache = MsgsInTipsetCache::new(2).unwrap(); + let cache = MsgsInTipsetCache::new(2.try_into().unwrap()); let key1 = TipsetKey::from(nunny::vec![Cid::new_v1( DAG_CBOR, MultihashCode::Blake2b256.digest(&[1]) diff --git a/src/chain/store/index.rs b/src/chain/store/index.rs index fbe3f919a582..cd375b19e7ef 100644 --- a/src/chain/store/index.rs +++ b/src/chain/store/index.rs @@ -8,23 +8,21 @@ use crate::blocks::{Tipset, TipsetKey}; use crate::chain::Error; use crate::metrics; use crate::shim::clock::ChainEpoch; +use crate::utils::cache::SizeTrackingLruCache; use crate::utils::misc::env::is_env_truthy; use fvm_ipld_blockstore::Blockstore; use itertools::Itertools; -use lru::LruCache; use nonzero_ext::nonzero; -use parking_lot::Mutex; const DEFAULT_TIPSET_CACHE_SIZE: NonZeroUsize = nonzero!(131072_usize); -type TipsetCache = Mutex>>; +type TipsetCache = SizeTrackingLruCache>; /// Keeps look-back tipsets in cache at a given interval `skip_length` and can /// be used to look-back at the chain to retrieve an old tipset. pub struct ChainIndex { /// `Arc` reference tipset cache. ts_cache: TipsetCache, - /// `Blockstore` pointer needed to load tipsets from cold storage. pub db: DB, } @@ -40,25 +38,27 @@ pub enum ResolveNullTipset { impl ChainIndex { pub fn new(db: DB) -> Self { - let ts_cache = Mutex::new(LruCache::new(DEFAULT_TIPSET_CACHE_SIZE)); + let ts_cache = SizeTrackingLruCache::new_with_default_metrics_registry( + "tipset".into(), + DEFAULT_TIPSET_CACHE_SIZE, + ); Self { ts_cache, db } } /// Loads a tipset from memory given the tipset keys and cache. Semantically /// identical to [`Tipset::load`] but the result is cached. pub fn load_tipset(&self, tsk: &TipsetKey) -> Result>, Error> { - if !is_env_truthy("FOREST_TIPSET_CACHE_DISABLED") - && let Some(ts) = self.ts_cache.lock().get(tsk) - { + let cache_enabled = !is_env_truthy("FOREST_TIPSET_CACHE_DISABLED"); + if cache_enabled && let Some(ts) = self.ts_cache.get_cloned(tsk) { metrics::LRU_CACHE_HIT .get_or_create(&metrics::values::TIPSET) .inc(); - return Ok(Some(ts.clone())); + return Ok(Some(ts)); } let ts_opt = Tipset::load(&self.db, tsk)?.map(Arc::new); - if let Some(ts) = &ts_opt { - self.ts_cache.lock().put(tsk.clone(), ts.clone()); + if cache_enabled && let Some(ts) = &ts_opt { + self.ts_cache.push(tsk.clone(), ts.clone()); metrics::LRU_CACHE_MISS .get_or_create(&metrics::values::TIPSET) .inc(); diff --git a/src/chain_sync/bad_block_cache.rs b/src/chain_sync/bad_block_cache.rs index 8ddd7e373c79..c77a0dd3268c 100644 --- a/src/chain_sync/bad_block_cache.rs +++ b/src/chain_sync/bad_block_cache.rs @@ -25,10 +25,7 @@ impl Default for BadBlockCache { impl BadBlockCache { pub fn new(cap: NonZeroUsize) -> Self { Self { - cache: SizeTrackingLruCache::new_with_default_metrics_registry( - "bad_block_cache".into(), - cap, - ), + cache: SizeTrackingLruCache::new_with_default_metrics_registry("bad_block".into(), cap), } } diff --git a/src/db/car/mod.rs b/src/db/car/mod.rs index c7fd4e69df64..a8e8c8f5e49b 100644 --- a/src/db/car/mod.rs +++ b/src/db/car/mod.rs @@ -72,9 +72,7 @@ impl ZstdFrameCache { ZstdFrameCache { max_size, current_size: AtomicUsize::new(0), - lru: SizeTrackingLruCache::unbounded_with_default_metrics_registry( - "zstd_frame_cache".into(), - ), + lru: SizeTrackingLruCache::unbounded_with_default_metrics_registry("zstd_frame".into()), } } diff --git a/src/message/chain_message.rs b/src/message/chain_message.rs index b17d8aaefc82..bfa57e303a73 100644 --- a/src/message/chain_message.rs +++ b/src/message/chain_message.rs @@ -1,17 +1,17 @@ // Copyright 2019-2025 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT +use super::Message as MessageTrait; +use crate::message::signed_message::SignedMessage; use crate::shim::message::MethodNum; use crate::shim::{address::Address, econ::TokenAmount, message::Message}; use fvm_ipld_encoding::RawBytes; +use get_size2::GetSize; use serde::{Deserialize, Serialize}; -use super::Message as MessageTrait; -use crate::message::signed_message::SignedMessage; - /// `Enum` to encapsulate signed and unsigned messages. Useful when working with /// both types -#[derive(Clone, Debug, Serialize, Deserialize, Hash, Eq, PartialEq)] +#[derive(Clone, Debug, Serialize, Deserialize, Hash, Eq, PartialEq, GetSize)] #[serde(untagged)] pub enum ChainMessage { Unsigned(Message), diff --git a/src/message/signed_message.rs b/src/message/signed_message.rs index bcaec7f309ef..3e0b3f7624e5 100644 --- a/src/message/signed_message.rs +++ b/src/message/signed_message.rs @@ -12,10 +12,11 @@ use crate::shim::{ }; use fvm_ipld_encoding::tuple::*; use fvm_ipld_encoding::{RawBytes, to_vec}; +use get_size2::GetSize; /// Represents a wrapped message with signature bytes. #[cfg_attr(test, derive(derive_quickcheck_arbitrary::Arbitrary))] -#[derive(PartialEq, Clone, Debug, Serialize_tuple, Deserialize_tuple, Hash, Eq)] +#[derive(PartialEq, Clone, Debug, Serialize_tuple, Deserialize_tuple, Hash, Eq, GetSize)] pub struct SignedMessage { pub message: Message, pub signature: Signature, diff --git a/src/message_pool/msgpool/msg_pool.rs b/src/message_pool/msgpool/msg_pool.rs index da7f70c4f670..0c4c15a8bd30 100644 --- a/src/message_pool/msgpool/msg_pool.rs +++ b/src/message_pool/msgpool/msg_pool.rs @@ -476,11 +476,11 @@ where let pending = Arc::new(SyncRwLock::new(HashMap::new())); let tipset = Arc::new(SyncRwLock::new(api.get_heaviest_tipset())); let bls_sig_cache = Arc::new(SizeTrackingLruCache::new_with_default_metrics_registry( - "bls_sig_cache".into(), + "bls_sig".into(), BLS_SIG_CACHE_SIZE, )); let sig_val_cache = Arc::new(SizeTrackingLruCache::new_with_default_metrics_registry( - "sig_val_cache".into(), + "sig_val".into(), SIG_VAL_CACHE_SIZE, )); let local_msgs = Arc::new(SyncRwLock::new(HashSet::new())); diff --git a/src/shim/address.rs b/src/shim/address.rs index de4290638878..116894b0b28b 100644 --- a/src/shim/address.rs +++ b/src/shim/address.rs @@ -14,6 +14,7 @@ use fvm_shared3::address::Address as Address_v3; use fvm_shared4::address::Address as Address_v4; use fvm_shared4::address::Address as Address_latest; pub use fvm_shared4::address::{Error, Network, PAYLOAD_HASH_LEN, Payload, Protocol}; +use get_size2::GetSize; use integer_encoding::VarInt; use num_traits::FromPrimitive; use serde::{Deserialize, Serialize}; @@ -259,6 +260,12 @@ impl DerefMut for Address { } } +impl GetSize for Address { + fn get_heap_size(&self) -> usize { + 0 // all variants of the internal payload are stack-allocated + } +} + /// A Filecoin address is an identifier that refers to an actor in the Filecoin state. All actors /// (miner actors, the storage market actor, account actors) have an address. This address encodes /// information about the network to which an actor belongs, the specific type of address encoding, diff --git a/src/shim/econ.rs b/src/shim/econ.rs index b3b53818e59a..e4f5fbe3e5df 100644 --- a/src/shim/econ.rs +++ b/src/shim/econ.rs @@ -8,10 +8,12 @@ use std::{ }; use super::fvm_shared_latest::econ::TokenAmount as TokenAmount_latest; +use crate::utils::get_size::big_int_heap_size_helper; use fvm_shared2::econ::TokenAmount as TokenAmount_v2; use fvm_shared3::econ::TokenAmount as TokenAmount_v3; pub use fvm_shared3::{BLOCK_GAS_LIMIT, TOTAL_FILECOIN_BASE}; use fvm_shared4::econ::TokenAmount as TokenAmount_v4; +use get_size2::GetSize; use num_bigint::BigInt; use num_traits::Zero; use serde::{Deserialize, Serialize}; @@ -34,6 +36,12 @@ impl fmt::Debug for TokenAmount { } } +impl GetSize for TokenAmount { + fn get_heap_size(&self) -> usize { + big_int_heap_size_helper(self.0.atto()) + } +} + #[cfg(test)] impl quickcheck::Arbitrary for TokenAmount { fn arbitrary(g: &mut quickcheck::Gen) -> Self { diff --git a/src/shim/message.rs b/src/shim/message.rs index 4266f9aa7b60..47e3f97518d4 100644 --- a/src/shim/message.rs +++ b/src/shim/message.rs @@ -1,14 +1,13 @@ // Copyright 2019-2025 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use anyhow::anyhow; -use fvm_ipld_encoding::RawBytes; -use fvm_ipld_encoding::de::Deserializer; -use fvm_ipld_encoding::ser::Serializer; +use anyhow::anyhow; +use fvm_ipld_encoding::{RawBytes, de::Deserializer, ser::Serializer}; use fvm_shared2::message::Message as Message_v2; pub use fvm_shared3::METHOD_SEND; pub use fvm_shared3::message::Message as Message_v3; use fvm_shared4::message::Message as Message_v4; +use get_size2::GetSize; use serde::{Deserialize, Serialize}; use crate::shim::{address::Address, econ::TokenAmount}; @@ -16,7 +15,7 @@ use crate::shim::{address::Address, econ::TokenAmount}; /// Method number indicator for calling actor methods. pub type MethodNum = u64; -#[derive(Clone, Default, PartialEq, Eq, Debug, Hash)] +#[derive(Clone, Default, PartialEq, Eq, Debug, Hash, GetSize)] #[cfg_attr(test, derive(derive_quickcheck_arbitrary::Arbitrary))] pub struct Message { pub version: u64, @@ -28,12 +27,26 @@ pub struct Message { #[cfg_attr(test, arbitrary(gen( |g| RawBytes::new(Vec::arbitrary(g)) )))] + #[get_size(size_fn = raw_bytes_heap_size)] pub params: RawBytes, pub gas_limit: u64, pub gas_fee_cap: TokenAmount, pub gas_premium: TokenAmount, } +fn raw_bytes_heap_size(b: &RawBytes) -> usize { + // Note: this is a cheap but inaccurate estimation, + // the correct implementation should be `Vec.from(b.clone()).get_heap_size()`, + // or `b.bytes.get_heap_size()` if `bytes` is made public. + b.bytes().get_heap_size() +} + +// impl GetSize for Message{ +// fn get_heap_size(&self) -> usize { + +// } +// } + impl From for Message { fn from(other: Message_v4) -> Self { Self { diff --git a/src/shim/sector.rs b/src/shim/sector.rs index 908a3f0b46fd..af354efbb6d3 100644 --- a/src/shim/sector.rs +++ b/src/shim/sector.rs @@ -19,6 +19,7 @@ pub use fvm_shared4::sector::{ RegisteredSealProof as RegisteredSealProofV4, SectorInfo as SectorInfoV4, SectorSize as SectorSizeV4, }; +use get_size2::GetSize; use num_derive::FromPrimitive; use serde::{Deserialize, Serialize}; use std::hash::{Hash, Hasher}; @@ -377,6 +378,12 @@ impl From for PoStProof { } } +impl GetSize for PoStProof { + fn get_heap_size(&self) -> usize { + self.0.proof_bytes.get_heap_size() + } +} + pub fn convert_window_post_proof_v1_to_v1p1( rpp: RegisteredPoStProofV3, ) -> anyhow::Result { diff --git a/src/state_manager/cache.rs b/src/state_manager/cache.rs index c89b9a72140d..9c1a7c1609d3 100644 --- a/src/state_manager/cache.rs +++ b/src/state_manager/cache.rs @@ -45,7 +45,7 @@ impl TipsetStateCacheInner { fn cache_name() -> String { use convert_case::{Case, Casing as _}; format!( - "tipset_state_cache_{}", + "tipset_state_{}", crate::utils::misc::short_type_name::().to_case(Case::Snake) ) } diff --git a/src/state_migration/common/mod.rs b/src/state_migration/common/mod.rs index e98e7369d3b4..db105f6641e3 100644 --- a/src/state_migration/common/mod.rs +++ b/src/state_migration/common/mod.rs @@ -32,7 +32,7 @@ impl MigrationCache { pub fn new(size: NonZeroUsize) -> Self { Self { cache: Arc::new(SizeTrackingLruCache::new_with_default_metrics_registry( - "migration_cache".into(), + "migration".into(), size, )), } diff --git a/src/utils/cache/lru.rs b/src/utils/cache/lru.rs index c32623e0f478..05bf605e4130 100644 --- a/src/utils/cache/lru.rs +++ b/src/utils/cache/lru.rs @@ -124,6 +124,14 @@ where self.cache.write().push(k, v) } + pub fn contains(&self, k: &Q) -> bool + where + K: Borrow, + Q: Hash + Eq + ?Sized, + { + self.cache.read().contains(k) + } + pub fn get_cloned(&self, k: &Q) -> Option where K: Borrow, @@ -175,7 +183,7 @@ where g.set(self.size_in_bytes() as _); g }; - let size_metric_name = format!("{}_{}_size", self.cache_name, self.cache_id); + let size_metric_name = format!("cache_{}_{}_size", self.cache_name, self.cache_id); let size_metric_help = format!( "Size of LruCache {}_{} in bytes", self.cache_name, self.cache_id diff --git a/src/utils/get_size/mod.rs b/src/utils/get_size/mod.rs index e9d060bf7e2c..f0b9997be947 100644 --- a/src/utils/get_size/mod.rs +++ b/src/utils/get_size/mod.rs @@ -5,6 +5,7 @@ use cid::Cid; use derive_more::{From, Into}; // re-exports the trait pub use get_size2::GetSize; +use num_bigint::BigInt; #[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, From, Into)] pub struct CidWrapper(pub Cid); @@ -50,6 +51,12 @@ pub fn nunny_vec_heap_size_helper(v: &nunny::Vec) -> usize { impl_vec_alike_heap_size_helper!(v, T) } +// This is a rough estimation. Use `b.allocation_size()` +// once https://github.com/rust-num/num-bigint/pull/333 is accepted and released. +pub fn big_int_heap_size_helper(b: &BigInt) -> usize { + b.bits().div_ceil(8) as usize +} + #[cfg(test)] mod tests { use super::*;