The performance profiling system provides comprehensive React application performance monitoring with interaction tracking, commit analysis, detailed timing data, and Suspense-based data loading for efficient profiling analysis.
Core data structures for representing React performance profiling information.
/**
* User interaction tracking data
*/
interface Interaction {
/** Unique interaction identifier */
id: number;
/** Human-readable interaction name */
name: string;
/** Timestamp when interaction started */
timestamp: number;
}
/**
* Interaction with associated commit information
*/
interface InteractionWithCommits {
/** Unique interaction identifier */
id: number;
/** Human-readable interaction name */
name: string;
/** Timestamp when interaction started */
timestamp: number;
/** Array of commit indices associated with this interaction */
commits: Array<number>;
}
/**
* Collection of interactions for a root
*/
interface Interactions {
/** Array of interactions with their commits */
interactions: Array<InteractionWithCommits>;
/** Root ID these interactions belong to */
rootID: number;
}Usage Examples:
// Access interaction data
const interactions = getInteractionsForRoot(rootID);
interactions.interactions.forEach(interaction => {
console.log(`Interaction: ${interaction.name}`);
console.log(`Started at: ${new Date(interaction.timestamp)}`);
console.log(`Commits: ${interaction.commits.length}`);
});Detailed performance data for individual React commits.
/**
* Detailed performance data for a specific commit
*/
interface CommitDetails {
/** Array of actual render durations for each element */
actualDurations: Array<number>;
/** Index of this commit in the profiling session */
commitIndex: number;
/** Interactions that triggered this commit */
interactions: Array<Interaction>;
/** Root ID this commit belongs to */
rootID: number;
}
/**
* Aggregated profiling statistics for a root
*/
interface ProfilingSummary {
/** Duration of each commit in milliseconds */
commitDurations: Array<number>;
/** Timestamp of each commit */
commitTimes: Array<number>;
/** Initial tree base durations before profiling started */
initialTreeBaseDurations: Array<number>;
/** Total number of interactions recorded */
interactionCount: number;
/** Root ID this summary belongs to */
rootID: number;
}Usage Examples:
// Analyze commit performance
const commitDetails = getCommitDetails(rootID, commitIndex);
console.log(`Commit ${commitIndex}:`);
console.log(`Interactions: ${commitDetails.interactions.length}`);
// Calculate average render time
const avgDuration = commitDetails.actualDurations.reduce((a, b) => a + b, 0) /
commitDetails.actualDurations.length;
console.log(`Average render duration: ${avgDuration}ms`);
// Get profiling summary
const summary = getProfilingSummary(rootID);
console.log(`Total commits: ${summary.commitDurations.length}`);
console.log(`Total interactions: ${summary.interactionCount}`);
// Find slowest commit
const slowestIndex = summary.commitDurations.indexOf(
Math.max(...summary.commitDurations)
);
console.log(`Slowest commit: ${slowestIndex} (${summary.commitDurations[slowestIndex]}ms)`);Data structures representing components in profiler tree visualization.
/**
* Component node in profiler tree
*/
interface Node {
/** Unique element identifier */
id: number;
/** Array of child element IDs */
children: Array<number>;
/** Component display name */
displayName: string | null;
/** React key prop */
key: number | string | null;
/** Parent element ID */
parentID: number;
/** Base duration for this subtree */
treeBaseDuration: number;
}
/**
* Complete commit tree structure
*/
interface CommitTree {
/** Map of element ID to node data */
nodes: Map<number, Node>;
/** Root element ID for this tree */
rootID: number;
}Usage Examples:
// Build commit tree visualization
const commitTree = buildCommitTree(commitData);
const rootNode = commitTree.nodes.get(commitTree.rootID);
function renderNode(node, depth = 0) {
const indent = ' '.repeat(depth);
console.log(`${indent}${node.displayName} (${node.treeBaseDuration}ms)`);
node.children.forEach(childID => {
const childNode = commitTree.nodes.get(childID);
if (childNode) {
renderNode(childNode, depth + 1);
}
});
}
renderNode(rootNode);Suspense-based cache for efficient loading and management of profiling data.
/**
* Suspense-compatible cache for profiling data
* Enables efficient async loading of large profiling datasets
*/
class ProfilingCache {
/**
* Read profiling data for specific parameters
* Suspends if data is not yet available
* @param params - Parameters identifying the data to read
* @returns Profiling data when available
*/
read(params: ProfilingParams): ProfilingData;
/**
* Preload profiling data to warm cache
* @param params - Parameters identifying the data to preload
*/
preload(params: ProfilingParams): void;
/**
* Clear all cached profiling data
*/
invalidate(): void;
}
interface ProfilingParams {
rootID: number;
commitIndex?: number;
interactionID?: number;
}Usage Examples:
import { Suspense } from 'react';
function ProfilingResults({ rootID }) {
return (
<Suspense fallback={<LoadingSpinner />}>
<CommitList rootID={rootID} />
</Suspense>
);
}
function CommitList({ rootID }) {
const store = useContext(StoreContext);
// This will suspend if profiling data is not ready
const profilingSummary = store.profilingCache.read({ rootID });
return (
<div>
{profilingSummary.commitDurations.map((duration, index) => (
<CommitItem
key={index}
rootID={rootID}
commitIndex={index}
duration={duration}
/>
))}
</div>
);
}Creating Suspense-compatible resources for profiling data.
/**
* Create a resource for Suspense-based data loading
* @param fetchFn - Function to fetch the data
* @param keyFn - Optional function to generate cache keys
* @returns Resource that can be read with Suspense
*/
function createResource<Input, Value>(
fetchFn: (input: Input) => Promise<Value>,
keyFn?: (input: Input) => string
): Resource<Input, Value>;
interface Resource<Input, Value> {
read(input: Input): Value;
preload(input: Input): void;
}Usage Examples:
// Create resource for commit details
const commitDetailsResource = createResource(
async ({ rootID, commitIndex }) => {
const response = await bridge.send('get-commit-details', { rootID, commitIndex });
return response.data;
},
({ rootID, commitIndex }) => `commit-${rootID}-${commitIndex}`
);
// Use in component
function CommitDetails({ rootID, commitIndex }) {
// Suspends until data is available
const details = commitDetailsResource.read({ rootID, commitIndex });
return (
<div>
<h3>Commit {commitIndex}</h3>
<p>Duration: {calculateCommitDuration(details)}ms</p>
<InteractionsList interactions={details.interactions} />
</div>
);
}Methods and patterns for initiating performance profiling.
/**
* Start profiling session with optional configuration
* @param options - Profiling configuration options
*/
function startProfiling(options?: ProfilingOptions): void;
interface ProfilingOptions {
/** Include component stack traces */
includeStackTraces?: boolean;
/** Track interaction origins */
trackInteractions?: boolean;
/** Maximum profiling duration in milliseconds */
maxDuration?: number;
}Usage Examples:
// Start basic profiling
store.startProfiling();
// Start profiling with options
store.startProfiling({
includeStackTraces: true,
trackInteractions: true,
maxDuration: 30000 // 30 seconds max
});
// Listen for profiling start
store.on('profiling-started', () => {
showProfilingIndicator();
// Auto-stop after timeout
setTimeout(() => {
if (store.isProfiling) {
store.stopProfiling();
}
}, 30000);
});Methods for ending profiling sessions and accessing results.
/**
* Stop current profiling session
* Triggers data processing and makes results available
*/
function stopProfiling(): void;
/**
* Check if profiling data is available for analysis
* @returns Whether profiling data has been collected
*/
function hasProfilingData(): boolean;Usage Examples:
// Stop profiling and analyze results
store.stopProfiling();
store.on('profiling-stopped', () => {
if (store.hasProfilingData) {
analyzeProfilingResults();
}
});
function analyzeProfilingResults() {
store.roots.forEach(rootID => {
const summary = getProfilingSummary(rootID);
console.log(`Root ${rootID} performance:`);
console.log(` Total commits: ${summary.commitDurations.length}`);
console.log(` Average commit time: ${average(summary.commitDurations)}ms`);
console.log(` Slowest commit: ${Math.max(...summary.commitDurations)}ms`);
console.log(` Interactions: ${summary.interactionCount}`);
});
}Tracking user interactions and their performance impact.
/**
* Trace interaction performance impact
* @param interactionName - Human-readable interaction name
* @param callback - Function to execute during interaction
* @returns Promise resolving when interaction completes
*/
function traceInteraction<T>(
interactionName: string,
callback: () => T
): Promise<T>;Usage Examples:
// Trace button click interaction
await traceInteraction('Button Click', () => {
handleButtonClick();
});
// Trace navigation interaction
await traceInteraction('Navigate to Dashboard', () => {
navigate('/dashboard');
});
// Custom interaction tracking
function trackUserAction(actionName, actionFn) {
return traceInteraction(actionName, () => {
const startTime = performance.now();
const result = actionFn();
const endTime = performance.now();
console.log(`${actionName} took ${endTime - startTime}ms`);
return result;
});
}Generating data for flame graph visualizations.
/**
* Generate flame graph data for commit visualization
* @param commitIndex - Commit to generate flame graph for
* @param rootID - Root ID for the commit
* @returns Flame graph node data
*/
function generateFlameGraphData(
commitIndex: number,
rootID: number
): FlameGraphNode[];
interface FlameGraphNode {
id: number;
name: string;
value: number;
children: FlameGraphNode[];
depth: number;
offset: number;
}Usage Examples:
// Generate flame graph for visualization
const flameGraphData = generateFlameGraphData(commitIndex, rootID);
function renderFlameGraph(nodes, parentWidth = 100) {
return nodes.map(node => (
<div
key={node.id}
style={{
width: `${(node.value / parentWidth) * 100}%`,
backgroundColor: getColorForDuration(node.value),
height: '20px',
position: 'relative'
}}
title={`${node.name}: ${node.value}ms`}
>
{node.children.length > 0 && (
<div style={{ position: 'absolute', top: '20px', left: 0, right: 0 }}>
{renderFlameGraph(node.children, node.value)}
</div>
)}
</div>
));
}Calculating and analyzing performance metrics from profiling data.
/**
* Calculate performance metrics for profiling session
* @param rootID - Root to calculate metrics for
* @returns Performance metrics object
*/
function calculateMetrics(rootID: number): PerformanceMetrics;
interface PerformanceMetrics {
totalTime: number;
averageCommitTime: number;
medianCommitTime: number;
slowestCommitTime: number;
fastestCommitTime: number;
commitCount: number;
interactionCount: number;
componentsAffected: number;
}Usage Examples:
// Calculate and display performance metrics
const metrics = calculateMetrics(rootID);
console.log('Performance Summary:');
console.log(`Total Time: ${metrics.totalTime}ms`);
console.log(`Average Commit: ${metrics.averageCommitTime}ms`);
console.log(`Median Commit: ${metrics.medianCommitTime}ms`);
console.log(`Range: ${metrics.fastestCommitTime}ms - ${metrics.slowestCommitTime}ms`);
console.log(`Commits: ${metrics.commitCount}`);
console.log(`Interactions: ${metrics.interactionCount}`);
console.log(`Components Affected: ${metrics.componentsAffected}`);
// Performance score calculation
function calculatePerformanceScore(metrics) {
const avgTime = metrics.averageCommitTime;
if (avgTime < 16) return 'Excellent'; // 60fps
if (avgTime < 33) return 'Good'; // 30fps
if (avgTime < 100) return 'Fair'; // 10fps
return 'Poor';
}
console.log(`Performance Score: ${calculatePerformanceScore(metrics)}`);