#[cfg(unix)]
pub(crate) fn open_file_limit() -> usize {
unsafe {
let mut limits = std::mem::zeroed::<libc::rlimit>();
if libc::getrlimit(libc::RLIMIT_NOFILE, &mut limits) != 0 {
return 1024;
}
usize::try_from(limits.rlim_cur).unwrap_or(usize::MAX)
}
}
#[cfg(not(unix))]
pub(crate) fn open_file_limit() -> usize {
1024
}
#[cfg(unix)]
pub fn raise_open_file_limit() -> (usize, usize) {
unsafe {
let mut limits = std::mem::zeroed::<libc::rlimit>();
if libc::getrlimit(libc::RLIMIT_NOFILE, &mut limits) != 0 {
return (0, 0);
}
let before = usize::try_from(limits.rlim_cur).unwrap_or(usize::MAX);
let ceiling = darwin_open_max().unwrap_or(limits.rlim_max);
let target = limits.rlim_max.min(ceiling);
if target <= limits.rlim_cur {
return (before, before);
}
let raised = libc::rlimit {
rlim_cur: target,
rlim_max: limits.rlim_max,
};
if libc::setrlimit(libc::RLIMIT_NOFILE, &raised) != 0 {
return (before, before);
}
(before, usize::try_from(target).unwrap_or(usize::MAX))
}
}
#[cfg(target_vendor = "apple")]
fn darwin_open_max() -> Option<libc::rlim_t> {
let value = unsafe { libc::sysconf(libc::_SC_OPEN_MAX) };
(value > 0).then_some(value as libc::rlim_t)
}
#[cfg(not(target_vendor = "apple"))]
fn darwin_open_max() -> Option<u64> {
None
}
#[cfg(not(unix))]
pub fn raise_open_file_limit() -> (usize, usize) {
(0, 0)
}
#[cfg(target_os = "linux")]
pub(crate) fn current_open_file_count() -> usize {
std::fs::read_dir("/proc/self/fd")
.map(|entries| entries.count())
.unwrap_or(3)
}
#[cfg(not(target_os = "linux"))]
pub(crate) fn current_open_file_count() -> usize {
3
}
pub fn trim_process_allocations() {
#[cfg(all(target_os = "linux", target_env = "gnu"))]
unsafe {
let _ = libc::malloc_trim(0);
}
}
pub fn report_process_memory(label: &str) {
if std::env::var_os("CF3_RS_PROFILE_RSS").is_none() {
return;
}
let Ok(status) = std::fs::read_to_string("/proc/self/status") else {
return;
};
let mut rss_kib = None;
let mut hwm_kib = None;
for line in status.lines() {
if let Some(value) = line.strip_prefix("VmRSS:") {
rss_kib = parse_status_kib(value);
} else if let Some(value) = line.strip_prefix("VmHWM:") {
hwm_kib = parse_status_kib(value);
}
}
if let (Some(rss), Some(hwm)) = (rss_kib, hwm_kib) {
eprintln!("cuttlefish: rss {label}: current {rss} KiB, peak {hwm} KiB");
}
}
fn parse_status_kib(value: &str) -> Option<u64> {
value
.split_whitespace()
.next()
.and_then(|value| value.parse::<u64>().ok())
}
#[cfg(test)]
mod tests {
use super::parse_status_kib;
#[test]
fn parses_linux_status_values() {
assert_eq!(parse_status_kib(" 12345 kB"), Some(12_345));
assert_eq!(parse_status_kib(" unavailable"), None);
}
}