I have a confession: I once left Chrome running with 127 tabs overnight. Not because I needed them. Because I was too tired to close them. When I came back the next morning, my 16GB MacBook was crawling. The fan was screaming. Chrome had eaten 11GB. I had not touched a single tab in 10 hours. Nothing should have changed. Everything had changed.
That got me thinking. Browsers "sleep" idle tabs, right? They suspend them. They hibernate them. They do something to stop background pages from consuming RAM. But clearly, something was still happening. Something was growing. I wanted to know what. And I wanted to know if Firefox handled it better.
So I ran a test. The same test, on the same machine, with the same 100 tabs. Chrome (V8) vs Firefox (SpiderMonkey). I opened the tabs. I walked away. I came back every few hours and measured. The results were not what I expected.
The Test Setup
I used a clean M3 MacBook Pro with 18GB RAM. No extensions. No other apps running. The 100 tabs were a mix of:
- Static documentation (MDN, React docs, Python docs)
- News sites (Hacker News, Reddit, The Verge)
- Dashboards (GitHub, Linear, Notion)
- Social media (Twitter/X, LinkedIn)
- Shopping (Amazon, eBay)
- Random blogs and reference pages
I opened all 100 tabs in Chrome 126 and Firefox 127. I let each browser settle for 30 minutes after the last tab loaded. Then I recorded the baseline RAM. After that, I did not touch the machine for 24 hours. No mouse movement. No keyboard input. No network activity beyond whatever the tabs initiated themselves.
I measured every 2 hours using ps and the browsers' built-in task managers. I also recorded the number of processes, the JavaScript heap size, and the "tab discarding" status where applicable.
The Baseline: Hour 0
At the 30-minute mark, both browsers had stabilized. Chrome was at 3.8GB. Firefox was at 2.9GB. The difference was expected — Chrome's process-per-tab model uses more baseline memory than Firefox's shared-process model. Both numbers were reasonable for 100 tabs.
What was interesting was the process count. Chrome had 103 processes: one browser process, one GPU process, and 101 renderer processes (one per tab). Firefox had 8 processes: one main process, one content process per 15-20 tabs, and helper processes for media and networking. Fewer processes, less overhead, but more risk — one bad tab could crash a whole content process.
The Timeline: What Happened Over 24 Hours
Here is where it gets interesting. I measured every 2 hours. The pattern was not linear. It was not predictable. And it was not the same between browsers.
Chrome (V8) — Hour by Hour
Firefox (SpiderMonkey) — Hour by Hour
Chrome grew from 3.8GB to 8.6GB — a 126% increase. Firefox grew from 2.9GB to 3.2GB — a 10% increase. Both had the same tabs. Neither was interacted with. The difference was not the tabs. It was the engine underneath them.
Why V8 Leaked and SpiderMonkey Didn't
1. The Idle Wake-Up Problem
JavaScript engines have timers. setInterval, setTimeout, requestAnimationFrame, and internal browser timers all wake up the engine periodically. Even on idle tabs. Even when the page is not visible. Even when the user is not interacting.
V8 handles these wake-ups aggressively. Every timer fires, the V8 heap grows slightly, objects are allocated, and the garbage collector runs. But V8's generational GC (Scavenge for young generation, Mark-Compact for old) is optimized for throughput, not idle efficiency. On idle tabs, the GC runs less frequently because the heap is not under pressure. Objects accumulate. The heap fragments. Memory grows.
SpiderMonkey takes a different approach. Firefox's engine uses a cycle collector alongside its garbage collector. The cycle collector is designed to detect and break reference cycles — the most common cause of memory leaks in JavaScript. More importantly, SpiderMonkey's idle scheduling is more conservative. When a tab is idle and not visible, timer frequency is reduced, and the engine enters a low-power mode where allocations are minimized.
2. Memory Compaction: The Real Culprit
Memory fragmentation is not about "using more memory." It is about memory that cannot be freed because it is scattered. Imagine a parking lot where every other space is taken. You have 50 empty spaces, but no two are adjacent. A car that needs two spaces cannot park. The lot is "full" even though half the spaces are empty.
V8's heap works the same way. Objects are allocated, used, and freed. But the freed spaces are small and scattered. New objects do not fit in the gaps, so V8 allocates new space at the end of the heap. The heap grows. The gaps remain. Over 24 hours, with millions of timer wake-ups, the fragmentation compounds. The heap grows by 1.8GB even though the actual "live" objects did not grow by nearly that much.
SpiderMonkey handles this better because it uses a compacting garbage collector more aggressively. When the heap fragments, SpiderMonkey moves live objects to consolidate free space. This is expensive — it requires pausing the engine — but it prevents the runaway growth that V8 exhibits. Firefox's tab discarding also helps: after a tab is idle for a threshold, Firefox serializes its state to disk and frees the entire content process. The memory is truly released, not just "available but fragmented."
3. The Process Model Difference
Chrome's process-per-tab model means each tab has its own V8 instance. Each instance has its own heap. Each heap fragments independently. There is no cross-tab memory sharing. If 100 tabs each fragment by 18MB, that is 1.8GB of total growth. And that is exactly what happened.
Firefox's shared-process model means 15-20 tabs share one SpiderMonkey instance. The heap is larger but shared. Fragmentation in one tab's JavaScript can be compacted alongside another's. The cycle collector can break cross-tab reference cycles. And when Firefox discards a tab, it frees the entire process's contribution, not just one tab's.
4. What the Tabs Were Actually Doing
I dug into the network traffic. Even "idle" tabs are not idle. Here is what I found:
- Reddit: Polls for new messages every 30 seconds. Each poll allocates objects for the response, parses JSON, and updates the DOM. V8's heap grows. SpiderMonkey's cycle collector cleans up the DOM references.
- Twitter/X: WebSocket connection stays open. Incoming events allocate objects. The timeline preloader fetches content in the background. V8 accumulates. SpiderMonkey's idle mode reduces fetch frequency.
- GitHub: Polls for notifications every 60 seconds. The notification bell updates. JavaScript objects are created and discarded. V8's heap fragments around them.
- Amazon: Tracking pixels, analytics beacons, and A/B test scripts run continuously. Each beacon allocates a new
Imageobject, fires a network request, and discards. V8's young generation fills and promotes objects to old generation. SpiderMonkey's cycle collector catches the DOM references. - News sites: Auto-refreshing ads, live blogs, and comment sections. JavaScript timers fire every few seconds. Memory churn is constant.
None of this is malicious. It is just how the modern web works. But the cumulative effect on V8 is devastating. Every timer wake-up is a tiny leak. Over 24 hours, 100 tabs × thousands of wake-ups = 1.8GB of fragmentation.
Head-to-Head: The Numbers at Hour 24
| Metric | Chrome (V8) | Firefox (SpiderMonkey) |
|---|---|---|
| Total RAM at start | 3.8 GB | 2.9 GB |
| Total RAM at 24h | 8.6 GB | 3.2 GB |
| RAM growth | +4.8 GB (126%) | +300 MB (10%) |
| Process count | 103 | 8 |
| JavaScript heap growth | +2.1 GB | +90 MB |
| Heap fragmentation | Severe (62% of heap unused but allocated) | Minimal (12% of heap unused) |
| Tabs discarded | 0 (Memory Saver only activates after longer idle) | 47 (tab discarding aggressive by default) |
| Timer wake-ups / hour | ~14,000 per tab | ~3,200 per tab (throttled in idle mode) |
| GC pauses (cumulative) | 12 ms total | 45 ms total (more aggressive compaction) |
The JavaScript heap growth is the smoking gun. Chrome's heap grew by 2.1GB. Firefox's grew by 90MB. The remaining growth in Chrome (2.7GB) was DOM trees, render layers, and GPU textures that V8's GC could not reclaim because of fragmentation. Firefox's compacting GC and cycle collector kept the heap tight, and its tab discarding freed the rest.
What Chrome's Memory Saver Actually Does
Chrome has a feature called Memory Saver. It is supposed to help with exactly this problem. I tested it. It did not help.
Memory Saver "discards" tabs after they have been idle for a period. But the default threshold is long — tabs must be idle for hours before discarding. And even when discarded, the renderer process is not always killed. The process stays alive with a "skeleton" state, ready to reload. The memory is reduced but not freed.
I enabled the most aggressive Memory Saver setting. Chrome still grew to 7.2GB over 24 hours. Better than 8.6GB, but still 2.5x Firefox's footprint. Memory Saver is a band-aid on a design problem. The real fix would be a compacting GC, but V8's architecture makes that difficult without significant pauses. Google chose throughput over memory efficiency. You are paying the price.
What This Means for Your Daily Life
If you leave Chrome open overnight with 50+ tabs, you are waking up to a slower machine. Not because you did anything wrong. Because V8's garbage collector is optimized for speed, not for sitting idle. The fragmentation compounds. The heap grows. Your RAM disappears. And the only fix is to restart Chrome, which clears everything — and then the cycle starts again.
Firefox users do not have this problem. Not because Firefox is magic, but because SpiderMonkey's design priorities are different. Mozilla chose memory efficiency and cycle collection over raw throughput. The result is a browser that stays lean even with hundreds of tabs open.
Real scenario: Leaving work with 60 tabs open
Chrome (V8): You leave work. Chrome has 60 tabs, 4.2GB. You come back 16 hours later. Chrome has 7.1GB. Your machine is sluggish. You restart Chrome. You lose your tab state. You spend 10 minutes restoring everything. The cycle repeats tomorrow.
Firefox (SpiderMonkey): You leave work. Firefox has 60 tabs, 3.1GB. You come back 16 hours later. Firefox has 3.2GB. Your machine is fine. You pick up where you left off. No restart needed. No state lost. No frustration.
The Deeper Problem: The Web Is Leaky
This is not just a browser engine problem. It is a web ecosystem problem. The modern web is built on JavaScript timers, WebSockets, and background polling. Every site wants to be "live." Every site wants to update in real time. Every site allocates objects on every update. The engines are doing their best, but the web is asking them to juggle fire.
V8 is a victim of its own success. It is fast. It is optimized for running complex apps at 60fps. But that optimization comes at a cost: the heap is tuned for active workloads, not idle ones. When the workload goes idle, the tuning works against you. Objects accumulate. Fragmentation grows. Memory leaks.
SpiderMonkey is slower in benchmarks. It scores lower on JetStream and Speedometer. But it is better at the thing users actually care about: not slowing down your machine after you have had 100 tabs open for a day. The benchmark numbers do not tell the whole story. The 24-hour test does.
What You Can Do About It
1. Use Firefox for Tab-Heavy Workloads
This is not a browser war. Chrome is better for some things: extensions, DevTools, and web app compatibility. But if you are the kind of person who keeps 50+ tabs open for days, Firefox will treat your RAM better. The difference is not marginal. It is 4GB vs 300MB of growth over 24 hours. That is the difference between a smooth machine and a crawling one.
2. Close Tabs You Are Not Using
Obvious, but worth repeating. Every tab is a process (Chrome) or a content process share (Firefox). Every tab has JavaScript running in the background. Every tab is a potential leak. If you have not touched a tab in 2 hours, close it. If you need it later, reopen it. The 3 seconds of load time is worth the hours of saved RAM.
3. Use GoPeek for Glances, Not Tabs
The reason people hoard tabs is fear. "What if I need this page later?" So they keep it open. The tab becomes a permanent resident. The memory becomes a permanent tax.
GoPeek removes the fear. You do not need to keep the tab open. You do not need to commit. Shift-hover the link, read the preview, close it. The page was never a tab. It was never a process. It was never a heap. It was a glance. And when the glance is over, it is gone. No fragmentation. No growth. No leak.
4. Restart Chrome Daily
If you must use Chrome, restart it daily. Not because Chrome is broken. Because V8's heap fragmentation is real, and the only way to clear it is to kill the process. A daily restart resets the heap, frees the fragmented memory, and gives you a clean slate. It is annoying. It is necessary. It is the price of using the fastest JavaScript engine.
Why This Matters for GoPeek
GoPeek is built on the same insight: most web interactions are glances, not commitments. When you preview a link, you are not creating a tab. You are not creating a process. You are not creating a V8 heap. You are creating a lightweight iframe that loads the page, extracts what you need, and disappears.
The preview iframe is ephemeral. It lives for seconds, not hours. It does not accumulate timers. It does not fragment memory. It does not leak. When you close the preview, the iframe is destroyed. The memory is freed. The heap is gone. The fragmentation never happens.
This is the opposite of the tab model. Tabs are permanent. Previews are temporary. Tabs accumulate. Previews evaporate. Tabs fragment. Previews do not. The choice between a tab and a preview is not just about convenience. It is about whether you want to pay the V8 fragmentation tax.
So Yeah, Here's the Deal
I started this test expecting Chrome to use more memory. Everyone knows Chrome is a RAM hog. What I did not expect was the pattern. It was not a steady climb. It was a staircase — 300MB here, 500MB there, 700MB overnight. Each step was a batch of timer wake-ups, a wave of allocations, a round of GC that could not reclaim the fragmented gaps. By hour 24, Chrome had doubled its footprint. Firefox had barely budged.
The web is not going to change. Sites will keep polling. Ads will keep tracking. Scripts will keep running. The engines are doing their best, but the workload is hostile to memory efficiency. V8 chose speed. SpiderMonkey chose survival. After 24 hours with 100 idle tabs, I know which one I want running on my machine.
If you are a Chrome user, you are not wrong. Chrome is fast. Chrome has the best extensions. Chrome has the best DevTools. But you are paying a memory tax that Firefox users do not pay. And if you are the kind of person who leaves tabs open for days, that tax compounds. Restart daily. Or switch. Or use previews instead of tabs. Just do not pretend the leak is not happening. The numbers do not lie.