Previously the 64 slot LRU cache didn't have any limit, now one is implemented that defaults to about 96MB.
Unified · Split
| @@ -151,7 +151,7 @@ impl Cache { · 150 unmodified lines | ||
| 151 | 151 | lenient_config, |
| 152 | 152 | )?; |
| 153 | 153 | let object_kind_hint = util::disambiguate_hint(&config, lenient_config)?; |
| 154 | − let (pack_cache_bytes, object_cache_bytes) = | |
| 154 | + let (static_pack_cache_limit_bytes, pack_cache_bytes, object_cache_bytes) = | |
| 155 | 155 | util::parse_object_caches(&config, lenient_config, filter_config_section)?; |
| 156 | 156 | // NOTE: When adding a new initial cache, consider adjusting `reread_values_and_clear_caches()` as well. |
| 157 | 157 | Ok(Cache { |
| @@ -159,6 +159,7 @@ impl Cache { · 1 unmodified line | ||
| 159 | 159 | use_multi_pack_index, |
| 160 | 160 | object_hash, |
| 161 | 161 | object_kind_hint, |
| 162 | + static_pack_cache_limit_bytes, | |
| 162 | 163 | pack_cache_bytes, |
| 163 | 164 | object_cache_bytes, |
| 164 | 165 | reflog, |
| @@ -222,8 +223,11 @@ impl Cache { · 57 unmodified lines | ||
| 222 | 223 | self.url_rewrite = Default::default(); |
| 223 | 224 | self.diff_renames = Default::default(); |
| 224 | 225 | self.diff_algorithm = Default::default(); |
| 225 | − (self.pack_cache_bytes, self.object_cache_bytes) = | |
| 226 | − util::parse_object_caches(config, self.lenient_config, self.filter_config_section)?; | |
| 226 | + ( | |
| 227 | + self.static_pack_cache_limit_bytes, | |
| 228 | + self.pack_cache_bytes, | |
| 229 | + self.object_cache_bytes, | |
| 230 | + ) = util::parse_object_caches(config, self.lenient_config, self.filter_config_section)?; | |
| 227 | 231 | #[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))] |
| 228 | 232 | { |
| 229 | 233 | self.url_scheme = Default::default(); |
| @@ -73,7 +73,12 @@ pub(crate) fn parse_object_caches( · 72 unmodified lines | ||
| 73 | 73 | config: &gix_config::File<'static>, |
| 74 | 74 | lenient: bool, |
| 75 | 75 | mut filter_config_section: fn(&gix_config::file::Metadata) -> bool, |
| 76 | −) -> Result<(Option<usize>, usize), Error> { | |
| 76 | +) -> Result<(Option<usize>, Option<usize>, usize), Error> { | |
| 77 | + let static_pack_cache_limit = config | |
| 78 | + .integer_filter_by_key("core.deltaBaseCacheLimit", &mut filter_config_section) | |
| 79 | + .map(|res| gitoxide::Core::DEFAULT_PACK_CACHE_MEMORY_LIMIT.try_into_usize(res)) | |
| 80 | + .transpose() | |
| 81 | + .with_leniency(lenient)?; | |
| 77 | 82 | let pack_cache_bytes = config |
| 78 | 83 | .integer_filter_by_key("core.deltaBaseCacheLimit", &mut filter_config_section) |
| 79 | 84 | .map(|res| Core::DELTA_BASE_CACHE_LIMIT.try_into_usize(res)) |
| @@ -85,7 +90,7 @@ pub(crate) fn parse_object_caches( · 5 unmodified lines | ||
| 85 | 90 | .transpose() |
| 86 | 91 | .with_leniency(lenient)? |
| 87 | 92 | .unwrap_or_default(); |
| 88 | − Ok((pack_cache_bytes, object_cache_bytes)) | |
| 93 | + Ok((static_pack_cache_limit, pack_cache_bytes, object_cache_bytes)) | |
| 89 | 94 | } |
| 90 | 95 | |
| 91 | 96 | pub(crate) fn parse_core_abbrev( |
| @@ -470,6 +470,8 @@ pub(crate) struct Cache { · 469 unmodified lines | ||
| 470 | 470 | pub(crate) pack_cache_bytes: Option<usize>, |
| 471 | 471 | /// The amount of bytes to use for caching whole objects, or 0 to turn it off entirely. |
| 472 | 472 | pub(crate) object_cache_bytes: usize, |
| 473 | + /// The amount of bytes we can hold in our static LRU cache. Otherwise, go with the defaults. | |
| 474 | + pub(crate) static_pack_cache_limit_bytes: Option<usize>, | |
| 473 | 475 | /// The config section filter from the options used to initialize this instance. Keep these in sync! |
| 474 | 476 | filter_config_section: fn(&gix_config::file::Metadata) -> bool, |
| 475 | 477 | /// The object kind to pick if a prefix is ambiguous. |
| @@ -67,6 +67,11 @@ mod subsections { · 66 unmodified lines | ||
| 67 | 67 | pub struct Core; |
| 68 | 68 | |
| 69 | 69 | impl Core { |
| 70 | + /// The `gitoxide.core.defaultPackCacheMemoryLimit` key. | |
| 71 | + pub const DEFAULT_PACK_CACHE_MEMORY_LIMIT: keys::UnsignedInteger = | |
| 72 | + keys::UnsignedInteger::new_unsigned_integer("defaultPackCacheMemoryLimit", &Gitoxide::CORE).with_note( | |
| 73 | + "If unset, we default to 96MB memory cap for the default 64 slot LRU cache for object deltas.", | |
| 74 | + ); | |
| 70 | 75 | /// The `gitoxide.core.useNsec` key. |
| 71 | 76 | pub const USE_NSEC: keys::Boolean = keys::Boolean::new_boolean("useNsec", &Gitoxide::CORE) |
| 72 | 77 | .with_note("A runtime version of the USE_NSEC build flag."); |
| @@ -89,7 +94,12 @@ mod subsections { · 16 unmodified lines | ||
| 89 | 94 | } |
| 90 | 95 | |
| 91 | 96 | fn keys(&self) -> &[&dyn Key] { |
| 92 | − &[&Self::USE_NSEC, &Self::USE_STDEV, &Self::SHALLOW_FILE] | |
| 97 | + &[ | |
| 98 | + &Self::DEFAULT_PACK_CACHE_MEMORY_LIMIT, | |
| 99 | + &Self::USE_NSEC, | |
| 100 | + &Self::USE_STDEV, | |
| 101 | + &Self::SHALLOW_FILE, | |
| 102 | + ] | |
| 93 | 103 | } |
| 94 | 104 | |
| 95 | 105 | fn parent(&self) -> Option<&dyn Section> { |
| @@ -37,7 +37,12 @@ fn setup_objects(mut objects: crate::OdbHandle, config: &crate::config::Cache) - · 36 unmodified lines | ||
| 37 | 37 | #[cfg(feature = "max-performance-safe")] |
| 38 | 38 | { |
| 39 | 39 | match config.pack_cache_bytes { |
| 40 | − None => objects.set_pack_cache(|| Box::<gix_pack::cache::lru::StaticLinkedList<64>>::default()), | |
| 40 | + None => match config.static_pack_cache_limit_bytes { | |
| 41 | + None => objects.set_pack_cache(|| Box::<gix_pack::cache::lru::StaticLinkedList<64>>::default()), | |
| 42 | + Some(limit) => { | |
| 43 | + objects.set_pack_cache(move || Box::new(gix_pack::cache::lru::StaticLinkedList::<64>::new(limit))) | |
| 44 | + } | |
| 45 | + }, | |
| 41 | 46 | Some(0) => objects.unset_pack_cache(), |
| 42 | 47 | Some(bytes) => objects.set_pack_cache(move || -> Box<gix_odb::cache::PackCache> { |
| 43 | 48 | Box::new(gix_pack::cache::lru::MemoryCappedHashmap::new(bytes)) |