CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-devtools-experimental

Experimental rewrite of React DevTools extension for debugging React applications with improved performance and multi-root support

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

performance-profiling.mddocs/

Performance Profiling

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.

Capabilities

Profiling Data Types

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}`);
});

Commit Analysis

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)`);

Profiler Tree Nodes

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);

Profiling Cache System

ProfilingCache Class

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>
  );
}

Resource Creation

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>
  );
}

Profiling Control Flow

Starting Profiling Sessions

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);
});

Stopping and Analyzing

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}`);
  });
}

Advanced Profiling Features

Interaction Tracing

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;
  });
}

Flame Graph Data

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>
  ));
}

Performance Metrics

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)}`);

docs

backend-agent.md

bridge-communication.md

data-hydration.md

devtools-ui.md

frontend-store.md

hook-system.md

index.md

performance-profiling.md

tile.json