Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

no-restricted-paths is slow when many imports/excepts #1758

Open
robatwilliams opened this issue May 12, 2020 · 13 comments
Open

no-restricted-paths is slow when many imports/excepts #1758

robatwilliams opened this issue May 12, 2020 · 13 comments

Comments

@robatwilliams
Copy link

The rule appears to be building and validating the excepts for each zone every time an import is encountered. This makes it very slow when you have many files/imports, zones, and/or excepts.

I narrowed it down to this validation part here:

const hasValidExceptionPaths = absoluteExceptionPaths
            .every((absoluteExceptionPath) => isValidExceptionPath(absoluteFrom, absoluteExceptionPath))

https://github.com/benmosher/eslint-plugin-import/blob/master/src/rules/no-restricted-paths.js#L88

Could it instead validate the exception paths once when the rule is initialised?

@ljharb
Copy link
Member

ljharb commented May 12, 2020

How many exception paths do you have? O.o

@ljharb
Copy link
Member

ljharb commented May 12, 2020

The line you referenced happens when checkForRestrictedImportPath is called; and it's called when the rule visits nodes because it needs that node information (that's what absoluteFrom is). I don't think it can be moved at all.

@robatwilliams
Copy link
Author

Quite a few (but we're working on that), but what we have more of is files and imports - it's a large codebase, and I'm trying to use this rule and/or no-restricted-imports to help improve and enforce separation.

I saw that absoluteFrom is derived from the basePath and zone.from, I don't see anything node-specific. The error it would produce is Restricted path exceptions must be descendants of the configured from path for that zone., which isn't node-specific. I might have missed something though.

@ljharb
Copy link
Member

ljharb commented May 12, 2020

The importPath used in const absoluteImportPath = resolve(importPath, context) is the specifier that shows up in the code; it's not known in advance.

@robatwilliams
Copy link
Author

Yes, I don't see that it's used for this validation though. Looks like a validation of the rule configuration, that the excepts does not backtrack to a parent of from.

Thanks for the quick responses, and apologies if I'm missing it.

@ljharb
Copy link
Member

ljharb commented May 12, 2020

importPath comes from the node, it's used in https://github.com/benmosher/eslint-plugin-import/blob/master/src/rules/no-restricted-paths.js#L89 to validate the exception paths.

Just a thought - if we supported globs/stars in the exceptions, would that let you consolidate your list significantly?

@robatwilliams
Copy link
Author

It does, but I don't see it (importPath) or absoluteImportPath used on L88-89 to validate the exception paths themselves:

const hasValidExceptionPaths = absoluteExceptionPaths
            .every((absoluteExceptionPath) => isValidExceptionPath(absoluteFrom, absoluteExceptionPath))

It's only used later on L96-97 to check if an offending import is excepted:

const pathIsExcepted = absoluteExceptionPaths
            .some((absoluteExceptionPath) => containsPath(absoluteImportPath, absoluteExceptionPath))

Looking at it from another angle, it's the validation for this part of the config, which doesn't sound node-specific. I'll take your word for it though if I'm still not making sense.

An optional except may be defined for a zone, allowing exception paths that would otherwise violate the related from. Note that except is relative to from and cannot backtrack to a parent directory.

Globs would help consolidate the list, yes (I see there's a PR #1708). Though I've gone with no-restricted-imports from ESLint core now.

@ljharb
Copy link
Member

ljharb commented May 12, 2020

aha, i do see what you mean.

it would split up the validation a bit, but a PR that hoists whatever can be hoisted out of the visitor into create sounds perfect.

@malykhinvi
Copy link
Contributor

@ljharb I prepared a PR, could you please have a look when you have a chance? On the project I work on, it made the check an order of magnitude faster.

@ljharb
Copy link
Member

ljharb commented Apr 7, 2021

Absolutely! Note that tests are currently broken on master (#1986) so i might not be able to land it just yet.

@fregante
Copy link
Contributor

fregante commented Nov 23, 2022

I'm experiencing slow performance for this rule as well. You can see the configuration in:

https://github.com/pixiebrix/pixiebrix-extension/blob/2604923b0f29c63bae5e1fbd690db4e33bd4b23c/.eslintrc.js#L15-L16 (note that dropping the glob only maybe saves 1 second)

In short, I don't want files in /A to import from /B and vice versa, for 5 such folders, but this rule appears to be taking a long time just for that:

Rule Time (ms) Relative
import/no-restricted-paths 30474.413 50.6%
@typescript-eslint/no-confusing-void-expression 5398.132 9.0%
@typescript-eslint/no-floating-promises 3957.692 6.6%
@typescript-eslint/promise-function-async 2753.125 4.6%
@typescript-eslint/no-redeclare 829.458 1.4%
react/display-name 825.262 1.4%
react/no-direct-mutation-state 723.626 1.2%
unicorn/prevent-abbreviations 690.028 1.1%
@typescript-eslint/no-misused-promises 662.684 1.1%
unicorn/template-indent 544.756 0.9%

I think it might not actually be the specific rule though:

See #2340 (comment); whichever is the first rule to build the ExportMap will be the slowest.

@ljharb
Copy link
Member

ljharb commented Nov 24, 2022

Indeed, if you maximally enable the useful import rules, you may find another rule is the 30s one.

@fregante
Copy link
Contributor

fregante commented Feb 9, 2024

I disabled the rule, nothing else came close to it, so it's definitely one of the slowest ones. The other one is import/no-cycle, which by itself takes twice the time, so it's disabled in regular runs.

See comparison in:

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

No branches or pull requests

4 participants