1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
/// How much RAM is the application using?
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MemoryUse {
/// Bytes allocated by the application according to operating system.
///
/// Resident Set Size (RSS) on Linux, Android, Mac, iOS.
/// Working Set on Windows.
///
/// `None` if unknown.
pub resident: Option<i64>,
/// Bytes used by the application according to our own memory allocator's accounting.
///
/// This can be smaller than [`Self::resident`] because our memory allocator may not
/// return all the memory we free to the OS.
///
/// `None` if [`crate::AccountingAllocator`] is not used.
pub counted: Option<i64>,
}
impl MemoryUse {
/// Read the current memory of the running application.
#[inline]
pub fn capture() -> Self {
Self {
resident: bytes_resident(),
counted: crate::accounting_allocator::global_allocs().map(|c| c.size as _),
}
}
/// Bytes used by the application according to our best estimate.
///
/// This is either [`Self::counted`] if it's available, otherwise fallbacks to
/// [`Self::resident`] if that's available, otherwise `None`.
#[inline]
pub fn used(&self) -> Option<i64> {
self.counted.or(self.resident)
}
}
impl std::ops::Mul<f32> for MemoryUse {
type Output = Self;
fn mul(self, factor: f32) -> Self::Output {
Self {
resident: self.resident.map(|v| (v as f32 * factor) as i64),
counted: self.counted.map(|v| (v as f32 * factor) as i64),
}
}
}
impl std::ops::Sub for MemoryUse {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
fn sub(a: Option<i64>, b: Option<i64>) -> Option<i64> {
Some(a? - b?)
}
MemoryUse {
resident: sub(self.resident, rhs.resident),
counted: sub(self.counted, rhs.counted),
}
}
}
// ----------------------------------------------------------------------------
/// According to the OS. This is what matters.
///
/// Resident Set Size (RSS) on Linux, Android, Mac, iOS.
/// Working Set on Windows.
#[cfg(not(target_arch = "wasm32"))]
fn bytes_resident() -> Option<i64> {
memory_stats::memory_stats().map(|usage| usage.physical_mem as i64)
}
#[cfg(target_arch = "wasm32")]
fn bytes_resident() -> Option<i64> {
// blocked on https://github.com/Arc-blroth/memory-stats/issues/1
None
}