Performance Monitoring
Learn to monitor and measure React Native app performance using various tools and techniques. This is a foundational concept in cross-platform mobile development that professional developers rely on daily. The explanations below are written to be beginner-friendly while covering the depth and nuance that comes from real-world React Native experience. Take your time with each section and practice the examples
Performance Tools
Use Flipper, React DevTools, and native profiling tools to identify performance bottlenecks in your React Native applications.. This is an essential concept that every React Native developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
Key Performance Metrics
- Frame Rate (FPS) - Target 60 FPS for smooth animations
- Memory Usage - Monitor heap size and memory leaks — a critical concept in cross-platform mobile development that you will use frequently in real projects
- Bundle Size - Keep JavaScript bundle under 1MB — a critical concept in cross-platform mobile development that you will use frequently in real projects
- Startup Time - Target < 3 seconds for app launch
- Time to Interactive - When app becomes fully responsive
- Network Performance - API response times and data usage
Performance Monitoring Setup
import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet, ScrollView, TouchableOpacity } from 'react-native';
import { Performance } from 'react-native-performance';
const PerformanceMonitor = () => {
const [metrics, setMetrics] = useState({
fps: 0,
memory: 0,
bundleSize: 0,
startupTime: 0,
});
useEffect(() => {
// Monitor FPS
const fpsInterval = setInterval(() => {
Performance.getFPS().then(fps => {
setMetrics(prev => ({ ...prev, fps }));
});
}, 1000);
// Monitor Memory
const memoryInterval = setInterval(() => {
Performance.getMemoryUsage().then(memory => {
setMetrics(prev => ({ ...prev, memory: memory.usedJSHeapSize }));
});
}, 2000);
// Get Bundle Size
Performance.getBundleSize().then(size => {
setMetrics(prev => ({ ...prev, bundleSize: size }));
});
// Get Startup Time
Performance.getStartupTime().then(time => {
setMetrics(prev => ({ ...prev, startupTime: time }));
});
return () => {
clearInterval(fpsInterval);
clearInterval(memoryInterval);
};
}, []);
const formatBytes = (bytes: number) => {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
const formatTime = (ms: number) => {
return ms < 1000 ? `${ms}ms` : `${(ms / 1000).toFixed(2)}s`;
};
const getPerformanceStatus = (metric: string, value: number) => {
switch (metric) {
case 'fps':
return value >= 55 ? 'excellent' : value >= 45 ? 'good' : 'poor';
case 'memory':
return value < 50 * 1024 * 1024 ? 'excellent' : value < 100 * 1024 * 1024 ? 'good' : 'poor';
case 'bundleSize':
return value < 1024 * 1024 ? 'excellent' : value < 2 * 1024 * 1024 ? 'good' : 'poor';
case 'startupTime':
return value < 2000 ? 'excellent' : value < 3000 ? 'good' : 'poor';
default:
return 'unknown';
}
};
const getStatusColor = (status: string) => {
switch (status) {
case 'excellent': return '#4CAF50';
case 'good': return '#FF9800';
case 'poor': return '#F44336';
default: return '#9E9E9E';
}
};
return (
<ScrollView style={styles.container}>
<Text style={styles.title}>Performance Monitor</Text>
<View style={styles.metricsContainer}>
<View style={styles.metricCard}>
<Text style={styles.metricLabel}>Frame Rate</Text>
<Text style={[styles.metricValue, { color: getStatusColor(getPerformanceStatus('fps', metrics.fps)) }]}>
{metrics.fps.toFixed(1)} FPS
</Text>
<Text style={styles.metricStatus}>
Status: {getPerformanceStatus('fps', metrics.fps)}
</Text>
</View>
<View style={styles.metricCard}>
<Text style={styles.metricLabel}>Memory Usage</Text>
<Text style={[styles.metricValue, { color: getStatusColor(getPerformanceStatus('memory', metrics.memory)) }]}>
{formatBytes(metrics.memory)}
</Text>
<Text style={styles.metricStatus}>
Status: {getPerformanceStatus('memory', metrics.memory)}
</Text>
</View>
<View style={styles.metricCard}>
<Text style={styles.metricLabel}>Bundle Size</Text>
<Text style={[styles.metricValue, { color: getStatusColor(getPerformanceStatus('bundleSize', metrics.bundleSize)) }]}>
{formatBytes(metrics.bundleSize)}
</Text>
<Text style={styles.metricStatus}>
Status: {getPerformanceStatus('bundleSize', metrics.bundleSize)}
</Text>
</View>
<View style={styles.metricCard}>
<Text style={styles.metricLabel}>Startup Time</Text>
<Text style={[styles.metricValue, { color: getStatusColor(getPerformanceStatus('startupTime', metrics.startupTime)) }]}>
{formatTime(metrics.startupTime)}
</Text>
<Text style={styles.metricStatus}>
Status: {getPerformanceStatus('startupTime', metrics.startupTime)}
</Text>
</View>
</View>
<View style={styles.recommendationsContainer}>
<Text style={styles.recommendationsTitle}>Performance Recommendations</Text>
<Text style={styles.recommendation}>
• Use FlatList for large lists instead of ScrollView
</Text>
<Text style={styles.recommendation}>
• Implement lazy loading for images and components
</Text>
<Text style={styles.recommendation}>
• Use useMemo and useCallback for expensive calculations
</Text>
<Text style={styles.recommendation}>
• Optimize images with proper formats and sizes
</Text>
<Text style={styles.recommendation}>
• Remove unused dependencies and code
</Text>
</View>
</ScrollView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#f5f5f5',
},
title: {
fontSize: 24,
fontWeight: 'bold',
textAlign: 'center',
marginBottom: 30,
color: '#333',
},
metricsContainer: {
gap: 15,
},
metricCard: {
backgroundColor: 'white',
padding: 20,
borderRadius: 10,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
metricLabel: {
fontSize: 16,
color: '#666',
marginBottom: 5,
},
metricValue: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 5,
},
metricStatus: {
fontSize: 14,
color: '#999',
},
recommendationsContainer: {
marginTop: 30,
backgroundColor: 'white',
padding: 20,
borderRadius: 10,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
recommendationsTitle: {
fontSize: 18,
fontWeight: 'bold',
color: '#333',
marginBottom: 15,
},
recommendation: {
fontSize: 14,
color: '#666',
marginBottom: 8,
lineHeight: 20,
},
});
export default PerformanceMonitor;