---
sidebar_position: 3
---

# Performance Monitoring

Using agnt to analyze, diagnose, and improve web application performance.

## Overview

agnt provides multiple tools for performance analysis:

- **Proxy traffic logs** - Request/response timing
- **Performance metrics** - Page load, paint timing
- **Network capture** - Resource loading analysis
- **Process monitoring** - Build and runtime performance

## Setting Up Performance Monitoring

### Start with Proxy

```json
// Start your app
run {script_name: "dev"}

// Create proxy for monitoring
proxy {action: "start", id: "perf", target_url: "http://localhost:3000", port: 8080}
```

Browse through `http://localhost:8080` to capture metrics.

## Analyzing Page Load Performance

### Get Performance Metrics

```json
proxylog {proxy_id: "perf", types: ["performance"]}
→ {
    entries: [{
      url: "http://localhost:8080/dashboard",
      navigation: {
        dom_content_loaded: 1250,  // DOM ready
        load_event: 2800           // Fully loaded
      },
      paint: {
        first_paint: 450,              // First pixels
        first_contentful_paint: 680    // First content
      },
      resources: [...]
    }]
  }
```

### Interpret Results

| Metric | Good | Needs Work | Poor |
|--------|------|------------|------|
| First Paint | < 1s | 1-2s | > 2s |
| First Contentful Paint | < 1.5s | 1.5-2.5s | > 2.5s |
| DOM Content Loaded | < 2s | 2-4s | > 4s |
| Load Event | < 3s | 3-5s | > 5s |

## Analyzing Network Performance

### Capture Network Data

```json
proxy {action: "exec", id: "perf", code: "window.__devtool.captureNetwork()"}
→ {
    summary: {
      totalResources: 42,
      totalTransferSize: 2500000,
      totalDuration: 3200,
      byType: {
        script: {count: 8, size: 1800000},
        stylesheet: {count: 3, size: 150000},
        image: {count: 25, size: 450000},
        fetch: {count: 6, size: 100000}
      }
    },
    entries: [...]
  }
```

### Find Slow Resources

```json
// Get all resources sorted by duration
proxy {action: "exec", id: "perf", code: `
  const network = window.__devtool.captureNetwork();
  const slow = network.entries
    .filter(e => e.duration > 500)
    .sort((a, b) => b.duration - a.duration)
    .slice(0, 10);
  slow
`}
→ Top 10 slowest resources
```

### Find Large Resources

```json
proxy {action: "exec", id: "perf", code: `
  const network = window.__devtool.captureNetwork();
  const large = network.entries
    .filter(e => e.transferSize > 100000)
    .sort((a, b) => b.transferSize - a.transferSize);
  large.map(e => ({name: e.name, size: Math.round(e.transferSize/1024) + 'KB'}))
`}
→ Large resources with sizes
```

## API Performance Analysis

### Track API Response Times

```json
proxylog {proxy_id: "perf", types: ["http"], url_pattern: "/api"}
→ {
    entries: [
      {url: "/api/users", duration_ms: 45},
      {url: "/api/products", duration_ms: 1200},  // Slow!
      {url: "/api/cart", duration_ms: 89}
    ]
  }
```

### Find Slow Endpoints

```json
// Filter for slow API calls (>500ms)
proxylog {proxy_id: "perf", types: ["http"], url_pattern: "/api"}
// Then filter results for duration_ms > 500
```

### Analyze Request Patterns

```json
proxylog {proxy_id: "perf", action: "stats"}
→ {
    by_type: {http: 150},
    // Look at request volume
  }
```

### Audit API Efficiency

Where `proxylog` gives raw per-request timing, [`api_audit`](/api/api_audit) scores the *pattern* of requests — serial waterfalls, N+1 fan-out, duplicate calls, and chatty page loads — over the recorded fetch/XHR buffer. Reload the page to populate the buffer, then:

```json
api_audit {proxy_id: "perf"}
→ === API Efficiency Audit: C (72) ===
   API efficiency is moderate. (38 calls analyzed). 3 issues to address

   n-plus-one (1)
     [warning] /api/users/{id} — 12× /api/users/{id} → batch
   waterfall (2)
     [critical] /api/profile — 4 calls run serially, ~820ms wasted vs parallel
```

The audit pinpoints *which* requests to parallelize or batch — not just which are slow individually.

### Audit Loading UX

A page can feel slow even when the network is fast if loaders fire one after another. [`loading_audit`](/api/loading_audit) scores the spinner timeline for **cascades** (serial loader chains) and **fragmentation** (many small spinners where one master loader would do):

```json
loading_audit {proxy_id: "perf"}
→ === Loading UX Audit: B (84) ===
   spinner-cascade (1)
     [warning] .profile-card — 3 loaders fire serially (avatar → bio → stats), ~640ms span
```

Both audits are also rolled into the `auditAll` overall grade — see [Quality & Performance Auditing](/api/frontend/quality-auditing).

## Build Performance

### Monitor Build Times

```json
// Time your build
run {script_name: "build", mode: "foreground"}
→ {runtime: "45.2s"}

// Check for issues
proc {action: "output", process_id: "build", grep: "(warning|slow|large)"}
```

### Analyze Bundle Size

```json
// Run build analysis
run {raw: true, command: "npx", args: ["source-map-explorer", "dist/main.js"], mode: "foreground-raw"}

// Or with bundle analyzer
run {script_name: "build:analyze", mode: "foreground"}
```

## Real-Time Monitoring

### Page Session Analysis

```json
// See all loaded pages
currentpage {proxy_id: "perf"}
→ {
    sessions: [
      {url: "/dashboard", resource_count: 35, error_count: 0},
      {url: "/products", resource_count: 42, error_count: 2}
    ]
  }

// Get details for slow page
currentpage {proxy_id: "perf", action: "get", session_id: "page-1"}
→ Full breakdown of resources and timing
```

### Live Traffic Analysis

```json
// Recent traffic with timing
proxylog {proxy_id: "perf", types: ["http"], since: "1m", limit: 50}
```

## Performance Optimization Workflow

### Step 1: Baseline Measurement

```json
// Navigate to page
// Get current performance
proxylog {proxy_id: "perf", types: ["performance"]}
→ {navigation: {load_event: 4500}}  // 4.5s - too slow

proxy {action: "exec", id: "perf", code: "window.__devtool.captureNetwork()"}
→ {summary: {totalTransferSize: 3500000}}  // 3.5MB
```

### Step 2: Identify Bottlenecks

```json
// Find blocking resources
proxy {action: "exec", id: "perf", code: `
  const network = window.__devtool.captureNetwork();
  network.entries
    .filter(e => e.renderBlockingStatus === 'blocking' || e.type === 'script')
    .sort((a, b) => b.duration - a.duration)
`}

// Find large JS bundles
proxy {action: "exec", id: "perf", code: `
  const network = window.__devtool.captureNetwork();
  network.entries
    .filter(e => e.type === 'script' && e.transferSize > 50000)
`}
```

### Step 3: Make Improvements

Based on findings:
- Add code splitting for large bundles
- Lazy load below-fold images
- Add caching headers
- Compress assets

### Step 4: Verify Improvement

```json
// After changes, measure again
proxylog {proxy_id: "perf", types: ["performance"]}
→ {navigation: {load_event: 2100}}  // 2.1s - improved!

proxy {action: "exec", id: "perf", code: "window.__devtool.captureNetwork()"}
→ {summary: {totalTransferSize: 1200000}}  // 1.2MB - improved!
```

## Core Web Vitals

### Collect Web Vitals

```json
proxy {action: "exec", id: "perf", code: `
  const perf = window.__devtool.captureNetwork();
  const paint = performance.getEntriesByType('paint');
  const nav = performance.getEntriesByType('navigation')[0];

  ({
    LCP: paint.find(p => p.name === 'largest-contentful-paint')?.startTime,
    FCP: paint.find(p => p.name === 'first-contentful-paint')?.startTime,
    TTFB: nav?.responseStart,
    // CLS and FID require PerformanceObserver
  })
`}
```

### Targets

| Metric | Good | Needs Improvement | Poor |
|--------|------|-------------------|------|
| LCP | < 2.5s | 2.5-4s | > 4s |
| FID | < 100ms | 100-300ms | > 300ms |
| CLS | < 0.1 | 0.1-0.25 | > 0.25 |
| TTFB | < 800ms | 800-1800ms | > 1800ms |

## Layout Performance

### Find Layout Thrashing

```json
proxy {action: "exec", id: "perf", code: "window.__devtool.diagnoseLayout()"}
→ {
    overflows: [...],
    summary: {overflowCount: 3}
  }
```

### Check for Forced Reflow

```json
// This is a code inspection rather than runtime check
// Look for patterns that cause layout thrashing
proxy {action: "exec", id: "perf", code: `
  // Check for large DOM trees
  document.querySelectorAll('*').length
`}
```

## Monitoring Dashboard Example

```json
// Create a simple performance dashboard
proxy {action: "exec", id: "perf", code: `
  const metrics = {};

  // Page load
  const perf = proxylog({types: ['performance']});
  metrics.pageLoad = perf.entries[0]?.navigation?.load_event;

  // Resource count
  const network = window.__devtool.captureNetwork();
  metrics.resourceCount = network.summary.totalResources;
  metrics.totalSize = Math.round(network.summary.totalTransferSize / 1024) + 'KB';

  // Error count
  const errors = proxylog({types: ['error']});
  metrics.errorCount = errors.entries.length;

  metrics
`}
```

## Best Practices

1. **Always baseline first** - Measure before optimizing
2. **Focus on user-centric metrics** - LCP, FID, CLS
3. **Check both fast and slow connections** - Use browser throttling
4. **Monitor over time** - Performance can regress
5. **Test real pages** - Home page often differs from inner pages
6. **Check mobile** - Often slower than desktop

## Common Performance Issues

| Issue | Detection | Solution |
|-------|-----------|----------|
| Large JS bundles | `captureNetwork()` by type | Code splitting |
| Render-blocking CSS | Check resource timing | Inline critical CSS |
| Slow API calls | `proxylog` by URL pattern | Caching, optimization |
| Too many requests | `captureNetwork()` count | Bundling, sprites |
| Large images | `captureNetwork()` by size | Compression, lazy load |

## See Also

- [Reverse Proxy](/features/reverse-proxy) - Traffic capture
- [Frontend Diagnostics](/features/frontend-diagnostics) - Network capture
- [Debugging Web Apps](/use-cases/debugging-web-apps) - General debugging
