Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pinchtab/pinchtab/llms.txt

Use this file to discover all available pages before exploring further.

PinchTab monitors Chrome’s memory usage at the OS level, providing accurate real-world memory consumption for each browser instance.

Enabling Memory Metrics

Memory monitoring is off by default to minimize overhead.
1

Open Dashboard

Navigate to http://localhost:<port>/dashboard
2

Go to Settings

Click Settings📈 Monitoring
3

Enable Metrics

Toggle Tab Memory Metrics on (marked as experimental)
4

Apply Changes

Click Apply Settings to save

How Memory is Calculated

PinchTab uses a process tree approach to measure memory:
1

Identify Browser Process

Gets the main Chrome PID from chromedp
2

Walk Process Tree

Finds all child processes (renderers, GPU, utilities)
3

Sum RSS Memory

Adds up Resident Set Size across all Chrome processes
4

Filter Renderers

Counts processes with --type=renderer for tab count
This approach ensures memory is isolated per instance — you only see memory for that specific Chrome profile, not other Chrome windows on your system.

Memory Fields

FieldDescription
memoryMBReal OS-level memory (RSS) across all Chrome processes
jsHeapUsedMBEstimated JS heap (~40% of memoryMB)
jsHeapTotalMBEstimated total heap (~50% of memoryMB)
renderersNumber of renderer processes (≈ tabs)
JS heap values are estimates based on typical Chrome memory distribution. For exact JS heap metrics, use Chrome DevTools directly.

API Endpoints

Per-Tab Metrics

GET /tabs/{tabId}/metrics
Returns memory metrics (aggregated, since we can’t reliably map tabs to PIDs):
{
  "memoryMB": 850.5,
  "jsHeapUsedMB": 340.2,
  "jsHeapTotalMB": 425.25,
  "renderers": 11,
  "documents": 0,
  "frames": 0,
  "nodes": 0,
  "listeners": 0
}
curl http://localhost:9867/tabs/tab_abc123/metrics | jq .

Instance Metrics

GET /metrics
Returns server metrics and browser memory:
{
  "metrics": {
    "goHeapAllocMB": 12.5,
    "goHeapSysMB": 24.0,
    "goNumGoroutine": 15
  },
  "memory": {
    "memoryMB": 850.5,
    "jsHeapUsedMB": 340.2,
    "jsHeapTotalMB": 425.25,
    "renderers": 11
  }
}
curl http://localhost:9868/metrics | jq .

All Instances (Orchestrator)

GET /instances/metrics
Returns memory metrics for all running instances:
[
  {
    "instanceId": "inst_abc123",
    "profileName": "MyProfile",
    "jsHeapUsedMB": 340.2,
    "jsHeapTotalMB": 425.25,
    "documents": 0,
    "frames": 0,
    "nodes": 0,
    "listeners": 0
  }
]
curl http://localhost:9867/instances/metrics | jq .

Dashboard Visualization

When enabled, the Monitoring page shows:
  • Chart: Solid lines for tab counts (left axis), dashed lines for memory in MB (right axis)
  • Instance List: Shows memory alongside tab count (e.g., :9869 · 11 tabs · 1382MB)
  • Real-time updates: Data polled every 30 seconds, chart retains ~30 minutes of history
The dashboard provides a visual timeline of memory usage and tab counts across all instances.

Performance Considerations

  • Memory metrics use gopsutil for OS-level process info
  • Minimal overhead: just reads /proc (Linux) or uses sysctl (macOS)
  • No CDP calls required — works reliably even with many tabs
  • 5-second grace period for new instances to stabilize before polling
Memory monitoring has negligible performance impact since it reads OS-level statistics rather than querying Chrome directly.

Monitoring Scripts

Basic Memory Monitor

#!/bin/bash

while true; do
  echo "=== $(date) ==="
  
  # Get metrics for all instances
  METRICS=$(curl -s http://localhost:9867/instances/metrics)
  
  # Calculate totals
  TOTAL_HEAP=$(echo "$METRICS" | jq '[.[].jsHeapUsedMB] | add')
  INSTANCE_COUNT=$(echo "$METRICS" | jq 'length')
  
  echo "Instances: $INSTANCE_COUNT"
  echo "Total JS Heap: ${TOTAL_HEAP} MB"
  
  # Per-instance breakdown
  echo "$METRICS" | jq -r '.[] | "\(.profileName): \(.jsHeapUsedMB) MB"'
  
  sleep 30
done

Alert on High Memory

import requests
import time

THRESHOLD_MB = 2000  # Alert if any instance exceeds 2GB

while True:
    try:
        response = requests.get('http://localhost:9867/instances/metrics')
        instances = response.json()
        
        for inst in instances:
            memory = inst.get('jsHeapUsedMB', 0)
            if memory > THRESHOLD_MB:
                print(f"⚠️ HIGH MEMORY: {inst['profileName']} using {memory:.1f} MB")
                print(f"   Instance ID: {inst['instanceId']}")
        
        total = sum(i.get('jsHeapUsedMB', 0) for i in instances)
        print(f"Total: {total:.1f} MB across {len(instances)} instances")
        
    except Exception as e:
        print(f"Error: {e}")
    
    time.sleep(30)

Export Metrics to CSV

import { writeFileSync } from 'fs';

interface InstanceMetrics {
  instanceId: string;
  profileName: string;
  jsHeapUsedMB: number;
  jsHeapTotalMB: number;
}

async function exportMetrics() {
  const response = await fetch('http://localhost:9867/instances/metrics');
  const instances: InstanceMetrics[] = await response.json();
  
  const timestamp = new Date().toISOString();
  const csv = [
    'timestamp,instanceId,profileName,jsHeapUsedMB,jsHeapTotalMB',
    ...instances.map(i => 
      `${timestamp},${i.instanceId},${i.profileName},${i.jsHeapUsedMB},${i.jsHeapTotalMB}`
    )
  ].join('\n');
  
  const filename = `metrics-${Date.now()}.csv`;
  writeFileSync(filename, csv);
  console.log(`Exported to ${filename}`);
}

// Run every minute
setInterval(exportMetrics, 60000);
exportMetrics();

Troubleshooting

Memory shows 0

  • Chrome may not have started yet (check instance status)
  • Browser context not initialized
  • Wait 5-10 seconds after instance creation
# Check instance status
curl http://localhost:9867/instances | jq '.[] | {id, status}'

# Wait for running status
INST_ID="inst_abc123"
while [ "$(curl -s http://localhost:9867/instances/$INST_ID | jq -r '.status')" != "running" ]; do
  echo "Waiting for instance to start..."
  sleep 1
done

Memory seems too high

  • Chrome is known to use significant memory
  • Each tab runs in a separate renderer process
  • Extensions and DevTools add to memory usage
  • Consider closing unused tabs or instances
# List tabs per instance
curl http://localhost:9867/instances | jq '.[] | {id, profileName, port}' | while read -r line; do
  INST_ID=$(echo $line | jq -r '.id')
  TAB_COUNT=$(curl -s http://localhost:9867/instances/$INST_ID/tabs | jq 'length')
  echo "$line has $TAB_COUNT tabs"
done

Memory doesn’t match Activity Monitor/Task Manager

  • PinchTab shows RSS (Resident Set Size) for Chrome processes
  • System tools may show different metrics (virtual memory, shared memory)
  • Other Chrome windows are excluded — we only count this instance’s process tree
RSS (Resident Set Size) represents actual physical memory used, which is the most accurate metric for resource planning.

Memory Management Best Practices

Set reasonable limits based on available RAM:
# Estimate memory per instance type
HEADLESS_MB=80
HEADED_MB=150
AVAILABLE_RAM_MB=8192  # 8GB

# Calculate max instances
MAX_HEADLESS=$((AVAILABLE_RAM_MB / HEADLESS_MB))
MAX_HEADED=$((AVAILABLE_RAM_MB / HEADED_MB))

echo "Can run ~$MAX_HEADLESS headless or ~$MAX_HEADED headed instances"