profile-tests

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

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.
使用统一性能剖析库对elements包中的测试进行CPU性能分析,可识别性能瓶颈、生成优化建议并检测反模式。

Quick Commands

快速命令

Profile Browser Tests (Simple)

浏览器测试性能剖析(简易版)

bash
undefined
bash
undefined

Built-in profiling for all browser tests

对所有浏览器测试进行内置性能剖析

./scripts/browsertest --profile
./scripts/browsertest --profile

Profile specific test file

剖析指定测试文件

./scripts/browsertest --profile packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
./scripts/browsertest --profile packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts

Profile with test pattern

按测试模式进行剖析

./scripts/browsertest --profile -t "batch capture"
undefined
./scripts/browsertest --profile -t "batch capture"
undefined

Profile Browser Tests (Detailed Analysis)

浏览器测试性能剖析(详细分析版)

bash
undefined
bash
undefined

Full analysis with unified profiling library

使用统一性能剖析库进行全面分析

npx tsx scripts/profile-browsertest.ts
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
npx tsx scripts/profile-browsertest.ts
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts

Get JSON output for LLM analysis

获取JSON输出用于LLM分析

npx tsx scripts/profile-browsertest.ts
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
--json
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
undefined
npx tsx scripts/profile-browsertest.ts
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
--focus renderToImage
--json
undefined

Profile Scenarios

场景性能剖析

bash
undefined
bash
undefined

Profile a scenario in sandbox

剖析沙箱中的场景

./scripts/ef profile EFCanvas basic --json
./scripts/ef profile EFCanvas basic --json

With pattern detection

启用模式检测

./scripts/ef profile EFCanvas basic --json --verbose
./scripts/ef profile EFCanvas basic --json --verbose

Compare against baseline

与基准版本对比

./scripts/ef profile EFCanvas basic
--baseline .profiles/baseline.cpuprofile
--json
undefined
./scripts/ef profile EFCanvas basic
--baseline .profiles/baseline.cpuprofile
--json
undefined

Performance Investigation Workflow

性能排查流程

When investigating performance issues in tests:
排查测试中的性能问题时:

1. Capture Initial Profile

1. 捕获初始性能剖析数据

bash
undefined
bash
undefined

For browser tests

针对浏览器测试

npx tsx scripts/profile-browsertest.ts
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
--json > profile.json
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
undefined
./scripts/ef profile EFCanvas basic --json > profile.json
undefined

2. Analyze JSON Output

2. 分析JSON输出

Parse the profile to identify:
json
{
  "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..."
    }
  ]
}
解析性能剖析数据以识别:
json
{
  "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被调用234次 - 考虑添加缓存"
  ],
  "patterns": [
    {
      "name": "检测到热循环",
      "severity": "high",
      "suggestion": "审查循环逻辑..."
    }
  ]
}

3. Prioritize Optimizations

3. 优先处理优化项

Focus on:
  • Functions with
    selfTimePct > 15%
    (critical bottlenecks)
  • Functions with
    callCount > 100
    and
    selfTimePct > 5%
    (caching opportunities)
  • Files with
    timePct > 40%
    (architectural issues)
  • Patterns with
    severity: "high"
重点关注:
  • selfTimePct > 15%
    的函数(关键瓶颈)
  • callCount > 100
    selfTimePct > 5%
    的函数(缓存优化机会)
  • timePct > 40%
    的文件(架构层面问题)
  • severity: "high"
    的模式

4. Make Changes

4. 实施优化

Apply optimizations based on patterns detected.
根据检测到的模式应用优化方案。

5. Validate with Baseline Comparison

5. 通过基准对比验证优化效果

bash
undefined
bash
undefined

Save baseline before changes

在修改前保存基准版本

./scripts/ef profile EFCanvas basic
--save .profiles/baseline-$(date +%Y%m%d-%H%M%S).cpuprofile
./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 ⚠️
./scripts/ef profile EFCanvas basic
--baseline .profiles/baseline-TIMESTAMP.cpuprofile
--json

查看对比输出:
- 负的`selfTimeDiffMs` = 性能提升 ✅
- 正的`selfTimeDiffMs` = 性能退化 ⚠️

Understanding Profile Metrics

理解性能剖析指标

Key Metrics

核心指标

MetricMeaningUse For
selfTimeMs
Time in function itself (excluding callees)Direct optimization target
selfTimePct
Percentage of total profile timePrioritization (>15% = critical)
callCount
Times function appears in call stacksCaching/memoization decisions
hitCount
Profile samples that caught functionLoop detection (>200 = tight loop)
指标含义适用场景
selfTimeMs
函数自身执行时间(不包含调用其他函数的时间)直接优化目标
selfTimePct
占总剖析时间的百分比优先级判定(>15% = 关键级)
callCount
函数在调用栈中出现的次数缓存/记忆化决策依据
hitCount
捕获到该函数的剖析样本数循环检测(>200 = 密集循环)

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
统一性能剖析库可检测8种常见反模式:
过度DOM操作 → 批量更新DOM或使用DocumentFragment 布局抖动 → 将布局读取与写入操作分离 热循环 → 优化循环体或减少迭代次数 千刀万剐式性能损耗 → 为频繁调用的函数添加记忆化 重型JSON操作 → 使用结构化克隆或减少序列化操作 频繁样式计算 → 缓存计算后的样式 Animation API开销 → 缓存动画对象 文件级耗时集中 → 需要进行架构审查

Common Optimization Patterns

常见优化模式

High Call Count (>100) + Moderate Time (5-15%)

高调用次数(>100)+ 中等耗时(5-15%)

Problem: Function called frequently with small individual cost Solution: Memoization or caching
typescript
// 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;
}
问题: 函数调用频繁,单次调用成本较低 解决方案: 添加记忆化或缓存
typescript
// 优化前
function expensiveCalculation(x: number) {
  return /* 复杂计算 */;
}

// 优化后
const cache = new Map<number, number>();
function expensiveCalculation(x: number) {
  if (cache.has(x)) return cache.get(x)!;
  const result = /* 复杂计算 */;
  cache.set(x, result);
  return result;
}

High Self Time (>30%) + Low Call Count (<10)

高自身耗时(>30%)+ 低调用次数(<10)

Problem: Single function doing too much work Solution: Reduce complexity or defer work
typescript
// Before
function processAll() {
  // All work done synchronously
  loadData();
  transformData();
  validateData();
  saveData();
}

// After  
function processAll() {
  loadData(); // Only critical work
  queueMicrotask(() => {
    transformData();
    validateData();
    saveData();
  });
}
问题: 单个函数承担过多工作 解决方案: 降低复杂度或延迟非关键工作
typescript
// 优化前
function processAll() {
  // 所有工作同步执行
  loadData();
  transformData();
  validateData();
  saveData();
}

// 优化后  
function processAll() {
  loadData(); // 仅执行关键工作
  queueMicrotask(() => {
    transformData();
    validateData();
    saveData();
  });
}

DOM Manipulation Pattern Detected

检测到DOM操作模式

Problem: Multiple DOM updates causing reflows Solution: Batch updates
typescript
// 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
问题: 多次DOM更新导致重排 解决方案: 批量更新
typescript
// 优化前
for (const item of items) {
  container.appendChild(createItem(item)); // 多次重排
}

// 优化后
const fragment = document.createDocumentFragment();
for (const item of items) {
  fragment.appendChild(createItem(item));
}
container.appendChild(fragment); // 单次重排

Output Formats

输出格式

Text Output (Human-Readable)

文本输出(易读版)

bash
./scripts/ef profile EFCanvas basic
Shows:
  • Top hotspots by self time
  • Time aggregated by file
  • Automated recommendations
  • Detected patterns (with --verbose)
bash
./scripts/ef profile EFCanvas basic
展示内容:
  • 按自身耗时排序的顶级性能热点
  • 按文件聚合的耗时统计
  • 自动化优化建议
  • 检测到的模式(启用--verbose时)

JSON Output (LLM/Script-Friendly)

JSON输出(适用于LLM/脚本分析)

bash
./scripts/ef profile EFCanvas basic --json
Structured data for programmatic analysis:
  • Ranked hotspots with metrics
  • File-level aggregations
  • Recommendations array
  • Pattern detection results
bash
./scripts/ef profile EFCanvas basic --json
用于程序化分析的结构化数据:
  • 带指标的排序后性能热点
  • 文件级聚合数据
  • 优化建议数组
  • 模式检测结果

Verbose Mode (Enhanced Analysis)

详细模式(增强分析)

bash
./scripts/ef profile EFCanvas basic --json --verbose
Adds:
  • Call count information
  • Anti-pattern detection
  • Detailed suggestions
bash
./scripts/ef profile EFCanvas basic --json --verbose
新增内容:
  • 调用次数信息
  • 反模式检测
  • 详细优化建议

Specialized Profiling Tools

专用性能剖析工具

Profile Playback Performance

剖析回放性能

bash
npx tsx scripts/profile-playback.ts \
  --project improv-edit \
  --duration 5000 \
  --json
bash
npx tsx scripts/profile-playback.ts \
  --project improv-edit \
  --duration 5000 \
  --json

Profile Export Performance

剖析导出性能

bash
npx tsx scripts/profile-export.ts \
  --project design-catalog \
  --json
bash
npx tsx scripts/profile-export.ts \
  --project design-catalog \
  --json

Profile Page Load

剖析页面加载性能

bash
npx tsx scripts/profile-load.ts \
  --project improv-edit \
  --json
bash
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
    hitCount
    for sampling-based frequency instead
"性能剖析功能不可用"
  • 确保浏览器由Playwright控制(使用
    ef open
    ,而非普通浏览器)
"性能剖析数据为空"
  • 场景/测试可能执行过快(<10ms)
  • 尝试运行耗时更长的测试或增加测试复杂度
"数值异常无意义"
  • 检查时间单位是微秒还是毫秒
  • 统一库返回的是毫秒
  • 旧接口可能使用微秒
"调用次数统计异常"
  • 调用次数是基于调用栈遍历的近似值
  • 如需基于采样的频率统计,请使用
    hitCount

Best Practices

最佳实践

  1. Always save baselines before making changes
  2. Focus on self time for direct impact (total time includes callees)
  3. Start with top 3 hotspots for biggest impact
  4. Use JSON output for programmatic analysis
  5. Check patterns before manual analysis - they suggest specific fixes
  6. Validate changes by comparing before/after profiles
  7. Watch for regressions in baseline comparisons
  1. 修改前务必保存基准版本
  2. 聚焦自身耗时以获得直接优化效果(总耗时包含调用其他函数的时间)
  3. 从Top3性能热点入手以获得最大优化收益
  4. 使用JSON输出进行程序化分析
  5. 先查看模式检测结果再进行手动分析——模式会给出具体修复方向
  6. 通过前后对比验证优化效果
  7. 在基准对比中关注性能退化情况

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/
  • 完整性能剖析指南:
    elements/PROFILING.md
  • LLM专用指南:
    elements/LLM_PROFILING_GUIDE.md
  • 实现细节:
    elements/PROFILING_IMPLEMENTATION_SUMMARY.md
  • 库源码:
    packages/elements/src/profiling/