perf(release,tasks-runner,generators): O(n²) to O(n) optimizations using Set/Map
Current Behavior
Several core Nx operations use O(n) array operations inside loops, resulting in O(n²) or O(n*m) time complexity:
- Release commands:
releaseGraph.releaseGroups.find()called inside loops oversortedReleaseGroups - Git tag filtering: Regex
match()called twice on the same string - Task runner terminal output:
indexOf()used for task membership checks - Task graph utils: O(n²) array deduplication pattern
- Project configuration:
indexOf()used in filter for deleted files
Expected Behavior
All operations use optimal data structures:
- Map for O(1) key-based lookups instead of Array.find()
- Set for O(1) membership checks instead of Array.indexOf()
- Set spread for O(n) deduplication instead of indexOf pattern
- Variable caching to avoid duplicate regex operations
Summary of Changes
1. Release Commands (O(n²) → O(n))
┌─────────────────────────────────────────────────────────────┐
│ BEFORE │
│ for (name of sortedGroups) { // O(n) iterations │
│ releaseGroups.find(g => g.name) // O(n) per lookup │
│ } // Total: O(n²) │
├─────────────────────────────────────────────────────────────┤
│ AFTER │
│ groupMap = new Map(groups.map(g => [g.name, g])) // O(n) │
│ for (name of sortedGroups) { // O(n) iterations │
│ groupMap.get(name) // O(1) per lookup │
│ } // Total: O(n) │
└─────────────────────────────────────────────────────────────┘
2. Git Tag Filtering (2x → 1x regex operations)
┌─────────────────────────────────────────────────────────────┐
│ BEFORE │
│ !!tag.match(regex) && tag.match(regex).some(...) // 2 ops │
├─────────────────────────────────────────────────────────────┤
│ AFTER │
│ matches = tag.match(regex); matches?.some(...) // 1 op │
└─────────────────────────────────────────────────────────────┘
3. Task Runner Terminal Output (O(n) → O(1) lookups)
┌─────────────────────────────────────────────────────────────┐
│ BEFORE │
│ tasks.indexOf(taskRow.task) > -1 // O(n) lookup │
│ cachedTasks.indexOf(task) !== -1 // O(n) lookup │
├─────────────────────────────────────────────────────────────┤
│ AFTER │
│ taskSet.has(taskRow.task) // O(1) lookup │
│ cachedTasks.has(task) // O(1) lookup │
└─────────────────────────────────────────────────────────────┘
4. Task Graph Utils Deduplication (O(n²) → O(n))
┌─────────────────────────────────────────────────────────────┐
│ BEFORE │
│ arr.filter((item, i, arr) => arr.indexOf(item) === i) │
│ ↑ O(n) per element = O(n²) │
├─────────────────────────────────────────────────────────────┤
│ AFTER │
│ [...new Set(arr)] // O(n) total │
└─────────────────────────────────────────────────────────────┘
5. Project Configuration (O(n*m) → O(n))
┌─────────────────────────────────────────────────────────────┐
│ BEFORE │
│ projectFiles.filter(r => deletedFiles.indexOf(r) === -1) │
│ ↑ O(m) lookup per file = O(n*m) │
├─────────────────────────────────────────────────────────────┤
│ AFTER │
│ deletedFilesSet = new Set(deletedFiles) │
│ projectFiles.filter(r => !deletedFilesSet.has(r)) // O(n) │
└─────────────────────────────────────────────────────────────┘
Files Changed
packages/nx/src/command-line/release/release.ts- Map for release group lookuppackages/nx/src/command-line/release/version.ts- Map for release group lookuppackages/nx/src/command-line/release/publish.ts- Map for release group lookuppackages/nx/src/command-line/release/utils/git.ts- Cache regex match resultpackages/nx/src/tasks-runner/life-cycles/dynamic-run-many-terminal-output-life-cycle.ts- Set for task lookuppackages/nx/src/tasks-runner/life-cycles/invoke-runner-terminal-output-life-cycle.ts- Set for cached/failed taskspackages/nx/src/tasks-runner/task-graph-utils.ts- Set-based deduplicationpackages/nx/src/generators/utils/project-configuration.ts- Set for deleted file lookup
Related Issue(s)
Performance optimization - no specific issue.
Merge Dependencies
Must be merged AFTER: #33737 Must be merged BEFORE: #33748
Deploy request for nx-docs pending review.
Visit the deploys page to approve it
| Name | Link |
|---|---|
| Latest commit | 9611ee9df282bee557037c154504fa3c0d25daf2 |
The latest updates on your projects. Learn more about Vercel for GitHub.
| Project | Deployment | Preview | Updated (UTC) |
|---|---|---|---|
| nx-dev | Preview | Dec 8, 2025 5:35am |
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
@adwait1290 We are very grateful for your enthusiasm to contribute, I kindly request that you please stop sending these AI assisted micro-perf PRs now. In future, please open an issue regarding your plans and do not simply send pages worth of micro PRs without open communication.
Upon deeper inspection in some cases, we have found that they are not resulting in real-world performance wins, and instead create regressions because they are not considering memory and GC overhead of the whole system.
We will work on better benchmarking infrastructure on our side to have greater confidence in CI as to whether these kinds of PRs are actually net wins but for now each individual PR requires a thorough investigation by the team and you are sending far, far too many.
To reduce noise on the repo, I am going to close this, but rest assured it will be looked at as part of our performance optimization and benchmarking effort and merged in if it creates a provable net win.
Thank you once again for your keenness to help make Nx the best it can be, we really appreciate it!
This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.