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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// SPDX-FileCopyrightText: Copyright (c) 2026 Mike Li/Mikewolfli/Wei Li(mikewolfli@163.com)
// SPDX-License-Identifier: MIT
//! Darwin-family system probes shared by the macOS (cocoa and objc2) and iOS backends.
//!
//! # Why this module exists
//!
//! `Platform::total_memory_mb`, `is_on_battery` and `process_memory_utilization` are
//! answered by every backend, and each answer must come from an API the host actually
//! has. The cocoa backend, the objc2 preview backend, the iOS backend and the generic
//! mobile backend all landed on `crate::platform::os_probes`, which parses
//! `/proc/meminfo`, `/sys/class/power_supply` and `/proc/self/status` — files that only
//! exist on a **Linux** kernel. On Apple hardware every one of those probes silently
//! degraded to the "unknown" answer (`None` / `false`), so a macOS build reported no
//! installed memory and no process footprint while the trait documentation promised
//! `sysctl hw.memsize` and `ps`.
//!
//! The bug was invisible because the "unknown" answer is a *legal* return value: nothing
//! panicked, nothing logged. `Platform::total_memory_mb`'s own doc comment forbids
//! substituting a made-up constant, so the fix cannot be to invent a number either — it
//! has to be an actual Darwin probe.
//!
//! # Why /proc was the wrong answer even where it "works"
//!
//! iOS does not ship a readable `/proc/meminfo` (the sandbox hides it), so the iOS
//! backend was in the same state as macOS. Android *and* HarmonyOS are Linux-kernel
//! systems and keep using [`crate::platform::os_probes`] correctly — that is the
//! documented contract of that module, and this one does not replace it.
//!
//! # Cost
//!
//! `sysconf` is a libc call with no file I/O. The `pmset` and `ps` probes each spawn a
//! short-lived child process, so their answers are cached for a short TTL
//! ([`BATTERY_CACHE_TTL`], [`MEMORY_CACHE_TTL`]): `AdaptivePerformanceMonitor` samples memory
//! every frame, and spawning `ps` at 60 Hz was a measurable share of a frame. A TTL is the
//! honest middle ground between "never ask" and "ask 60 times a second": the figure is live to
//! within a few seconds, and the cache is stamped rather than permanent.
use crateToString;
use crate;
/// How long a `ps` sample is reused.
///
/// Shorter than the battery TTL because memory pressure can change within a frame burst; five
/// seconds is long enough that a sustained render loop spawns one `ps`, not hundreds.
const MEMORY_CACHE_TTL: Duration = from_secs;
/// How long a `pmset` answer is reused.
///
/// Power source changes on the scale of seconds at the fastest (a user unplugging a laptop), and
/// a stale answer for half a minute cannot strip animations for longer than that.
const BATTERY_CACHE_TTL: Duration = from_secs;
/// Runs `probe` at most once per `ttl`, returning the cached value in between.
/// Reads installed physical memory in mebibytes via `sysconf(_SC_PHYS_PAGES)`.
///
/// This is the same quantity `sysctl hw.memsize` returns and the same quantity the
/// Linux probe reads from `/proc/meminfo`, so the two backends answer the question
/// comparably. `_SC_PHYS_PAGES` already accounts for the pages the kernel can hand out,
/// which is why it is preferred over `hw.memsize` — no FFI binding is needed for
/// `sysctl` itself.
///
/// Returns `None` when the sysconf query fails, which keeps the "unknown" answer
/// available instead of substituting a constant.
/// Reports whether the machine is currently drawing from its battery.
///
/// `pmset -g batt` prints `Now drawing from 'AC Power'` or `Now drawing from
/// 'Battery Power'`; the latter is the only discharging answer. A desktop Mac has no
/// battery and prints `'AC Power'`, which is the same `false` a Linux tower reports
/// from an empty `/sys/class/power_supply`.
///
/// Returns `false` when `pmset` cannot be spawned or prints neither phrase — the safe
/// direction, because a wrong "on battery" would silently strip animations.
/// Samples this process's resident memory against its virtual size, clamped to `[0, 1]`.
///
/// `ps -o rss=,vsz=` reports both figures in kibibytes for one pid, which is the same
/// RSS/VmSize ratio the Linux probe computes from `/proc/self/status`. The ratio is a
/// cheap proxy for how much of the mapped address space is resident; `vsz` is the
/// denominator, so a process that has mapped a large file reports a low figure.
///
/// Returns `None` when `ps` cannot be spawned, prints no parsable pair, or reports a
/// non-positive virtual size (a zero denominator has no utilisation to speak of).
/// The `ps` selector this module relies on, exposed so a test can assert the spelling.
///
/// `ps -o rss=,vsz=` is BSD syntax (no leading `-` on the selector list, `=` to drop the
/// header). A future edit that "tidies" it into `--format` would silently make
/// [`process_memory_utilization`] return `None` on every Darwin host, so the selector is
/// pinned by a test rather than left as a literal inside the function.
pub const PS_SELECTOR: = ;
/// The `pmset` argument list, exposed for the same reason as [`PS_SELECTOR`].
pub const PMSET_ARGUMENTS: = ;
/// Formats the parse failure the `ps` probe must report rather than guess at.
///
/// Kept here so the probe and its tests agree on one message; returns the text a caller
/// would see in a log when `ps` prints something unparsable.