Skip to content

Conversation

@meeroslav
Copy link
Contributor

@meeroslav meeroslav commented Dec 19, 2025

On test repo reduces the nx/js/dependencies-and-lockfile:createDependencies:

  • from 10506ms
  • to 3665ms

Current Behavior

Expected Behavior

Related Issue(s)

Fixes #

@vercel
Copy link

vercel bot commented Dec 19, 2025

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

Project Deployment Review Updated (UTC)
nx-dev Ready Ready Preview Dec 19, 2025 5:26pm

@nx-cloud
Copy link
Contributor

nx-cloud bot commented Dec 19, 2025

View your CI Pipeline Execution ↗ for commit 6ef7b46

Command Status Duration Result
nx affected --targets=lint,test,test-kt,build,e... ✅ Succeeded 34m 24s View ↗
nx run-many -t check-imports check-lock-files c... ✅ Succeeded 2m 27s View ↗
nx-cloud record -- nx-cloud conformance:check ✅ Succeeded 11s 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-19 17:56:07 UTC

@netlify
Copy link

netlify bot commented Dec 19, 2025

Deploy Preview for nx-docs ready!

Name Link
🔨 Latest commit 6ef7b46
🔍 Latest deploy log https://app.netlify.com/projects/nx-docs/deploys/6945885d65768e0009484e6a
😎 Deploy Preview https://deploy-preview-33963--nx-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@meeroslav meeroslav marked this pull request as ready for review December 19, 2025 17:19
@meeroslav meeroslav requested review from a team as code owners December 19, 2025 17:19

const { findImports } = require('../../../../native');

// TODO(jon): check why this function is very slow and whether we it can be optimized
Copy link
Member

Choose a reason for hiding this comment

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

This would be better for @FrozenPandaz

Copy link
Collaborator

Choose a reason for hiding this comment

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

All files get processed in parallel... it goes as fast as the largest file which is the slowest to process. IF this is taking long it likely mans that there is a considerably large typescript file. You can see which one it is with NATIVE_FILE_LOGGING tbh, I don't think the TODO comment is necessary.


const { findImports } = require('../../../../native');

// TODO(jon): check why this function is very slow and whether we it can be optimized
Copy link
Collaborator

Choose a reason for hiding this comment

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

All files get processed in parallel... it goes as fast as the largest file which is the slowest to process. IF this is taking long it likely mans that there is a considerably large typescript file. You can see which one it is with NATIVE_FILE_LOGGING tbh, I don't think the TODO comment is necessary.

for (const [project, fileData] of Object.entries(
ctx.filesToProcess.projectFileMap
)) {
Object.keys(ctx.filesToProcess.projectFileMap).forEach((project) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this actually yield a performance benefit?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I don't have the numbers anymore, but it shaved off 100+ms IIRC.

dynamicImportExpressions,
} of imports) {
for (let i = 0; i < imports.length; i++) {
const {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this actually yield any performance benefit?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It does, however, in this location it's not large impact so if you don't like this old-school syntax we can revert this block.

if (this.packageJsonResolutionCache.has(packageJsonPath)) {
return this.packageJsonResolutionCache.get(packageJsonPath);
}
if (existsSync(packageJsonPath)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

we should get rid of this existsSync.. it will throw an error if it doesn't exist which is already handled

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's more common for the file to not exist (falling through down to the root package.json). The existSync saves time as readFileSync + try/catch is noticeably slower at scale.

// Package.json doesn't exist, keep traversing
}
if (dir === workspaceRoot) {
return null;
Copy link
Collaborator

Choose a reason for hiding this comment

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

So before.. we were able to.. resolve outside of the workspace root?

Have we considered if this actually helps when the workspaceRoot is not the same as the node_modules root? WHat if someone has like..

repo-root/package.json
repo-root/node_modules
repo-root/nx-workspace-root/nx.json

If this doesn't yield a major perf behefit, I would not make htis change for now

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can test on the customer repo if reverting this change impacts performance.
I was more worried about correctness. Omitting the version is root package.json would cause traversal down to machine root, hoping no other package.json is found it the way. Also, this would be repeated for every single package name lookup.

> = {},
private readonly npmResolutionCache: NpmResolutionCache = defaultNpmResolutionCache
private readonly npmResolutionCache: NpmResolutionCache = defaultNpmResolutionCache,
private readonly packageJsonResolutionCache: PackageJsonResolutionCache = defaultPackageJsonResolutionCache
Copy link
Collaborator

Choose a reason for hiding this comment

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

I did not review too carefully.. but just to sanity check me...

This is OK for the daemon because everytime we calculate dependencies, we create a brand new project locator with no cache right? So this cache will not remain between different graph calculations?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, exactly. The cache is reused only during the single CLI command/daemon OP lifetime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants