pub struct MemInfo {Show 27 fields
pub total: u64,
pub available: u64,
pub used: u64,
pub free: u64,
pub classes: Vec<MemoryClass>,
pub buffers: u64,
pub cached: u64,
pub sreclaimable: u64,
pub shmem: u64,
pub wired: u64,
pub compressed: u64,
pub active: u64,
pub inactive: u64,
pub purgeable: u64,
pub speculative: u64,
pub zswap: u64,
pub zswapped: u64,
pub zswap_max: u64,
pub huge_pages_total: u64,
pub huge_pages_free: u64,
pub huge_pages_rsvd: u64,
pub huge_pages_surplus: u64,
pub huge_page_size: u64,
pub laundry: u64,
pub file_cache: u64,
pub managed_pages: u64,
pub internal: u64,
}Expand description
The memory breakdown a platform reports.
Every backend fills in total and classes, then calls
finish_linux or finish_darwin exactly once to derive used/available.
The classes are the authority on what counts as used: finish_* only sums
the flags. This matters because the platforms genuinely disagree, and every
attempt to hardcode a formula produced a number that contradicted either the
class sum or the operating system (docs/PORTABILITY.md).
Fields§
§total: u64§available: u64Memory that can be handed to a new allocation, including reclaimable
cache. Derived by the finish_* methods.
used: u64Derived: the sum of every class flagged counts_as_used.
free: u64Free pages. Not a class of its own on macOS, where free is tiny and the
page cache holds the slack.
classes: Vec<MemoryClass>The ordered class list. Order is the bar-segment order.
buffers: u64§cached: u64§sreclaimable: u64§shmem: u64§wired: u64§compressed: u64§active: u64§inactive: u64§purgeable: u64§speculative: u64§zswap: u64Bytes currently held in the zswap pool (Meminfo: Zswap).
Not part of the memory bar: zswap pages are anonymous pages that have
been compressed, so they are already counted in used. Reporting them
again would double-count. They get their own meter instead.
zswapped: u64Bytes swapped out to zswap over the machine’s lifetime (Zswapped).
zswap_max: u64The zswap pool’s ceiling, from
/sys/module/zswap/parameters/max_pool_percent times physical memory.
0 when the parameter is unreadable.
huge_pages_total: u64Huge page counters, in pages (Meminfo: HugePages_*).
huge_pages_free: u64§huge_pages_rsvd: u64§huge_pages_surplus: u64§huge_page_size: u64Bytes per huge page (Hugepagesize), 0 when huge pages are disabled.
laundry: u64Pages that are dirty and queued for writeback (v_laundry_count).
FreeBSD counts these separately from active and inactive, and they
cannot be reused without a write first, so they belong in used rather
than in cache.
file_cache: u64The page cache (v_cache_count), in bytes rather than pages.
Modern FreeBSD folds the unified buffer cache into the inactive queue and
reports 0 here; it is kept because older kernels and vfs.bufspace still
populate it, and silently dropping it would understate reclaimable memory
on exactly those systems.
managed_pages: u64v_page_count, the number of pages the VM subsystem manages.
Used as the denominator for the partition check: active + inactive + laundry + wired + free must equal it, which is what makes the bar
segments add up to physical memory.
internal: u64internal_page_count: anonymous pages, the “by backing store” family.
macOS reports memory twice over, once by usage (active, inactive, …)
and once by backing store (internal, external). Only this one is
needed for accounting, because internal is exactly
active + inactive + speculative - external and therefore counts each
anonymous page once instead of re-adding overlapping usage classes.
Implementations§
Source§impl MemInfo
impl MemInfo
Sourcepub fn used_from_classes(&self) -> u64
pub fn used_from_classes(&self) -> u64
Sum the classes tagged counts_as_used.
Sourcepub fn cache_from_classes(&self) -> u64
pub fn cache_from_classes(&self) -> u64
Sum the classes tagged counts_as_cache.
Sourcepub fn finish_linux(&mut self)
pub fn finish_linux(&mut self)
Linux/GNU free accounting, matching linux/LinuxMachine.c.
used = total - free - cached - sreclaimable - buffers, with shmem
subtracted from the cached total first so it is not counted twice.
available is MemAvailable clamped to total, falling back to free
on kernels older than 3.14 that do not provide it.
Do not try to make used + available == total here: they measure
different things, and forcing it clamps MemAvailable down to
total - used, which is a much smaller (wrong) number.
Sourcepub fn finish_darwin(&mut self)
pub fn finish_darwin(&mut self)
macOS accounting, matching htop 3.4 and later.
used = (internal - purgeable) + wired + compressedhtop 3.4.1 (darwin/Platform.c, Platform_setMemoryValues) says it the
long way round:
natural_t used = vm->active_count + vm->inactive_count +
vm->speculative_count + vm->wire_count +
vm->compressor_page_count - vm->purgeable_count -
vm->external_page_count;
mtr->values[MEMORY_METER_USED] = (double)(used - vm->compressor_page_count) * page_K;
mtr->values[MEMORY_METER_COMPRESSED] = (double)vm->compressor_page_count * page_K;and MemoryMeter_updateValues prints USED + COMPRESSED. That sum is
internal + wired + compressed, because internal_page_count is
active + inactive + speculative - external. htop main (3.6-dev) states
the same figure directly, as a class list marked countsAsUsed: wired,
internal - purgeable, compressed. One formula therefore matches both,
and it matches Activity Monitor and top as well.
Consequences, all intentional:
- The compressor is counted as used. On a Mac that has been running a while it is the largest single term — 7 GB on a 16 GB machine is normal — and leaving it out made gander report ~5 GB where htop reported ~13 GB.
inactiveandspeculativeare not added on top. They are part ofinternal(or are file cache), so adding them double-counts; that was the other shipped mistake, and it is why the by-backing-store counter is used here instead of the by-usage ones.freeisvm_stat’s own free count. Deriving it astotal - used - cacheis what made the bar claim 7.8 GB free on a machine with 0.3 GB free: the compressor pages thatusedomitted fell through into the free segment.available = total - used, so the two figures partition memory exactly, and so do the bar segments.
The old htop-3.3.0 formula (used = active + wired, compressor ignored)
is gone: it was the reason the meter disagreed with every other tool by
the size of the compressor.
Sourcepub fn finish_freebsd(&mut self)
pub fn finish_freebsd(&mut self)
FreeBSD accounting.
FreeBSD’s VM keeps five mutually exclusive page queues, so the model is a partition rather than a formula:
used = active + wired + laundry
cache = inactive + page cache
available = free + cacheEvery page is in exactly one queue (v_page_count is their sum), which is
why the bar segments can be checked against physical memory the way
macOS’s can. laundry counts as used because those pages cannot be
reused until their write completes — the same reasoning that puts
macOS’s compressor in used.
free is the kernel’s own free count, never total - used: deriving it
is what made the macOS bar claim 7.8 GB free on a machine with 0.3 GB.
Sourcepub fn huge_used_bytes(&self) -> u64
pub fn huge_used_bytes(&self) -> u64
Huge pages in use, in bytes.
total - free rather than total - free - rsvd: reserved pages are
already committed to a process that has not faulted them in yet, so a
free figure that includes them overstates what is actually available.
htop prints used/total with the same subtraction.
pub fn huge_total_bytes(&self) -> u64
Sourcepub fn huge_pages_configured(&self) -> bool
pub fn huge_pages_configured(&self) -> bool
Whether the kernel has huge pages configured at all.
A machine with HugePages_Total of 0 has the feature compiled in but
nothing reserved; a meter for it would be a permanent empty bar, so the
meter says n/a here instead. Same reasoning as DiskIO on macOS.
Sourcepub fn compute_used(&mut self)
pub fn compute_used(&mut self)
Backwards-compatible alias used by the Linux parser.
Sourcepub fn is_consistent(&self) -> bool
pub fn is_consistent(&self) -> bool
Whether every derived figure is within physical bounds.
Sourcepub fn is_exactly_partitioned(&self) -> bool
pub fn is_exactly_partitioned(&self) -> bool
Stronger check for platforms that derive available from used.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for MemInfo
impl RefUnwindSafe for MemInfo
impl Send for MemInfo
impl Sync for MemInfo
impl Unpin for MemInfo
impl UnsafeUnpin for MemInfo
impl UnwindSafe for MemInfo
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more