History

feat: Add `gitoxide.core.defaultPackCacheMemoryLimit` to control memory limits. (#851)

Previously the 64 slot LRU cache didn't have any limit, now one is implemented that defaults to about 96MB.

Sebastian Thiel committed 3 years ago

Commit 020ff4e1 parent 969cc775 files · +33 −7Browse files

Unified · Split

5 files
  1. gix/src/config/cache/init.rs +7 −3
  2. gix/src/config/cache/util.rs +7 −2
  3. gix/src/config/mod.rs +2 −0
  4. gix/src/config/tree/sections/gitoxide.rs +11 −1
  5. gix/src/repository/init.rs +6 −1
gix/src/config/cache/init.rs+7−3
@@ -151,7 +151,7 @@ impl Cache { · 150 unmodified lines
151151 lenient_config,
152152 )?;
153153 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) =
155155 util::parse_object_caches(&config, lenient_config, filter_config_section)?;
156156 // NOTE: When adding a new initial cache, consider adjusting `reread_values_and_clear_caches()` as well.
157157 Ok(Cache {
@@ -159,6 +159,7 @@ impl Cache { · 1 unmodified line
159159 use_multi_pack_index,
160160 object_hash,
161161 object_kind_hint,
162+ static_pack_cache_limit_bytes,
162163 pack_cache_bytes,
163164 object_cache_bytes,
164165 reflog,
@@ -222,8 +223,11 @@ impl Cache { · 57 unmodified lines
222223 self.url_rewrite = Default::default();
223224 self.diff_renames = Default::default();
224225 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)?;
227231 #[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
228232 {
229233 self.url_scheme = Default::default();
gix/src/config/cache/util.rs+7−2
@@ -73,7 +73,12 @@ pub(crate) fn parse_object_caches( · 72 unmodified lines
7373 config: &gix_config::File<'static>,
7474 lenient: bool,
7575 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)?;
7782 let pack_cache_bytes = config
7883 .integer_filter_by_key("core.deltaBaseCacheLimit", &mut filter_config_section)
7984 .map(|res| Core::DELTA_BASE_CACHE_LIMIT.try_into_usize(res))
@@ -85,7 +90,7 @@ pub(crate) fn parse_object_caches( · 5 unmodified lines
8590 .transpose()
8691 .with_leniency(lenient)?
8792 .unwrap_or_default();
88− Ok((pack_cache_bytes, object_cache_bytes))
93+ Ok((static_pack_cache_limit, pack_cache_bytes, object_cache_bytes))
8994 }
9095
9196 pub(crate) fn parse_core_abbrev(
gix/src/config/mod.rs+2−0
@@ -470,6 +470,8 @@ pub(crate) struct Cache { · 469 unmodified lines
470470 pub(crate) pack_cache_bytes: Option<usize>,
471471 /// The amount of bytes to use for caching whole objects, or 0 to turn it off entirely.
472472 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>,
473475 /// The config section filter from the options used to initialize this instance. Keep these in sync!
474476 filter_config_section: fn(&gix_config::file::Metadata) -> bool,
475477 /// The object kind to pick if a prefix is ambiguous.
gix/src/config/tree/sections/gitoxide.rs+11−1
@@ -67,6 +67,11 @@ mod subsections { · 66 unmodified lines
6767 pub struct Core;
6868
6969 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+ );
7075 /// The `gitoxide.core.useNsec` key.
7176 pub const USE_NSEC: keys::Boolean = keys::Boolean::new_boolean("useNsec", &Gitoxide::CORE)
7277 .with_note("A runtime version of the USE_NSEC build flag.");
@@ -89,7 +94,12 @@ mod subsections { · 16 unmodified lines
8994 }
9095
9196 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+ ]
93103 }
94104
95105 fn parent(&self) -> Option<&dyn Section> {
gix/src/repository/init.rs+6−1
@@ -37,7 +37,12 @@ fn setup_objects(mut objects: crate::OdbHandle, config: &crate::config::Cache) - · 36 unmodified lines
3737 #[cfg(feature = "max-performance-safe")]
3838 {
3939 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+ },
4146 Some(0) => objects.unset_pack_cache(),
4247 Some(bytes) => objects.set_pack_cache(move || -> Box<gix_odb::cache::PackCache> {
4348 Box::new(gix_pack::cache::lru::MemoryCappedHashmap::new(bytes))