Profile convert to metadata format is O(n²) per tag in `mergeProfiles` (13.8.3+), blocks the event loop for minutes on large profiles
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 35/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 停滞
- 技术栈
- node.js, typescript
- 领域
- performance
调研方向
Start with src/convert/convertContext/profileMetadataFinalizer.ts and inspect mergeProfiles, especially the duplicate check described around line 235. Compare conversion time and per-entry zip hashes using the reported 73-profile reproduction; the linked pull request #1867 indicates work is already underway. Done means large-profile conversion avoids the quadratic slowdown while preserving the reported output behavior.
由索引模型根据 Issue 内容生成。
描述
Versions: @salesforce/source-deploy-retrieve 13.10.1 (same mergeProfiles loop since 13.8.3, when ProfileMetadataFinalizer was added; 13.8.2 and earlier copied profile files as-is). Node 26.0.0, macOS.
Repro: a project with 73 profiles in one package directory (103 MB of *.profile-meta.xml, large fieldPermissions / objectPermissions lists). ComponentSet.fromSource(profilesDir) then new MetadataConverter().convert(cs, 'metadata', { type: 'zip' }):
| Version | convert | longest event-loop block | zip bytes |
|---|---|---|---|
| 13.7.0 | 2.1 s | ~0.1 s | 7,116,094 |
| 13.10.1 | 247 s | one continuous block | 7,116,094 |
| 13.10.1 + fix below | 7.9-8.3 s | 5.9-6.3 s | 7,116,094 |
Output is byte-identical in all three (per-entry sha256 of the zip match).
Root cause: src/convert/convertContext/profileMetadataFinalizer.ts, mergeProfiles, line 235:
if (mergedValues.some((existing) => isDeepStrictEqual(existing, entry))) continue;
Every entry is compared with every entry already merged for that tag, synchronously, so a tag with n entries costs n²/2 isDeepStrictEqual calls. This runs even when a profile has only one source file, where there is nothing to merge.
Proposed fix: (1) when profiles.length === 1, return the single profile's entries as-is (root attributes built the same way); (2) for several pieces, dedupe with a Set keyed by a deterministic serialization of each entry (sorted object keys) instead of the linear scan. The singleton-conflict check is unchanged.
Behavior note: with (1), exact duplicate entries inside one profile file are kept, as in 13.8.2 and earlier; 13.8.3-13.10.1 drop them. Duplicates across pieces are still removed.
The remaining ~6 s block after the fix is fast-xml-parser parsing all profiles back to back in parseXml (~4 s) plus JsToXml (~1.3 s), from the finalizer parsing and re-serializing profiles that 13.8.2 streamed unchanged. Not addressed here.
- 主要语言
- 没有语言数据
- 星标
- 575
- 派生
- 80
- 平均合并
- 11 小时 37 分钟
- 30 天内合并 PR
- 6
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
forcedotcom/cli 的其他 Issue
-
area:afdx bug owned by another team
难度 2/5 1-3 小时 新手友好度 76/100
forcedotcom/cli#3676 · 3 条评论 ·
-
sf agent mcp asset replace --assets null throws raw TypeError instead of InvalidShape可能已有人在做 @konkonrong-lgtm 于 87 天前认领。 未关闭area:afdx bug investigating owned by another team validated
难度 2/5 1-3 小时 新手友好度 78/100
forcedotcom/cli#3625 · 4 条评论 ·
-
area:afdx bug owned by another team
难度 2/5 1-3 小时 新手友好度 78/100
forcedotcom/cli#3608 · 2 条评论 ·
-
investigating validated
难度 4/5 3-5 天 新手友好度 45/100
forcedotcom/cli#3683 · 1 条评论 ·
-
bug validated
难度 3/5 1-2 天 新手友好度 35/100
forcedotcom/cli#3679 · 3 条评论 ·
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 76/100
graphql-python/graphql-core#304 ·
维护者通常 1 天内回复
-
AREDL name lookups normalize the whole cached list again for every level可能已有人在做 @Isma-L154 今天认领。 未关闭enhancement
难度 2/5 1-3 小时 新手友好度 69/100
Wal-014/Personal-Progress-List#177 ·
维护者通常 1 天内回复
-
good first issue performance priority: low
难度 2/5 1-3 小时 新手友好度 82/100
TMHSDigital/Free-Game-Dev-Assets#261 ·
维护者通常 1 天内回复
-
bug game: 010042D00D900000 mac
难度 2/5 1-3 小时 新手友好度 84/100
维护者通常 1 天内回复
-
domain/usage p2
难度 2/5 1-3 小时 新手友好度 83/100