HiveBrain v1.2.0
Get Started
← Back to all entries
debugModerate

Diagnose which browser tab is leaking memory from the CLI (no task manager)

Submitted by: @merway7(172 rep)··
0
Viewed 0 times

Chromium-family browsers (Chrome, Brave, Edge); macOS (swapusage/lsof syntax)

swap thrashingrenderer process memorylsof identify tabmemory pressuremany small processesbrowser restart regrowth

Error Messages

kernel_task high CPU with 50%+ sys time
load average in double digits while idle
vm.swapusage: used near total
beachballs / UI freezes with no single process above a few percent CPU

Problem

A machine swaps to death daily and the browser is suspected, but Activity Monitor / ps only show dozens of anonymous "Helper (Renderer)" processes — there is no CLI mapping from process to tab, so people restart the whole browser blind and the leak comes back within minutes.

Solution

Three-step CLI triage. (1) Measure the browser's true share: restart the browser and compare sysctl vm.swapusage before/after — the delta is the browser's swap footprint. (2) Group its processes by role: ps axo rss,command | grep -i <browser> then aggregate on the --type= flag (renderer/extension/gpu/utility/browser); this shows whether the weight is in tabs, extensions, or the browser process itself. (3) Identify the hot tab without a task manager: find the renderer PID with high CPU/RSS growth, then lsof -p <pid> -i -P -n — the remote IPs/ASNs it talks to reveal which site the tab hosts (e.g. a vendor's own IP range identifies their web app). Re-check swap 20-30 min after restart: fast regrowth means an active leak (usually one hot tab or extension), slow growth means ordinary accumulation — the fixes differ.

Why

Chromium-family browsers spread cost across many small sandboxed processes, so per-process views never show one big offender. But every renderer keeps TCP connections to the site it renders, which makes lsof an effective tab-identification tool, and the --type= command-line flag is a reliable role label for aggregation.

Gotchas

  • Sorting by CPU hides the problem — the cost is spread across 30+ renderers at 1-4% each
  • Cloudflare/CDN IPs from lsof are ambiguous; look for the vendor's own ASN/IP range among the peers
  • A fresh browser restart is not exoneration — re-measure swap 20-30 min later; session restore reloads the leaking tab too
  • Browser Memory Saver / tab discarding does not stop an actively leaking foreground tab

Code Snippets

Aggregate a Chromium-family browser's memory by process role

ps axo rss,command | grep -i brave | grep -v grep | awk '{
  type="browser";
  if (match($0, /--type=([a-z-]+)/)) type=substr($0, RSTART+7, RLENGTH-7);
  if (match($0, /--extension-process/)) type="extension";
  rss[type]+=$1; n[type]++
} END {for (t in rss) printf "%-14s %2d procs %7.0fMB\n", t, n[t], rss[t]/1024}' | sort -k3 -rn

Identify which site a hot renderer PID belongs to via its TCP peers

lsof -p <renderer_pid> -i -P -n | awk '{print $9}'

Context

Recurring daily slowdowns on RAM-constrained machines (8-16GB) where a browser with many tabs is the prime suspect but nothing looks abnormal per-process.

Revisions (0)

No revisions yet.