CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-speedscope

A fast, interactive web-based viewer for performance profiles with support for multiple profiler formats

Pending
Overview
Eval results
Files

data-structures.mddocs/

Data Structures

Core data structures for representing performance profiles, call trees, and frame information with weight calculations and hierarchical relationships.

Capabilities

Profile Classes

Core classes for representing performance profiling data.

/**
 * Main profile class representing a complete performance profile
 * Contains timing data, call trees, and metadata
 */
class Profile {
  /** Get the human-readable name of this profile */
  getName(): string;
  
  /** Set the name of this profile */
  setName(name: string): void;
  
  /** Get the unit of measurement for weights (e.g., 'milliseconds', 'bytes') */
  getWeightUnit(): string;
  
  /** Get the total weight/duration of this profile */
  getTotalWeight(): number;
  
  /** Get the formatter for displaying weight values */
  getValueFormatter(): ValueFormatter;
  
  /** Get the number of samples in this profile */
  getSampleCount(): number;
  
  /** Check if this profile has timing information */
  getHasTiming(): boolean;
  
  /** Get the minimum timestamp in the profile */
  getMinValue(): number;
  
  /** Get the maximum timestamp in the profile */
  getMaxValue(): number;
}

/**
 * Collection of related profiles, typically from the same profiling session
 */
interface ProfileGroup {
  /** Human-readable name for this group of profiles */
  name: string;
  
  /** Index of the profile to display by default */
  indexToView: number;
  
  /** Array of profiles in this group */
  profiles: Profile[];
}

Frame Representation

Classes and interfaces for representing individual stack frames.

/**
 * Metadata for a stack frame
 */
interface FrameInfo {
  /** Unique identifier for this frame */
  key: string | number;
  
  /** Display name of the frame (e.g., function name) */
  name: string;
  
  /** Source file path (optional) */
  file?: string;
  
  /** Line number in source file (1-based, optional) */
  line?: number;
  
  /** Column number in source file (1-based, optional) */
  col?: number;
}

/**
 * Stack frame with timing and weight information
 * Extends HasWeights to track self and total time/memory usage
 */
class Frame extends HasWeights {
  /** Unique identifier for this frame */
  key: string | number;
  
  /** Display name of the frame */
  name: string;
  
  /** Source file path (optional) */
  file?: string;
  
  /** Line number in source file (optional) */
  line?: number;
  
  /** Column number in source file (optional) */
  col?: number;
  
  /** 
   * Create a new frame from frame info
   * @param frameInfo - Metadata for the frame
   */
  constructor(frameInfo: FrameInfo);
}

/**
 * Base class providing weight tracking functionality
 * Used by Frame and CallTreeNode to track timing/memory data
 */
class HasWeights {
  /** Get the self weight (time spent directly in this frame) */
  getSelfWeight(): number;
  
  /** Get the total weight (time spent in this frame and all children) */
  getTotalWeight(): number;
  
  /** Add to the total weight */
  addToTotalWeight(delta: number): void;
  
  /** Add to the self weight */
  addToSelfWeight(delta: number): void;
  
  /** Copy weights from another HasWeights instance */
  overwriteWeightWith(other: HasWeights): void;
}

Call Tree Structure

Classes for representing hierarchical call relationships.

/**
 * Node in a call tree representing a function call with timing data
 * Each node tracks its frame, parent, children, and weight information
 */
class CallTreeNode extends HasWeights {
  /** The frame this node represents */
  frame: Frame;
  
  /** Parent node in the call tree (null for root) */
  parent: CallTreeNode | null;
  
  /** Child nodes representing functions called from this frame */
  children: CallTreeNode[];
  
  /** 
   * Create a new call tree node
   * @param frame - The frame this node represents
   * @param parent - Parent node (null for root)
   */
  constructor(frame: Frame, parent: CallTreeNode | null);
  
  /** Check if this is a root node (has no parent) */
  isRoot(): boolean;
  
  /** Get or create a child node for the given frame */
  getOrInsertChildWithFrame(frame: Frame): CallTreeNode;
}

Profile Builders

Builder classes for constructing profiles from raw profiling data.

/**
 * Builder for call tree based profiles (hierarchical timing data)
 * Used for profiles that track function call relationships over time
 */
class CallTreeProfileBuilder {
  /** 
   * Create a new call tree profile builder
   * @param valueFormatter - Formatter for displaying timing values
   */
  constructor(valueFormatter?: ValueFormatter);
  
  /** Get the root node of the call tree */
  getRoot(): CallTreeNode;
  
  /** 
   * Enter a frame (start timing)
   * @param frame - Frame being entered
   * @param at - Timestamp when frame was entered
   */
  enterFrame(frame: Frame, at: number): void;
  
  /** 
   * Leave a frame (end timing)
   * @param frame - Frame being left  
   * @param at - Timestamp when frame was left
   */
  leaveFrame(frame: Frame, at: number): void;
  
  /** Build the final profile from collected data */
  build(): Profile;
}

/**
 * Builder for sampled profiles (periodic sampling data)
 * Used for profiles that capture stack samples at regular intervals
 */
class StackListProfileBuilder {
  /** 
   * Create a new stack list profile builder
   * @param valueFormatter - Formatter for displaying sample values
   */
  constructor(valueFormatter?: ValueFormatter);
  
  /** 
   * Append a stack sample
   * @param stack - Array of frames representing the call stack
   * @param weight - Weight/duration of this sample
   */
  appendSample(stack: Frame[], weight: number): void;
  
  /** Build the final profile from collected samples */
  build(): Profile;
}

Symbol Remapping

Type definitions for remapping symbols to source locations.

/**
 * Function type for remapping frame symbols
 * Used to map minified/compiled symbols back to source names and locations
 */
type SymbolRemapper = (
  frame: Frame
) => {
  name?: string;
  file?: string; 
  line?: number;
  col?: number;
} | null;

Value Formatters

Classes for formatting profile values for display.

/**
 * Base interface for formatting profile values
 */
interface ValueFormatter {
  /** Format a numeric value for display */
  format(v: number): string;
  
  /** Get the unit string (e.g., 'ms', 'bytes') */
  unit: string;
}

/**
 * Formatter for time values with appropriate unit scaling
 */
class TimeFormatter implements ValueFormatter {
  unit: string;
  format(v: number): string;
}

/**
 * Formatter for byte/memory values with appropriate unit scaling  
 */
class ByteFormatter implements ValueFormatter {
  unit: string;
  format(v: number): string;
}

/**
 * Pass-through formatter that displays raw numeric values
 */
class RawValueFormatter implements ValueFormatter {
  unit: string;
  format(v: number): string;
}

Usage Examples:

import { 
  Profile, 
  Frame, 
  CallTreeProfileBuilder, 
  StackListProfileBuilder,
  TimeFormatter 
} from 'speedscope';

// Create frames for profiling data
const mainFrame = new Frame({
  key: 'main',
  name: 'main',
  file: 'app.js',
  line: 1
});

const helperFrame = new Frame({
  key: 'helper', 
  name: 'helper',
  file: 'utils.js',
  line: 15
});

// Build a call tree profile
const builder = new CallTreeProfileBuilder(new TimeFormatter());
builder.enterFrame(mainFrame, 0);
builder.enterFrame(helperFrame, 10);
builder.leaveFrame(helperFrame, 50);
builder.leaveFrame(mainFrame, 100);

const profile = builder.build();
profile.setName('My Profile');

// Create a profile group
const profileGroup = {
  name: 'Application Profile',
  indexToView: 0,
  profiles: [profile]
};

// Build a sampled profile  
const sampledBuilder = new StackListProfileBuilder(new TimeFormatter());
sampledBuilder.appendSample([mainFrame, helperFrame], 40);
sampledBuilder.appendSample([mainFrame], 20);

const sampledProfile = sampledBuilder.build();

Profile Data Flow

  1. Raw Data: Profiler outputs timing/sampling data in various formats
  2. Import: Format-specific importers parse data into Frame and timing information
  3. Building: ProfileBuilder classes construct Profile objects with call trees or sample lists
  4. ProfileGroup: Related profiles are grouped together with metadata
  5. Visualization: Profile data drives the flamechart and timeline visualizations

Types

// Core profile data structures
type ProfileData = CallTreeProfile | SampledProfile;

interface CallTreeProfile {
  type: 'call-tree';
  root: CallTreeNode;
}

interface SampledProfile {
  type: 'sampled'; 
  samples: StackSample[];
}

interface StackSample {
  stack: Frame[];
  weight: number;
  timestamp?: number;
}

Install with Tessl CLI

npx tessl i tessl/npm-speedscope

docs

cli.md

data-structures.md

file-format.md

import.md

index.md

tile.json