Skip to content

Commit 8fe284f

Browse files
committed
perf: use Set for O(1) merge commit lookup instead of O(N*M) iteration
- Pre-build Set of PR commit descriptions before filter loop - Change from commits.some() [O(M)] to Set.has() [O(1)] lookup - Reduces complexity from O(N*M) to O(N+M) Performance improvement: - 50 direct commits × 100 total = 5,000 ops → 150 ops (96.7% faster) - 100 direct commits × 500 total = 50,000 ops → 600 ops (98.8% faster) Addresses Copilot performance feedback on hasCorrespondingMergeCommit check
1 parent cac8ef8 commit 8fe284f

File tree

1 file changed

+14
-10
lines changed

1 file changed

+14
-10
lines changed

src/get-new-changes.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,14 @@ export async function getNewChangeEntries({
211211
useChangelogEntry,
212212
);
213213

214+
// Pre-build a Set of descriptions from PR-based commits for efficient lookup
215+
// This avoids O(N*M) complexity when checking for corresponding merge commits
216+
const prCommitDescriptions = new Set(
217+
commits
218+
.filter((commit) => commit.prNumber)
219+
.map((commit) => commit.description.trim()),
220+
);
221+
214222
// Filter commits to exclude duplicates:
215223
// - For commits with PR numbers: check if PR number already exists in changelog
216224
// - For commits without PR numbers: check if the description already exists in changelog
@@ -219,24 +227,20 @@ export async function getNewChangeEntries({
219227
// PR-based commit: check if this PR number is already logged
220228
return !loggedPrNumbers.includes(prNumber);
221229
}
222-
230+
223231
// Direct commit (no PR number): need to handle two cases
224-
232+
225233
// Case 1: Check if there's a corresponding merge commit in this batch
226234
// This handles squash merges where both the original commit and merge commit appear
227-
const hasCorrespondingMergeCommit = commits.some(
228-
(commit) =>
229-
commit.prNumber && commit.description.trim() === description.trim(),
230-
);
231-
232-
if (hasCorrespondingMergeCommit) {
235+
const normalizedDescription = description.trim();
236+
if (prCommitDescriptions.has(normalizedDescription)) {
233237
// Skip this commit - the merge commit with PR number will be used instead
234238
return false;
235239
}
236-
240+
237241
// Case 2: Check if this exact description is already logged in the changelog
238242
// Trim description to match pre-normalized loggedDescriptions
239-
return !loggedDescriptions.includes(description.trim());
243+
return !loggedDescriptions.includes(normalizedDescription);
240244
});
241245

242246
return newCommits.map(({ prNumber, subject, description }) => {

0 commit comments

Comments
 (0)