memory_stats/
lib.rs

1//! # Memory Stats
2//!
3//! A cross-platform memory profiler for Rust, supporting Windows, Linux, and MacOS. This crate provides two metrics:
4//!
5//! - **"Physical" Memory**, which corresponds to the _Resident Set Size_ on Linux and MacOS and the _Working Set_ on Windows.
6//! - **"Virtual" Memory**, which corresponds to the _Virtual Size_ on Linux and MacOS and the _Pagefile Usage_ on Windows.
7//!
8//! ## Usage
9//!
10//! Add `memory-stats` as a dependency to your `Cargo.toml`:
11//!
12//! ```toml
13//! [dependencies]
14//! memory-stats = "1.0.0"
15//! ```
16//!
17//! ### Optional Features
18//!
19//! `serde`: Enables serialization and deserialization of the [`MemoryStats`] struct.
20//!
21//! ## Example
22//!
23//! Here's an example that prints out the current memory usage:
24//!
25//! ```
26//! use memory_stats::memory_stats;
27//!
28//! if let Some(usage) = memory_stats() {
29//!     println!("Current physical memory usage: {}", usage.physical_mem);
30//!     println!("Current virtual memory usage: {}", usage.virtual_mem);
31//! } else {
32//!     println!("Couldn't get the current memory usage :(");
33//! }
34//! ```
35//!
36//! ## Caveats
37//!
38//! Getting accurate memory usage on Linux is fairly expensive and not always possible. This crate always attempts to use the statistics from
39//! [`/proc/self/smaps`](https://man7.org/linux/man-pages/man5/proc.5.html#:~:text=See%20user_namespaces%287%29.-,/proc/%5Bpid%5D/smaps,-%28since%20Linux%202.6.14)
40//! if avaliable. However, since support for `/proc/self/smaps` might not be compiled in on all kernels, this crate will also use the faster but less accurate statistics from
41//! [`/proc/self/statm`](https://man7.org/linux/man-pages/man5/proc.5.html#:~:text=by%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20waitpid%282%29.-,/proc/%5Bpid%5D/statm,-Provides%20information%20about)
42//! as a fallback.
43//!
44//! If speed is needed over accuracy, the `always_use_statm` feature can be enabled to always use the `/proc/self/statm` statistics.
45
46#[cfg(feature = "serde")]
47use serde::{Deserialize, Serialize};
48
49#[cfg(target_os = "windows")]
50#[path = "windows.rs"]
51mod platform;
52
53#[cfg(any(target_os = "linux", target_os = "android"))]
54#[path = "linux.rs"]
55mod platform;
56
57#[cfg(any(target_os = "macos", target_os = "ios"))]
58#[path = "darwin.rs"]
59mod platform;
60
61#[cfg(target_os = "freebsd")]
62#[path = "freebsd.rs"]
63mod platform;
64
65#[cfg(not(any(
66    target_os = "windows",
67    target_os = "linux",
68    target_os = "android",
69    target_os = "macos",
70    target_os = "ios",
71    target_os = "freebsd",
72)))]
73mod platform {
74    use crate::MemoryStats;
75
76    pub fn memory_stats() -> Option<MemoryStats> {
77        None
78    }
79}
80
81/// Statistics on the memory used by the current process.
82#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
83#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
84pub struct MemoryStats {
85    /// The "physical" memory used by this process, in bytes.
86    /// This corresponds to the following
87    /// metric on each platform:
88    /// - **Linux, Android, MacOS, iOS**: Resident Set Size
89    /// - **Windows**: Working Set
90    pub physical_mem: usize,
91
92    /// The "virtual" memory used by this process, in bytes.
93    /// This corresponds to the following
94    /// metric on each platform:
95    /// - **Linux, Android, MacOS, iOS**: Virtual Size
96    /// - **Windows**: Pagefile Usage
97    pub virtual_mem: usize,
98}
99
100/// Returns a snapshot of the the memory used by the
101/// current process.
102///
103/// # Errors
104///
105/// If the current memory usage cannot be queried
106/// or `memory_stats` is run on a unsupported platform,
107/// `None` is returned.
108pub fn memory_stats() -> Option<MemoryStats> {
109    platform::memory_stats()
110}