profile-tests
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseProfiling 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
undefinedbash
undefinedBuilt-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"
undefinedProfile Browser Tests (Detailed Analysis)
浏览器测试性能剖析(详细分析版)
bash
undefinedbash
undefinedFull analysis with unified profiling library
使用统一性能剖析库进行全面分析
npx tsx scripts/profile-browsertest.ts
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
npx tsx scripts/profile-browsertest.ts
packages/elements/src/preview/renderTimegroupToCanvas.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
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
--json
npx tsx scripts/profile-browsertest.ts
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
--json
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
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
--focus renderToImage
--json
undefinednpx tsx scripts/profile-browsertest.ts
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
--focus renderToImage
--json
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
--focus renderToImage
--json
undefinedProfile Scenarios
场景性能剖析
bash
undefinedbash
undefinedProfile 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
--baseline .profiles/baseline.cpuprofile
--json
undefined./scripts/ef profile EFCanvas basic
--baseline .profiles/baseline.cpuprofile
--json
--baseline .profiles/baseline.cpuprofile
--json
undefinedPerformance Investigation Workflow
性能排查流程
When investigating performance issues in tests:
排查测试中的性能问题时:
1. Capture Initial Profile
1. 捕获初始性能剖析数据
bash
undefinedbash
undefinedFor browser tests
针对浏览器测试
npx tsx scripts/profile-browsertest.ts
packages/elements/src/preview/renderTimegroupToCanvas.browsertest.ts
--json > profile.json
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
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
undefined2. 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 (critical bottlenecks)
selfTimePct > 15% - Functions with and
callCount > 100(caching opportunities)selfTimePct > 5% - Files with (architectural issues)
timePct > 40% - 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
undefinedbash
undefinedSave baseline before changes
在修改前保存基准版本
./scripts/ef profile EFCanvas basic
--save .profiles/baseline-$(date +%Y%m%d-%H%M%S).cpuprofile
--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
--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
--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
--baseline .profiles/baseline-TIMESTAMP.cpuprofile
--json
查看对比输出:
- 负的`selfTimeDiffMs` = 性能提升 ✅
- 正的`selfTimeDiffMs` = 性能退化 ⚠️Understanding Profile Metrics
理解性能剖析指标
Key Metrics
核心指标
| Metric | Meaning | Use For |
|---|---|---|
| Time in function itself (excluding callees) | Direct optimization target |
| Percentage of total profile time | Prioritization (>15% = critical) |
| Times function appears in call stacks | Caching/memoization decisions |
| Profile samples that caught function | Loop detection (>200 = tight loop) |
| 指标 | 含义 | 适用场景 |
|---|---|---|
| 函数自身执行时间(不包含调用其他函数的时间) | 直接优化目标 |
| 占总剖析时间的百分比 | 优先级判定(>15% = 关键级) |
| 函数在调用栈中出现的次数 | 缓存/记忆化决策依据 |
| 捕获到该函数的剖析样本数 | 循环检测(>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 basicShows:
- 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 --jsonStructured 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 --verboseAdds:
- 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 \
--jsonbash
npx tsx scripts/profile-playback.ts \
--project improv-edit \
--duration 5000 \
--jsonProfile Export Performance
剖析导出性能
bash
npx tsx scripts/profile-export.ts \
--project design-catalog \
--jsonbash
npx tsx scripts/profile-export.ts \
--project design-catalog \
--jsonProfile Page Load
剖析页面加载性能
bash
npx tsx scripts/profile-load.ts \
--project improv-edit \
--jsonbash
npx tsx scripts/profile-load.ts \
--project improv-edit \
--jsonTroubleshooting
问题排查
"Profiling functions not available"
- Ensure browser is controlled by Playwright (use , not regular browser)
ef open
"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 for sampling-based frequency instead
hitCount
"性能剖析功能不可用"
- 确保浏览器由Playwright控制(使用,而非普通浏览器)
ef open
"性能剖析数据为空"
- 场景/测试可能执行过快(<10ms)
- 尝试运行耗时更长的测试或增加测试复杂度
"数值异常无意义"
- 检查时间单位是微秒还是毫秒
- 统一库返回的是毫秒
- 旧接口可能使用微秒
"调用次数统计异常"
- 调用次数是基于调用栈遍历的近似值
- 如需基于采样的频率统计,请使用
hitCount
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
- 修改前务必保存基准版本
- 聚焦自身耗时以获得直接优化效果(总耗时包含调用其他函数的时间)
- 从Top3性能热点入手以获得最大优化收益
- 使用JSON输出进行程序化分析
- 先查看模式检测结果再进行手动分析——模式会给出具体修复方向
- 通过前后对比验证优化效果
- 在基准对比中关注性能退化情况
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/