profile-tests
Profiling Tests and Browser Tests
CPU profiling for elements package tests using the unified profiling library. Identifies performance bottlenecks, generates optimization recommendations, and detects anti-patterns.
Quick Commands
Profile Browser Tests (Simple)
# Built-in profiling for all browser tests
./scripts/browsertest --profile
# Profile specific test file
./scripts/browsertest --profile packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
# Profile with test pattern
./scripts/browsertest --profile -t "batch capture"
Profile Browser Tests (Detailed Analysis)
# Full analysis with unified profiling library
npx tsx scripts/profile-browsertest.ts \
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
# Get JSON output for LLM analysis
npx tsx scripts/profile-browsertest.ts \
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts \
--json
# Focus on specific file
npx tsx scripts/profile-browsertest.ts \
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts \
--focus renderToImage \
--json
Profile Scenarios
# Profile a scenario in sandbox
./scripts/ef profile EFCanvas basic --json
# With pattern detection
./scripts/ef profile EFCanvas basic --json --verbose
# Compare against baseline
./scripts/ef profile EFCanvas basic \
--baseline .profiles/baseline.cpuprofile \
--json
Performance Investigation Workflow
When investigating performance issues in tests:
1. Capture Initial Profile
# For browser tests
npx tsx scripts/profile-browsertest.ts \
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts \
--json > profile.json
# For scenarios
./scripts/ef profile EFCanvas basic --json > profile.json
2. Analyze JSON Output
Parse the profile to identify:
{
"hotspots": [
{
"rank": 1,
"functionName": "updateFrame",
"file": "EFTimegroup.ts",
"line": 234,
"selfTimeMs": 45.2,
"selfTimePct": 31.1,
"callCount": 234
}
],
"byFile": [
{ "file": "EFTimegroup.ts", "timeMs": 82.1, "timePct": 56.5 }
],
"recommendations": [
"• updateFrame called 234 times - consider caching"
],
"patterns": [
{
"name": "Hot Loop Detected",
"severity": "high",
"suggestion": "Review loop logic..."
}
]
}
3. Prioritize Optimizations
Focus on:
- Functions with
selfTimePct > 15%(critical bottlenecks) - Functions with
callCount > 100andselfTimePct > 5%(caching opportunities) - Files with
timePct > 40%(architectural issues) - Patterns with
severity: "high"
4. Make Changes
Apply optimizations based on patterns detected.
5. Validate with Baseline Comparison
# Save baseline before changes
./scripts/ef profile EFCanvas basic \
--save .profiles/baseline-$(date +%Y%m%d-%H%M%S).cpuprofile
# After optimization, compare
./scripts/ef profile EFCanvas basic \
--baseline .profiles/baseline-TIMESTAMP.cpuprofile \
--json
Check comparison output:
- Negative
selfTimeDiffMs= improvement ✅ - Positive
selfTimeDiffMs= regression ⚠️
Understanding Profile Metrics
Key Metrics
| Metric | Meaning | Use For |
|---|---|---|
selfTimeMs |
Time in function itself (excluding callees) | Direct optimization target |
selfTimePct |
Percentage of total profile time | Prioritization (>15% = critical) |
callCount |
Times function appears in call stacks | Caching/memoization decisions |
hitCount |
Profile samples that caught function | Loop detection (>200 = tight loop) |
Interpreting Patterns
The unified profiling library detects 8 common anti-patterns:
Excessive DOM Manipulation → Batch DOM updates or use DocumentFragment Layout Thrashing → Separate layout reads from writes Hot Loop → Optimize loop body or reduce iterations Death by a Thousand Cuts → Add memoization for frequently-called functions Heavy JSON Operations → Use structured cloning or reduce serialization Frequent Style Computation → Cache computed styles Animation API Overhead → Cache animation objects File-Level Concentration → Architectural review needed
Common Optimization Patterns
High Call Count (>100) + Moderate Time (5-15%)
Problem: Function called frequently with small individual cost Solution: Memoization or caching
// Before
function expensiveCalculation(x: number) {
return /* complex math */;
}
// After
const cache = new Map<number, number>();
function expensiveCalculation(x: number) {
if (cache.has(x)) return cache.get(x)!;
const result = /* complex math */;
cache.set(x, result);
return result;
}
High Self Time (>30%) + Low Call Count (<10)
Problem: Single function doing too much work Solution: Reduce complexity or defer work
// Before
function processAll() {
// All work done synchronously
loadData();
transformData();
validateData();
saveData();
}
// After
function processAll() {
loadData(); // Only critical work
queueMicrotask(() => {
transformData();
validateData();
saveData();
});
}
DOM Manipulation Pattern Detected
Problem: Multiple DOM updates causing reflows Solution: Batch updates
// Before
for (const item of items) {
container.appendChild(createItem(item)); // Multiple reflows
}
// After
const fragment = document.createDocumentFragment();
for (const item of items) {
fragment.appendChild(createItem(item));
}
container.appendChild(fragment); // Single reflow
Output Formats
Text Output (Human-Readable)
./scripts/ef profile EFCanvas basic
Shows:
- Top hotspots by self time
- Time aggregated by file
- Automated recommendations
- Detected patterns (with --verbose)
JSON Output (LLM/Script-Friendly)
./scripts/ef profile EFCanvas basic --json
Structured data for programmatic analysis:
- Ranked hotspots with metrics
- File-level aggregations
- Recommendations array
- Pattern detection results
Verbose Mode (Enhanced Analysis)
./scripts/ef profile EFCanvas basic --json --verbose
Adds:
- Call count information
- Anti-pattern detection
- Detailed suggestions
Specialized Profiling Tools
Profile Playback Performance
npx tsx scripts/profile-playback.ts \
--project improv-edit \
--duration 5000 \
--json
Profile Export Performance
npx tsx scripts/profile-export.ts \
--project design-catalog \
--json
Profile Page Load
npx tsx scripts/profile-load.ts \
--project improv-edit \
--json
Troubleshooting
"Profiling functions not available"
- Ensure browser is controlled by Playwright (use
ef open, not regular browser)
"Profile data is empty"
- Scenario/test may execute too quickly (<10ms)
- Try longer-running tests or increase test complexity
"High numbers don't make sense"
- Check if times are in microseconds vs milliseconds
- Unified library returns milliseconds
- Legacy interfaces may use microseconds
"Call counts seem wrong"
- Call count is approximate based on call stack traversal
- Use
hitCountfor sampling-based frequency instead
Best Practices
- Always save baselines before making changes
- Focus on self time for direct impact (total time includes callees)
- Start with top 3 hotspots for biggest impact
- Use JSON output for programmatic analysis
- Check patterns before manual analysis - they suggest specific fixes
- Validate changes by comparing before/after profiles
- Watch for regressions in baseline comparisons
Additional Resources
- Full profiling guide:
elements/PROFILING.md - LLM-specific guide:
elements/LLM_PROFILING_GUIDE.md - Implementation details:
elements/PROFILING_IMPLEMENTATION_SUMMARY.md - Library source:
packages/elements/src/profiling/
More from editframe/skills
video-analysis
Analyze video files using ffprobe, mp4dump, and jq. Use when investigating video samples, keyframes, MP4 box structure, codec info, packet timing, or debugging video playback issues.
75visual-thinking
Create visual analogies by mapping relational structure from familiar domains onto unfamiliar concepts using spatial relationships to make abstract patterns concrete. Covers static diagrams AND animated video storytelling (camera choreography, race comparisons, pacing). Use when explaining complex concepts, creating analogies, designing diagrams, creating explainer animations, or revealing system structure.
71css-animations
CSS animation fill-mode requirements for Editframe timeline system. Use when creating CSS animations, debugging flashing/flickering issues, or when user mentions animation problems, fade effects, slide effects, or sequential animations.
69threejs-compositions
Integrate Three.js 3D scenes into Editframe compositions via addFrameTask. Scenes are pure functions of time, fully scrubable, and renderable to MP4. Use when creating 3D animations, WebGL content in compositions, or integrating Three.js with Editframe's timeline system.
66editor-gui
Build video editing interfaces using Editframe's GUI web components. Assemble timeline, scrubber, filmstrip, preview, and playback controls like lego bricks. Use when creating video editors, editing tools, or when user mentions timeline, scrubber, preview, playback controls, trim handles, or wants to build editing UIs.
64elements-new-package
Create a new @editframe/* workspace package in the elements monorepo and publish it to npm.
64