use std::sync::LazyLock;
use tracing::info;
use crate::utils::ByteSize;
use crate::utils::configuration_utils::parse_bool_value;
const ROUND_TO: u64 = 8_000_000;
#[derive(Debug, Clone, Copy)]
pub struct UsableMemory {
pub host_total: Option<u64>,
pub cgroup_limit: Option<u64>,
}
impl UsableMemory {
pub fn usable(&self) -> Option<u64> {
match (self.host_total, self.cgroup_limit) {
(Some(host), Some(cgroup)) => Some(host.min(cgroup)),
(host, cgroup) => host.or(cgroup),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DownloadBufferDefaults {
pub size: ByteSize,
pub perfile: ByteSize,
pub limit: ByteSize,
}
pub const STATIC_DEFAULTS: DownloadBufferDefaults = DownloadBufferDefaults {
size: ByteSize::new(2_000_000_000),
perfile: ByteSize::new(512_000_000),
limit: ByteSize::new(8_000_000_000),
};
pub const STATIC_HP_DEFAULTS: DownloadBufferDefaults = DownloadBufferDefaults {
size: ByteSize::new(16_000_000_000),
perfile: ByteSize::new(2_000_000_000),
limit: ByteSize::new(64_000_000_000),
};
struct Fractions {
size_divisor: u64,
perfile_divisor: u64,
limit_divisor: u64,
}
const STANDARD_FRACTIONS: Fractions = Fractions {
size_divisor: 16,
perfile_divisor: 64,
limit_divisor: 4,
};
const HIGH_PERFORMANCE_FRACTIONS: Fractions = Fractions {
size_divisor: 8,
perfile_divisor: 32,
limit_divisor: 2,
};
const SIZE_FLOOR: u64 = 64_000_000;
const SIZE_CEILING: u64 = STATIC_HP_DEFAULTS.size.as_u64();
const PERFILE_FLOOR: u64 = 16_000_000;
const PERFILE_CEILING: u64 = STATIC_HP_DEFAULTS.perfile.as_u64();
const LIMIT_FLOOR: u64 = 264_000_000;
const LIMIT_CEILING: u64 = STATIC_HP_DEFAULTS.limit.as_u64();
fn derive_download_buffer_defaults(usable: u64, fractions: &Fractions) -> DownloadBufferDefaults {
let apply = |divisor: u64, floor: u64, ceiling: u64| -> u64 {
let value = (usable / divisor).clamp(floor, ceiling);
(value / ROUND_TO) * ROUND_TO
};
DownloadBufferDefaults {
size: ByteSize::new(apply(fractions.size_divisor, SIZE_FLOOR, SIZE_CEILING)),
perfile: ByteSize::new(apply(fractions.perfile_divisor, PERFILE_FLOOR, PERFILE_CEILING)),
limit: ByteSize::new(apply(fractions.limit_divisor, LIMIT_FLOOR, LIMIT_CEILING)),
}
}
#[cfg(not(target_family = "wasm"))]
fn probe_usable_memory() -> UsableMemory {
use sysinfo::{MemoryRefreshKind, ProcessRefreshKind, ProcessesToUpdate, RefreshKind, System};
let mut system =
System::new_with_specifics(RefreshKind::nothing().with_memory(MemoryRefreshKind::nothing().with_ram()));
let host_total = match system.total_memory() {
0 => None,
total => Some(total),
};
let cgroup_limit = sysinfo::get_current_pid().ok().and_then(|pid| {
system.refresh_processes_specifics(ProcessesToUpdate::Some(&[pid]), false, ProcessRefreshKind::nothing());
let limits = system.process(pid)?.cgroup_limits()?;
Some(limits.total_memory).filter(|&limit| host_total.is_none_or(|host| limit < host))
});
UsableMemory {
host_total,
cgroup_limit,
}
}
#[cfg(target_family = "wasm")]
fn probe_usable_memory() -> UsableMemory {
UsableMemory {
host_total: None,
cgroup_limit: None,
}
}
pub static USABLE_MEMORY: LazyLock<UsableMemory> = LazyLock::new(probe_usable_memory);
struct DerivedDefaults {
standard: DownloadBufferDefaults,
high_performance: DownloadBufferDefaults,
}
static DERIVED_DEFAULTS: LazyLock<DerivedDefaults> = LazyLock::new(|| match USABLE_MEMORY.usable() {
Some(usable) => DerivedDefaults {
standard: derive_download_buffer_defaults(usable, &STANDARD_FRACTIONS),
high_performance: derive_download_buffer_defaults(usable, &HIGH_PERFORMANCE_FRACTIONS),
},
None => DerivedDefaults {
standard: STATIC_DEFAULTS,
high_performance: STATIC_HP_DEFAULTS,
},
});
pub fn log_derived_defaults() {
if !memory_derived_defaults_enabled() {
info!(
"Memory-derived download buffer defaults disabled via HF_XET_DISABLE_MEMORY_DERIVED_DOWNLOAD_BUFFERS; using static defaults"
);
return;
}
let memory = &*USABLE_MEMORY;
match memory.usable() {
Some(usable) => {
let standard = DERIVED_DEFAULTS.standard;
info!(
host_total = ?memory.host_total,
cgroup_limit = ?memory.cgroup_limit,
usable,
"Derived download buffer defaults from system memory: size={} perfile={} limit={}",
standard.size,
standard.perfile,
standard.limit
);
},
None => {
info!("System memory could not be determined; using static download buffer defaults");
},
}
}
fn memory_derived_defaults_enabled() -> bool {
match std::env::var("HF_XET_DISABLE_MEMORY_DERIVED_DOWNLOAD_BUFFERS") {
Ok(value) => !parse_bool_value(&value).unwrap_or(false),
Err(_) => true,
}
}
pub fn default_download_buffer_sizes() -> DownloadBufferDefaults {
if memory_derived_defaults_enabled() {
DERIVED_DEFAULTS.standard
} else {
STATIC_DEFAULTS
}
}
pub fn high_performance_download_buffer_sizes() -> DownloadBufferDefaults {
if memory_derived_defaults_enabled() {
DERIVED_DEFAULTS.high_performance
} else {
STATIC_HP_DEFAULTS
}
}
#[cfg(test)]
mod tests {
use super::*;
fn triple(d: DownloadBufferDefaults) -> (u64, u64, u64) {
(d.size.as_u64(), d.perfile.as_u64(), d.limit.as_u64())
}
#[test]
fn test_usable_memory_min() {
let mem = |h, c| UsableMemory {
host_total: h,
cgroup_limit: c,
};
assert_eq!(mem(Some(10), Some(4)).usable(), Some(4));
assert_eq!(mem(Some(4), Some(10)).usable(), Some(4));
assert_eq!(mem(Some(10), None).usable(), Some(10));
assert_eq!(mem(None, Some(4)).usable(), Some(4));
assert_eq!(mem(None, None).usable(), None);
}
#[test]
fn test_standard_derivation_table() {
let cases: &[(u64, (u64, u64, u64))] = &[
(268_435_456, (64_000_000, 16_000_000, 264_000_000)), (512_000_000, (64_000_000, 16_000_000, 264_000_000)), (1_073_741_824, (64_000_000, 16_000_000, 264_000_000)), (2_000_000_000, (120_000_000, 24_000_000, 496_000_000)),
(8_000_000_000, (496_000_000, 120_000_000, 2_000_000_000)),
(16_000_000_000, (1_000_000_000, 248_000_000, 4_000_000_000)),
(32_000_000_000, (2_000_000_000, 496_000_000, 8_000_000_000)), (64_000_000_000, (4_000_000_000, 1_000_000_000, 16_000_000_000)),
(128_000_000_000, (8_000_000_000, 2_000_000_000, 32_000_000_000)),
(256_000_000_000, (16_000_000_000, 2_000_000_000, 64_000_000_000)), (2_000_000_000_000, (16_000_000_000, 2_000_000_000, 64_000_000_000)), ];
for &(usable, expected) in cases {
assert_eq!(
triple(derive_download_buffer_defaults(usable, &STANDARD_FRACTIONS)),
expected,
"standard, usable={usable}"
);
}
assert_eq!(derive_download_buffer_defaults(2_000_000_000_000, &STANDARD_FRACTIONS), STATIC_HP_DEFAULTS);
}
#[test]
fn test_high_performance_derivation_table() {
let cases: &[(u64, (u64, u64, u64))] = &[
(268_435_456, (64_000_000, 16_000_000, 264_000_000)), (512_000_000, (64_000_000, 16_000_000, 264_000_000)), (8_000_000_000, (1_000_000_000, 248_000_000, 4_000_000_000)),
(16_000_000_000, (2_000_000_000, 496_000_000, 8_000_000_000)),
(32_000_000_000, (4_000_000_000, 1_000_000_000, 16_000_000_000)),
(64_000_000_000, (8_000_000_000, 2_000_000_000, 32_000_000_000)),
(128_000_000_000, (16_000_000_000, 2_000_000_000, 64_000_000_000)),
(256_000_000_000, (16_000_000_000, 2_000_000_000, 64_000_000_000)),
(2_000_000_000_000, (16_000_000_000, 2_000_000_000, 64_000_000_000)),
];
for &(usable, expected) in cases {
assert_eq!(
triple(derive_download_buffer_defaults(usable, &HIGH_PERFORMANCE_FRACTIONS)),
expected,
"hp, usable={usable}"
);
}
}
#[test]
fn test_derivation_invariants_across_sweep() {
for fractions in [&STANDARD_FRACTIONS, &HIGH_PERFORMANCE_FRACTIONS] {
let mut prev: Option<(u64, u64, u64)> = None;
let mut usable: u64 = 268_435_456;
while usable < 2_500_000_000_000 {
let (size, perfile, limit) = triple(derive_download_buffer_defaults(usable, fractions));
assert!(
size + 8 * perfile <= limit,
"invariant violated at usable={usable}: {size} + 8*{perfile} > {limit}"
);
for v in [size, perfile, limit] {
assert_eq!(v % ROUND_TO, 0, "not a multiple of {ROUND_TO} at usable={usable}");
}
assert!((SIZE_FLOOR..=SIZE_CEILING).contains(&size));
assert!((PERFILE_FLOOR..=PERFILE_CEILING).contains(&perfile));
assert!((LIMIT_FLOOR..=LIMIT_CEILING).contains(&limit));
if let Some((ps, pp, pl)) = prev {
assert!(size >= ps && perfile >= pp && limit >= pl, "not monotonic at usable={usable}");
}
prev = Some((size, perfile, limit));
usable = usable * 5 / 4;
}
}
}
#[test]
fn test_probe_reports_host_total() {
assert!(USABLE_MEMORY.host_total.is_some_and(|t| t > 0), "host total should be detectable on test hosts");
}
#[test]
#[serial_test::serial(config_env)]
fn test_kill_switch_restores_static_defaults() {
let _g = crate::utils::EnvVarGuard::set("HF_XET_DISABLE_MEMORY_DERIVED_DOWNLOAD_BUFFERS", "1");
assert_eq!(default_download_buffer_sizes(), STATIC_DEFAULTS);
assert_eq!(high_performance_download_buffer_sizes(), STATIC_HP_DEFAULTS);
}
#[test]
#[serial_test::serial(config_env)]
fn test_derived_defaults_match_probe() {
let _g = crate::utils::EnvVarGuard::set("HF_XET_DISABLE_MEMORY_DERIVED_DOWNLOAD_BUFFERS", "0");
let expected_std = match USABLE_MEMORY.usable() {
Some(u) => derive_download_buffer_defaults(u, &STANDARD_FRACTIONS),
None => STATIC_DEFAULTS,
};
let expected_hp = match USABLE_MEMORY.usable() {
Some(u) => derive_download_buffer_defaults(u, &HIGH_PERFORMANCE_FRACTIONS),
None => STATIC_HP_DEFAULTS,
};
assert_eq!(default_download_buffer_sizes(), expected_std);
assert_eq!(high_performance_download_buffer_sizes(), expected_hp);
}
}