Profile convert to metadata format is O(n²) per tag in `mergeProfiles` (13.8.3+), blocks the event loop for minutes on large profiles

Đang mở
#3,681 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

@sfdcmatt đang làm issue này rồi.

Từ ngày 5/11/2026.

  • #1867 của @sfdcmatt — đang mở

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
35/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Đình trệ
Công nghệ
node.js, typescript
Lĩnh vực
performance

Hướng nghiên cứu

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.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

bug

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.

Ngôn ngữ chính
Không có dữ liệu ngôn ngữ
Star
575
Fork
80
Merge trung bình
11 giờ 37 phút
Pull request đã merge (30 ngày)
6

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của forcedotcom/cli

Tất cả issue của forcedotcom/cli

Issue tương tự

Thêm issue về Performance

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.