How much memory Mac apps actually use
Three tools on your Mac will give you three different numbers for the same app. Here is a measured reading, and the commands to reproduce it.
Every article about Mac memory quotes numbers. Almost none of them say where the numbers came from, which is a problem, because macOS reports at least three different figures for the same application and they routinely disagree by a factor of two or more.
This page is the opposite arrangement: one reading, one machine, one timestamp, and the exact commands underneath it. You can run them and check every figure here.
Three numbers, three different answers
| Number | Where it comes from | What it actually tells you |
|---|---|---|
| footprint | phys_footprint, the Memory column in Activity Monitor | What this app currently costs you. The one to trust. |
| peak | phys_footprint_peak, from /usr/bin/footprint | The high-water mark since the process started. This is how a leak shows itself. |
| RSS | Resident set size, what ps prints | Counts shared framework pages once per process and ignores compressed pages, so it drifts from footprint in both directions. |
That last row is not a theoretical caveat. In the reading below, Microsoft Edge's RSS is 46% higher than its footprint, while on the same machine at the same moment a smaller app showed the reverse, with RSS at roughly a third of its footprint. Quoting "RSS" and "memory used" as if they were the same number is how two people end up arguing about an app with two correct but different figures in front of them.
The reading
Mac17,9 (Apple silicon), macOS 26.5.1, 64 GB installed. Taken September 11, 2026, 02:17 UTC. Sizes are 1024-based, the way
vm_stat and footprint report them. Helper processes are grouped under
the application they belong to, so a browser is one row rather than twenty.
| App | Processes | Footprint | Peak (largest process) | RSS |
|---|---|---|---|---|
| Vivaldi | 15 | 3.61 GB | 1.71 GB | 3.21 GB |
| Brave Browser | 15 | 2.34 GB | 0.78 GB | 2.18 GB |
| Microsoft Edge | 17 | 1.61 GB | 0.45 GB | 2.35 GB |
| Chromium | 22 | 1.04 GB | 0.48 GB | 2.23 GB |
| WindowServer | 1 | 0.89 GB | not readable | 0.16 GB |
| Docker | 10 | 0.47 GB | 2.75 GB | 0.61 GB |
| node | 4 | 0.24 GB | 0.29 GB | 0.27 GB |
Two rows are worth stopping on.
- Docker was using 0.47 GB and had peaked at 2.75 GB, roughly six times its current size. An app sitting quietly at a few hundred megabytes with a multi-gigabyte peak has already taken that memory from you once today, and the current figure alone would never tell you.
- Chromium was 22 processes for 1.04 GB; Vivaldi was 15 for 3.61 GB. Process count says nothing about cost. What matters is the total under the parent, which is why a list of thirty "Helper (Renderer)" rows in Activity Monitor is close to unreadable.
What this reading does not prove
It is one machine, one workload, one moment. It is not a benchmark and not a typical value: the same browser with four tabs open and with forty tabs open are different measurements, and nothing here controls for that. Treat the table as a worked example of the method, and the method as the part worth copying. If you need a number for your own machine, take your own reading - it takes about ten seconds, and how much RAM do I need turns a week of those readings into a decision.
Take the same reading on your Mac
Nothing here needs sudo, installs anything, or writes to disk.
System-wide, and the figure most people misread:
vm_stat
sysctl -n vm.swapusage
memory_pressure -Q Per process, sorted by what it actually costs:
top -l 1 -o mem -n 20 -stats pid,command,mem The peak for one process, which nothing in Activity Monitor will show you:
/usr/bin/footprint -p <pid>
And the grouping, which is the only part that needs more than one line. Paste this into a file
and run it with python3; it reads the same two commands as above and adds the
helper processes up under their parent application.
import re, subprocess, collections
sh = lambda c: subprocess.run(c, capture_output=True, text=True).stdout
U = {"B": 1, "": 1, "K": 1024, "M": 1024**2, "G": 1024**3}
mem = {}
for ln in sh(["top", "-l", "1", "-n", "4000", "-stats", "pid,mem"]).splitlines():
p = ln.split()
if len(p) == 2 and p[0].isdigit():
m = re.match(r"([\d.]+)([BKMG]?)", p[1])
if m: mem[int(p[0])] = float(m.group(1)) * U[m.group(2)]
apps, procs = collections.Counter(), collections.Counter()
for ln in sh(["ps", "-axo", "pid=,comm="]).splitlines():
p = ln.strip().split(None, 1)
if len(p) < 2 or not p[0].isdigit(): continue
hits = re.findall(r"/([^/]+)\.app/", p[1]) # outermost bundle wins
name = hits[0] if hits else p[1].split("/")[-1]
apps[name] += mem.get(int(p[0]), 0); procs[name] += 1
for name, total in apps.most_common(15):
print(f"{name[:34]:36}{procs[name]:>4} procs {total/1024**3:8.2f} GB")
One detail in there is load-bearing. A Chromium helper lives inside its own nested bundle, at a
path like /Applications/Vivaldi.app/Contents/Frameworks/.../Vivaldi Helper
(Renderer).app/Contents/MacOS/. Match the last .app in that path and you get
forty "Vivaldi Helper" rows and no Vivaldi. The outermost bundle is the application a person
recognises, which is why the regex takes the first match.
The number that looked alarming and was not
On the same machine, at the same moment:
- Free memory: 1.2% of 64 GB.
- Swap used: 0 bytes.
- The compressor was using 10.7 GB of RAM to hold 20.5 GB of data, a ratio of 1.91 to 1. That is 9.75 GB of physical memory this Mac did not have to find.
memory_pressurereported 64% free system-wide.
Two of those figures disagree by a factor of fifty, and both are correct. "Free" counts pages nobody has claimed yet, and an operating system that leaves 64 GB sitting idle is wasting it. Pressure is the figure that answers the question people actually mean: is memory keeping up. Zero swap with nothing paging out is what a healthy machine looks like, and it can look like that with 1% free.
This is also why a "free up RAM" button is measuring the wrong thing. See whether Mac memory cleaners do anything for what those tools actually change, and how to monitor RAM usage for the rest of the Memory tab.
What to do once you have the numbers
A reading tells you which app is expensive. It does not tell you what to do the next time the same app does the same thing, and that is the part that repeats. If one name keeps coming back at the top of your own table, the useful response is a rule rather than a reminder: a ceiling for that app, and a decision, made once, about what should happen when it is crossed.
That is what RAMKeeper does, and the free build does the measuring half of it without a licence: per-app and per-renderer attribution, current against peak, in the menu bar. Download it, or keep using the commands above - they are the same numbers.
Disclosure: this guide is published by RAMKeeper, which sells a Mac memory tool. Every figure on this page came from the commands printed above, on the machine described above, and you can check all of them without installing anything.