Real-time performance monitoring overlay for React Native apps. Track FPS, memory usage, and component render counts during development.
- JS FPS Monitoring: Track JavaScript thread frame rate in real-time
- Native UI FPS Monitoring: Monitor actual UI thread performance (iOS & Android)
- Memory Tracking: Monitor heap memory usage (Hermes engine supported)
- Render Count Tracking: Monitor component re-render frequency
- Draggable Overlay: Move the HUD anywhere on screen with drag gestures
- Lightweight Overlay: Minimal, toggleable HUD that stays out of your way
- Customizable: Position, theme, and alert thresholds
- Development-Only: Easy to disable for production builds
- TypeScript Support: Full type definitions included
npm install react-native-perf-hud
# or
yarn add react-native-perf-hudRun pod install:
cd ios && pod installNo additional setup required! The native module is automatically linked.
For draggable overlay support, install react-native-gesture-handler:
npm install react-native-gesture-handler
# or
yarn add react-native-gesture-handlerThen enable it in your config:
<PerfMonitorProvider config={{ enabled: __DEV__, draggable: true }}>
<YourApp />
</PerfMonitorProvider>import { PerfMonitorProvider } from 'react-native-perf-hud';
export default function App() {
return (
<PerfMonitorProvider config={{ enabled: __DEV__ }}>
<YourApp />
</PerfMonitorProvider>
);
}That's it! The performance overlay will automatically appear in the top-right corner.
The PerfMonitorProvider accepts a config prop with the following options:
type PerfMonitorConfig = {
enabled?: boolean; // Enable/disable monitoring (default: true)
showOverlay?: boolean; // Show the overlay HUD (default: true)
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
samplingIntervalMs?: number; // Update interval in ms (default: 500)
theme?: 'dark' | 'light' | 'auto'; // Overlay theme (default: 'dark')
zIndex?: number; // Overlay z-index (default: 9999)
draggable?: boolean; // Enable drag to reposition (default: false)
minimized?: boolean; // Start in minimized state (default: false)
alerts?: {
lowFpsThreshold?: number; // FPS threshold for warning (default: 30)
highMemoryThreshold?: number; // Memory threshold in MB (default: 200)
};
};<PerfMonitorProvider
config={{
enabled: __DEV__,
position: 'bottom-right',
theme: 'light',
samplingIntervalMs: 1000,
alerts: {
lowFpsThreshold: 45,
},
}}
>
<YourApp />
</PerfMonitorProvider>Hook to access current performance metrics programmatically.
import { usePerfState } from 'react-native-perf-hud';
function MyComponent() {
const metrics = usePerfState();
console.log(metrics.jsFps); // Current JS FPS
console.log(metrics.renderCount); // Total render count
console.log(metrics.memoryMb); // Memory usage (if available)
return <View>...</View>;
}Hook to track render count for a specific component.
import { useRenderCount } from 'react-native-perf-hud';
function MyComponent() {
const renderCount = useRenderCount('MyComponent');
console.log(`MyComponent rendered ${renderCount} times`);
return <View>...</View>;
}The overlay component is automatically rendered by PerfMonitorProvider when showOverlay: true. You can also render it manually:
import { PerfMonitorProvider, PerfOverlay } from 'react-native-perf-hud';
function App() {
return (
<PerfMonitorProvider config={{ enabled: __DEV__, showOverlay: false }}>
<YourApp />
{/* Render overlay manually */}
<PerfOverlay />
</PerfMonitorProvider>
);
}<PerfMonitorProvider config={{ enabled: __DEV__ }}>
<App />
</PerfMonitorProvider>function ProfileScreen() {
const renderCount = useRenderCount('ProfileScreen');
// Log when renders exceed threshold
useEffect(() => {
if (renderCount > 50) {
console.warn('ProfileScreen re-rendered too many times!');
}
}, [renderCount]);
return <View>...</View>;
}function Dashboard() {
const metrics = usePerfState();
useEffect(() => {
if (metrics.jsFps < 30) {
// Performance degraded, maybe reduce animations
console.warn('Low FPS detected:', metrics.jsFps);
}
}, [metrics.jsFps]);
return <View>...</View>;
}- Tap the overlay: Toggle between expanded and minimized states
- Minimized: Shows only current FPS
- Expanded: Shows all metrics (FPS, Memory, Render Count)
Frame rate of the JavaScript thread, calculated using requestAnimationFrame. Ideal value is 60 FPS. Values below 30 FPS indicate performance issues.
Frame rate of the actual UI thread, measured using platform-specific APIs:
- iOS: CADisplayLink for accurate display refresh rate
- Android: Choreographer for frame timing
Shows "N/A" if native module is not available. This is the most accurate indicator of visual smoothness.
Total number of component renders tracked across all components using useRenderCount(). Helps identify unnecessary re-renders.
Memory usage in MB. Shows heap memory usage when running on Hermes engine. Displays "N/A" for other JS engines or when memory tracking is unavailable.
When draggable: true is enabled in the config (requires react-native-gesture-handler), you can drag the overlay to reposition it anywhere on the screen. The overlay will remember its position while dragging.
- ✅ JS FPS monitoring
- ✅ Expandable/collapsible overlay
- ✅
useRenderCounthook - ✅ Configurable position and theme
- ✅ Memory usage tracking (Hermes support)
- ✅ Draggable overlay
- ✅ Native UI FPS tracking (iOS CADisplayLink, Android Choreographer)
- 🔜 Network request monitoring plugin
- 🔜 React Profiler auto-tracking
- 🔜 Performance alerts and notifications
- 🔜 Export performance data (CSV, JSON)
Contributions are welcome! Please feel free to submit a Pull Request.
MIT
- Ensure
enabled: trueandshowOverlay: truein config - Check that
PerfMonitorProviderwraps your app - Verify no z-index conflicts with other overlays
- Make sure the app is actively rendering
- Check that JavaScript thread is not blocked
- Ensure you have TypeScript 5.0+ installed
- Check that
@types/reactand@types/react-nativeare installed
- Report issues: https://github.com/wonwoo/react-native-perf-hud/issues
- Documentation: https://github.com/wonwoo/react-native-perf-hud#readme