Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@adwait1290
Copy link
Contributor

@adwait1290 adwait1290 commented Dec 8, 2025

Current Behavior

In buildExplicitPackageJsonDependencies, for every file in the project file map, we call isPackageJsonAtProjectRoot which uses Array.find():

function isPackageJsonAtProjectRoot(nodes, fileName) {
  return (
    fileName.endsWith('package.json') &&
    nodes.find((projectNode) =>  // O(n) lookup per file!
      joinPathFragments(projectNode.root, 'package.json') === fileName
    )
  );
}

This is O(files × projects) complexity.

Expected Behavior

Build a Set of valid package.json paths once, then use O(1) Set lookup:

const projectPackageJsonPaths = new Set(
  Object.values(ctx.projects).map((project) =>
    joinPathFragments(project.root, 'package.json')
  )
);

// Later: O(1) lookup
if (projectPackageJsonPaths.has(f.file)) { ... }

Performance Impact

Before (Array.find per file):       After (Set.has):
┌─────────────────────────┐         ┌─────────────────────────┐
│ For each file:          │         │ Build Set once:         │
│   nodes.find(...)       │         │   O(projects)           │
│   O(projects) per file  │         └───────────┬─────────────┘
└───────────┬─────────────┘                     │
            │                                   ▼
            ▼                         ┌─────────────────────────┐
┌─────────────────────────┐         │ For each file:          │
│ Total: O(files×projects)│         │   Set.has(f.file)       │
└─────────────────────────┘         │   O(1) per file         │
                                    └───────────┬─────────────┘
                                                │
                                                ▼
                                    ┌─────────────────────────┐
                                    │ Total: O(files+projects)│
                                    └─────────────────────────┘

Example: With 5,000 files and 200 projects:

  • Before: 5,000 × 200 = 1,000,000 comparisons (worst case)
  • After: 200 (build Set) + 5,000 (lookups) = 5,200 operations

Additional Changes

  • Replaced forEach with for...in/of loops
  • Removed unused isPackageJsonAtProjectRoot function
  • Removed unused ProjectConfiguration import
  • Net reduction of 7 lines

Why Accept This PR

  1. Significant complexity reduction: O(n²) → O(n)
  2. Hot path: Called during dependency graph construction for every file
  3. Cleaner code: Removed unused function, fewer lines

Related Issue(s)

Contributes to #32265

Merge Dependencies

This PR has no dependencies and can be merged independently.


Previously, isPackageJsonAtProjectRoot used Array.find() to check if
a file is a package.json at a project root, resulting in O(n) lookup
per file where n is number of projects.

Now builds a Set of valid package.json paths once at the start,
reducing lookup from O(files × projects) to O(files + projects).

Also:
- Replaced forEach with for...in/of loops
- Removed unused isPackageJsonAtProjectRoot function
- Removed unused ProjectConfiguration import
@adwait1290 adwait1290 requested a review from a team as a code owner December 8, 2025 07:30
@netlify
Copy link

netlify bot commented Dec 8, 2025

👷 Deploy request for nx-docs pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 8148d64

@vercel
Copy link

vercel bot commented Dec 8, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
nx-dev Ready Ready Preview Dec 8, 2025 7:37am

@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@JamesHenry
Copy link
Collaborator

Thank you @adwait1290 please make this the last one for now and give the team chance to review

@adwait1290
Copy link
Contributor Author

@JamesHenry will pause for now; let me know what I can do to help get these reviewed.

@FrozenPandaz FrozenPandaz changed the title perf(js): use Set for O(1) package.json root lookup fix(js): use Set for O(1) package.json root lookup Dec 8, 2025
@nx-cloud
Copy link
Contributor

nx-cloud bot commented Dec 8, 2025

View your CI Pipeline Execution ↗ for commit 8148d64

Command Status Duration Result
nx affected --targets=lint,test,test-kt,build,e... ✅ Succeeded 5m 51s View ↗
nx run-many -t check-imports check-lock-files c... ✅ Succeeded 2m 57s View ↗
nx-cloud record -- nx-cloud conformance:check ✅ Succeeded 12s View ↗
nx-cloud record -- nx format:check ✅ Succeeded 2s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded <1s View ↗

☁️ Nx Cloud last updated this comment at 2025-12-08 20:57:08 UTC

Copy link
Collaborator

@FrozenPandaz FrozenPandaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution! LGTM 🎉

@FrozenPandaz FrozenPandaz merged commit 5d597ee into nrwl:master Dec 8, 2025
18 of 23 checks passed
@JamesHenry
Copy link
Collaborator

@adwait1290 We're grateful for the contributions, however no team/project is expecting 25 PRs from a single contributor in rapid succession and so rather than adding to a growing list, it makes sense to wait a few days to allow us to work through the existing ones. You can that including yours we have 150+ PRs open that all need to be reviewed and we're working on it

@github-actions
Copy link
Contributor

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.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 15, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants