npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

ngx-performance-diagnostics

v1.0.4

Published

Angular library for detecting performance issues, change detection cycles, and memory leaks

Readme

ngx-performance-diagnostics

🔍 Real-time performance monitoring and diagnostics for Angular applications

npm version License: MIT

Detect performance issues, excessive change detection cycles, and memory leaks in your Angular applications with zero configuration. Perfect for development and debugging!

✨ Features

  • 🔍 Change Detection Monitor - Detect components with excessive CD cycles
  • 💾 Memory Leak Detector - Track memory usage and identify leaks
  • 📊 Visual Panels - Real-time diagnostics UI panels
  • 🎯 Zero Config - Works out of the box, no setup required
  • 🚀 Lightweight - Minimal overhead, dev-only friendly
  • 📦 Standalone - Fully compatible with Angular standalone components
  • 🔧 Flexible - Use individual tools or full diagnostic suite

📦 Installation

npm install ngx-performance-diagnostics --save-dev

🚀 Quick Start

1. Add Diagnostic Panels to Your Layout

import { Component } from '@angular/core';
import {
  CdMonitorPanelComponent,
  MemoryLeakPanelComponent
} from 'ngx-performance-diagnostics';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    // ... your imports
    CdMonitorPanelComponent,      // CD Monitor (right panel)
    MemoryLeakPanelComponent,     // Memory Monitor (left panel)
  ],
  template: `
    <router-outlet></router-outlet>

    <!-- Diagnostic panels (development only) -->
    @if (!isProduction) {
      <ngx-cd-monitor-panel></ngx-cd-monitor-panel>
      <ngx-memory-leak-panel></ngx-memory-leak-panel>
    }
  `
})
export class AppComponent {
  isProduction = false; // Set from environment
}

2. Monitor a Component

import { Component } from '@angular/core';
import { ChangeDetectionMonitorDirective } from 'ngx-performance-diagnostics';

@Component({
  selector: 'app-my-component',
  standalone: true,
  imports: [ChangeDetectionMonitorDirective],
  template: `
    <div cdMonitor="MyComponent">
      <!-- Your component content -->
      <h1>{{ title }}</h1>
    </div>
  `
})
export class MyComponent {
  title = 'Hello World';
}

3. Run Chrome with Memory Profiling Flags

# macOS
open -a "Google Chrome" --args --enable-precise-memory-info --expose-gc

# Windows
chrome.exe --enable-precise-memory-info --expose-gc

# Linux
google-chrome --enable-precise-memory-info --expose-gc

4. Start Debugging!

  1. Open your Angular app
  2. Click "Start" in the Memory Panel (bottom-left)
  3. Leave the app idle for 1-2 minutes
  4. Check the panels for issues:
    • CD Monitor (bottom-right): Shows change detection statistics
    • Memory Monitor (bottom-left): Shows memory trends

📖 API Documentation

Change Detection Monitor Directive

Monitor change detection cycles for any component:

<div cdMonitor="ComponentName" [cdMonitorThreshold]="50">
  <!-- Component content -->
</div>

Inputs:

  • cdMonitor: string - Component name for identification
  • cdMonitorThreshold: number - Warning threshold in cycles/second (default: 100)

What it tracks:

  • Cycles per second (c/s)
  • Total checks
  • Average time between checks
  • Min/Max time between checks

Change Detection Monitor Service

Programmatic access to CD statistics:

import { ChangeDetectionMonitorService } from 'ngx-performance-diagnostics';

export class MyComponent implements OnInit {
  constructor(private cdMonitor: ChangeDetectionMonitorService) {}

  ngOnInit() {
    // Subscribe to statistics
    this.cdMonitor.stats$.subscribe(summary => {
      console.log('Active:', summary.activeComponents);
      console.log('Problematic:', summary.problematicComponents);
    });

    // Get current stats
    const stats = this.cdMonitor.getStats();

    // Export to JSON
    const json = this.cdMonitor.exportStats();

    // Clear all stats
    this.cdMonitor.clearStats();
  }
}

Memory Leak Detector Service

Monitor memory usage and detect leaks:

import { MemoryLeakDetectorService } from 'ngx-performance-diagnostics';

export class MyComponent implements OnInit, OnDestroy {
  constructor(private memoryMonitor: MemoryLeakDetectorService) {}

  ngOnInit() {
    // Start monitoring
    this.memoryMonitor.startMonitoring();

    // Get report
    const report = this.memoryMonitor.getReport();
    console.log('Is leaking:', report.isLeaking);
    console.log('Trend:', report.trendPercentPerMinute, '% per minute');

    // Export report
    const json = this.memoryMonitor.exportReport();

    // Force garbage collection (requires --expose-gc flag)
    this.memoryMonitor.forceGC();
  }

  ngOnDestroy() {
    this.memoryMonitor.stopMonitoring();
  }
}

CD Monitor Panel Component

Visual panel showing change detection statistics:

<ngx-cd-monitor-panel></ngx-cd-monitor-panel>

Features:

  • Real-time component statistics
  • Click component to highlight in DOM
  • Export reports to JSON
  • Clear statistics

Memory Leak Panel Component

Visual panel showing memory usage:

<ngx-memory-leak-panel></ngx-memory-leak-panel>

Features:

  • Live memory chart
  • Trend analysis
  • Start/stop monitoring
  • Force garbage collection
  • Export reports to JSON

📊 Interpreting Results

Change Detection Monitor

| c/s (cycles/sec) | Status | Action | |------------------|--------|--------| | < 10 | ✅ Excellent | No action needed | | 10-50 | ⚠️ Acceptable | Monitor | | 50-100 | 🔶 Concerning | Investigate | | > 100 | 🚨 Critical | Fix immediately |

Common issues:

  • Getters in templates
  • Functions called in templates
  • Missing OnPush change detection strategy
  • Unsubscribed observables triggering updates

Memory Leak Detector

| Trend %/min | Status | Action | |-------------|--------|--------| | < 0 | ✅ Decreasing (GC working) | OK | | 0-2 | ✅ Stable | OK | | 2-5 | ⚠️ Suspicious growth | Investigate | | > 5 | 🚨 Leak detected | Fix immediately |

Common issues:

  • Unsubscribed RxJS observables
  • Event listeners not removed
  • Intervals/timeouts not cleared
  • Circular references
  • Large objects in closures

🔧 Common Fixes

Fix 1: Unsubscribed RxJS Observables

// ❌ BAD
ngOnInit() {
  this.service.data$.subscribe(data => this.data = data);
}

// ✅ GOOD - Option 1: takeUntil
private destroy$ = new Subject<void>();

ngOnInit() {
  this.service.data$
    .pipe(takeUntil(this.destroy$))
    .subscribe(data => this.data = data);
}

ngOnDestroy() {
  this.destroy$.next();
  this.destroy$.complete();
}

// ✅ GOOD - Option 2: async pipe (preferred)
@Component({
  template: `<div>{{ data$ | async }}</div>`
})
export class MyComponent {
  data$ = this.service.data$;
}

Fix 2: Getters in Templates

// ❌ BAD - getter called on every CD cycle
get total(): number {
  return this.items.reduce((sum, item) => sum + item.price, 0);
}

// ✅ GOOD - computed once
total = 0;

ngOnChanges() {
  this.total = this.items.reduce((sum, item) => sum + item.price, 0);
}

Fix 3: OnPush Change Detection

// ❌ BAD - Default strategy checks on every event
@Component({
  changeDetection: ChangeDetectionStrategy.Default
})

// ✅ GOOD - OnPush only checks on input changes
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush
})

Fix 4: Event Listeners

// ❌ BAD
ngOnInit() {
  window.addEventListener('resize', this.onResize);
}

// ✅ GOOD
ngOnInit() {
  window.addEventListener('resize', this.onResize);
}

ngOnDestroy() {
  window.removeEventListener('resize', this.onResize);
}

🎯 Usage Patterns

Development Only

import { isDevMode } from '@angular/core';

@Component({
  template: `
    @if (isDevMode()) {
      <ngx-cd-monitor-panel></ngx-cd-monitor-panel>
      <ngx-memory-leak-panel></ngx-memory-leak-panel>
    }
  `
})

Conditional Monitoring

// Monitor only specific components
@Component({
  template: `
    <div [cdMonitor]="shouldMonitor ? 'MyComponent' : null">
      <!-- Content -->
    </div>
  `
})
export class MyComponent {
  shouldMonitor = !environment.production;
}

Custom Thresholds

// Lower threshold for critical components
<div cdMonitor="CriticalComponent" [cdMonitorThreshold]="30">
  <!-- Lower threshold = earlier warnings -->
</div>

🔬 Advanced Usage

Programmatic Monitoring

import {
  ChangeDetectionMonitorService,
  MemoryLeakDetectorService
} from 'ngx-performance-diagnostics';

@Component({/*...*/})
export class DiagnosticsComponent implements OnInit {
  constructor(
    private cdMonitor: ChangeDetectionMonitorService,
    private memoryMonitor: MemoryLeakDetectorService
  ) {}

  ngOnInit() {
    // Start memory monitoring
    this.memoryMonitor.startMonitoring();

    // Check every 10 seconds
    setInterval(() => {
      const cdReport = this.cdMonitor.exportStats();
      const memReport = this.memoryMonitor.exportReport();

      // Send to analytics, log to console, etc.
      this.sendToAnalytics({ cd: cdReport, memory: memReport });
    }, 10000);
  }

  sendToAnalytics(data: any) {
    // Your analytics implementation
  }
}

Custom Export

exportDiagnostics() {
  const report = {
    timestamp: new Date().toISOString(),
    changeDetection: JSON.parse(this.cdMonitor.exportStats()),
    memory: JSON.parse(this.memoryMonitor.exportReport()),
    userAgent: navigator.userAgent,
    url: window.location.href
  };

  // Download or send to server
  this.downloadReport(report);
}

🛠️ Configuration

TypeScript Configuration

No special configuration needed! The library is built with strict mode and full type safety.

Angular Configuration

Works with:

  • ✅ Angular 17+
  • ✅ Angular 18+
  • ✅ Angular 19+
  • ✅ Standalone components
  • ✅ NgModules
  • ✅ Ivy compiler

🤝 Contributing

Contributions are welcome! Please read our Contributing Guide for details.

Development Setup

# Clone repository
git clone https://github.com/maciekv/ngx-performance-diagnostics.git
cd ngx-performance-diagnostics

# Install dependencies
npm install

# Build library
npm run build

# Run tests
npm test

📝 License

MIT © [Maciej Osytek]


🙏 Acknowledgments

Built for the Angular community with ❤️


📞 Support


🗺️ Roadmap

  • [ ] Unit tests
  • [ ] E2E tests
  • [ ] Zone.js integration
  • [ ] Performance timeline integration
  • [ ] Custom reporters
  • [ ] CI/CD performance checks

Happy Debugging! 🐛🔍