Skip to main content

Performance Monitoring

Dev-only Import

Performance monitoring utilities are exported from rn-iconify/dev to keep production bundles lean.

Monitor and optimize icon loading performance in your app with built-in metrics collection.

Enable Monitoringโ€‹

Enable performance monitoring in development:

import { enablePerformanceMonitoring, getPerformanceReport } from 'rn-iconify/dev';

// Enable monitoring
enablePerformanceMonitoring();

// Later, retrieve the report
const report = getPerformanceReport();
console.log(`Cache hit rate: ${(report.cacheStats.hitRate * 100).toFixed(1)}%`);
console.log(`Avg load time: ${report.summary.avgLoadTime.toFixed(2)}ms`);

Performance Reportโ€‹

The report object contains comprehensive metrics:

interface PerformanceReport {
summary: {
avgLoadTime: number;
minLoadTime: number;
maxLoadTime: number;
p50LoadTime: number;
p90LoadTime: number;
p99LoadTime: number;
totalLoads: number;
totalErrors: number;
uptime: number;
};
cacheStats: {
memoryHits: number;
bundledHits: number;
diskHits: number;
networkFetches: number;
errors: number;
totalRequests: number;
hitRate: number;
};
loadTimesByType: {
memory: number;
bundled: number;
disk: number;
network: number;
};
slowestIcons: Array<{
iconName: string;
avgDuration: number;
count: number;
}>;
mostUsedIcons: Array<{
iconName: string;
count: number;
}>;
/** Recent load events (last 100) */
recentEvents: IconLoadEvent[];
/** Report generation timestamp */
generatedAt: number;
}

Usage Exampleโ€‹

import { useEffect } from 'react';
import { enablePerformanceMonitoring, getPerformanceReport, PerformanceMonitor } from 'rn-iconify/dev';

function App() {
useEffect(() => {
// Enable in development only
if (__DEV__) {
enablePerformanceMonitoring();
}

// Log metrics periodically
const interval = setInterval(() => {
const report = getPerformanceReport();
console.log('Icon Performance:', {
loaded: report.summary.totalLoads,
cacheHitRate: `${(report.cacheStats.hitRate * 100).toFixed(1)}%`,
avgLoadTime: `${report.summary.avgLoadTime.toFixed(0)}ms`,
errors: report.summary.totalErrors,
});
}, 10000);

return () => clearInterval(interval);
}, []);

return <MainApp />;
}

Debug Componentโ€‹

Create a debug overlay for development:

import { useState, useEffect } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { enablePerformanceMonitoring, getPerformanceReport } from 'rn-iconify/dev';

function IconDebugOverlay() {
const [report, setReport] = useState(getPerformanceReport());

useEffect(() => {
enablePerformanceMonitoring();

const interval = setInterval(() => {
setReport(getPerformanceReport());
}, 1000);

return () => clearInterval(interval);
}, []);

if (!__DEV__) return null;

return (
<View style={styles.overlay}>
<Text style={styles.title}>Icon Metrics</Text>
<Text style={styles.metric}>
Loaded: {report.summary.totalLoads}
</Text>
<Text style={styles.metric}>
Cache: {(report.cacheStats.hitRate * 100).toFixed(0)}%
</Text>
<Text style={styles.metric}>
Avg: {report.summary.avgLoadTime.toFixed(0)}ms
</Text>
<Text style={styles.metric}>
Errors: {report.summary.totalErrors}
</Text>
</View>
);
}

const styles = StyleSheet.create({
overlay: {
position: 'absolute',
top: 50,
right: 10,
backgroundColor: 'rgba(0,0,0,0.8)',
padding: 10,
borderRadius: 8,
zIndex: 9999,
},
title: {
color: 'white',
fontWeight: 'bold',
marginBottom: 5,
},
metric: {
color: 'white',
fontSize: 12,
},
});

Bundle Statisticsโ€‹

Analyze bundle statistics:

import { loadOfflineBundle, getBundleStats } from 'rn-iconify';
import iconBundle from './assets/icons.bundle.json';

// Get statistics from bundle before loading
const stats = getBundleStats(iconBundle);
console.log('Bundle stats:', {
totalIcons: stats.iconCount,
prefixes: stats.prefixes,
sizeKB: (stats.estimatedSizeBytes / 1024).toFixed(2),
generatedAt: stats.generatedAt,
});

// Load the bundle
loadOfflineBundle(iconBundle);

Identify Slow Iconsโ€‹

Find icons that are slow to load:

import { getPerformanceReport } from 'rn-iconify/dev';

function analyzeSlowIcons() {
const report = getPerformanceReport();

// Get slowest icons from the report
const slowIcons = report.slowestIcons.filter(icon => icon.avgDuration > 500);

if (slowIcons.length > 0) {
console.warn('Slow loading icons:', slowIcons);
}

return slowIcons;
}

Subscribe to Eventsโ€‹

Listen for icon load events in real-time:

import { PerformanceMonitor, enablePerformanceMonitoring } from 'rn-iconify/dev';

// Enable monitoring first
enablePerformanceMonitoring();

// Subscribe to events
const unsubscribe = PerformanceMonitor.subscribe((event) => {
if (event.type === 'error') {
console.error(`Failed to load icon: ${event.iconName}`, event.error);
} else if (event.duration > 500) {
console.warn(`Slow icon: ${event.iconName} took ${event.duration}ms`);
}
});

// Unsubscribe when done
unsubscribe();

Print a formatted report to the console:

import { printPerformanceReport, enablePerformanceMonitoring } from 'rn-iconify/dev';

// Enable and later print
enablePerformanceMonitoring();

// After some time, print formatted report
printPerformanceReport();

Output:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ rn-iconify Performance Report โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Total Loads: 150 โ”‚ Errors: 0 โ”‚
โ”‚ Cache Hit Rate: 94.7% โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Load Times โ”‚
โ”‚ Average: 12.34ms โ”‚
โ”‚ Min: 0.12ms โ”‚ Max: 234.56ms โ”‚
โ”‚ P50: 8.00ms โ”‚ P90: 45.00ms โ”‚ P99: 120.00ms โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ By Source โ”‚
โ”‚ Memory: 0.15ms (89 hits) โ”‚
โ”‚ Bundled: 0.10ms (42 hits) โ”‚
โ”‚ Disk: 1.20ms (11 hits) โ”‚
โ”‚ Network: 156.00ms (8 fetches) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Reset Monitoringโ€‹

Clear all performance data:

import { PerformanceMonitor, getPerformanceReport } from 'rn-iconify/dev';

// Reset all metrics
PerformanceMonitor.reset();

// Metrics are now zeroed
const report = getPerformanceReport();
console.log(report.summary.totalLoads); // 0

Optimization Recommendationsโ€‹

Based on metrics, optimize your icon usage:

High Network Fetchesโ€‹

If networkFetches is high, consider:

import { prefetchIcons } from 'rn-iconify';

// Prefetch commonly used icons at app start
async function initApp() {
await prefetchIcons([
'mdi:home',
'mdi:settings',
'mdi:account',
// ... frequently used icons
]);
}

Low Cache Hit Rateโ€‹

If hitRate is low:

  1. Check cache configuration:
import { configure } from 'rn-iconify';

configure({
cache: {
maxMemoryItems: 1000, // Increase max cached icons
enableDiskCache: true,
},
});
  1. Use Babel plugin for critical icons:
// babel.config.js
module.exports = {
plugins: [
['rn-iconify/babel', {
include: ['mdi:home', 'mdi:settings'],
}],
],
};

High Average Load Timeโ€‹

If avgLoadTime is high:

  1. Use local Iconify server:
import { configure } from 'rn-iconify';

configure({
api: {
apiUrl: 'http://localhost:3000',
},
});
  1. Bundle critical icons:
// babel.config.js
module.exports = {
plugins: [
['rn-iconify/babel', {
include: ['mdi:*'], // Bundle all MDI icons
}],
],
};

Performance Targetsโ€‹

Recommended targets for good icon performance:

MetricTargetAction if Poor
Cache Hit Rate> 90%Increase cache size, prefetch icons
Avg Load Time< 100msUse local server, bundle critical icons
Errors0Check network, validate icon names

Best Practicesโ€‹

1. Development Onlyโ€‹

if (__DEV__) {
enablePerformanceMonitoring();
}

2. Regular Monitoringโ€‹

useEffect(() => {
const interval = setInterval(() => {
const report = getPerformanceReport();
// Analyze and log
}, 5000);

return () => clearInterval(interval);
}, []);

3. Set Performance Budgetโ€‹

function checkIconBudget() {
const report = getPerformanceReport();

if (report.summary.avgLoadTime > 200) {
console.warn('Icon load time exceeds budget');
}

if (report.cacheStats.hitRate < 0.8) {
console.warn('Cache hit rate below target');
}
}

Disable Monitoringโ€‹

Disable when not needed:

import { disablePerformanceMonitoring } from 'rn-iconify/dev';

disablePerformanceMonitoring();

PerformanceMonitor APIโ€‹

The PerformanceMonitor object provides detailed access to performance data.

getSummaryโ€‹

Get performance summary with percentiles:

import { PerformanceMonitor } from 'rn-iconify/dev';

const summary = PerformanceMonitor.getSummary();

console.log({
totalLoads: summary.totalLoads,
avgLoadTime: summary.avgLoadTime,
p50: summary.p50LoadTime, // median
p90: summary.p90LoadTime, // 90th percentile
p99: summary.p99LoadTime, // 99th percentile
totalErrors: summary.totalErrors,
uptime: summary.uptime,
});

getEventsโ€‹

Get all recorded load events:

import { PerformanceMonitor } from 'rn-iconify/dev';

const events = PerformanceMonitor.getEvents();

events.forEach(event => {
console.log({
icon: event.iconName,
duration: event.duration,
type: event.type, // 'memory_hit' | 'bundled_hit' | 'disk_hit' | 'network_fetch' | 'error'
timestamp: event.timestamp,
error: event.error, // Only present if type is 'error'
});
});

getCacheStatsโ€‹

Get cache-specific statistics:

import { PerformanceMonitor } from 'rn-iconify/dev';

const stats = PerformanceMonitor.getCacheStats();

console.log({
memoryHits: stats.memoryHits,
bundledHits: stats.bundledHits,
diskHits: stats.diskHits,
networkFetches: stats.networkFetches,
errors: stats.errors,
totalRequests: stats.totalRequests,
hitRate: stats.hitRate,
});

subscribeโ€‹

Subscribe to real-time load events:

import { PerformanceMonitor } from 'rn-iconify/dev';

const unsubscribe = PerformanceMonitor.subscribe((event) => {
// Called for every icon load
console.log(`${event.iconName}: ${event.duration}ms from ${event.type}`);

if (event.type === 'error') {
console.error(`Failed to load ${event.iconName}:`, event.error);
}
});

// Cleanup
return () => unsubscribe();

isEnabledโ€‹

Check if monitoring is enabled:

import { PerformanceMonitor } from 'rn-iconify/dev';

if (PerformanceMonitor.isEnabled()) {
console.log('Performance monitoring is active');
}

Next Stepsโ€‹