A few of our users are reporting slowness when using our parser (@typescript-eslint/parser) with this plugin.
Having a quick look at the codebase, I notice that you invoke the parser yourself so you can gather information about other files.
https://github.com/benmosher/eslint-plugin-import/blob/05c3935/utils/parse.js#L9-L39
As part of this, you pass in the parserOptions from the root config. If the project/projects option is set in the parserOptions, it will cause our parser to do a complete typechecking parse cycle, which is often rather slow.
I'm still gathering information from users, we have some caching and such in the parser to attempt to circumvent this, but I think there's a double parse happening because you have a new instance of everything.
My hypothesis is that if we add the following lines at line 25 in the above file, it will make your parser invocation be a single-file, non type-checked parse, which should obviously be fast!
+ delete parserOptions.project
+ delete parserOptions.projects
Once I get some data from users I'll happily raise a PR for this - I just wanted to bring it to your attention first.
Might deleting those result in different paths tho, potentially causing lint errors?
Passing in project/projects will cause the parser to load your tsconfig file from the specified location and invoke a full typescript parser cycle, which will cause typescript to parse every single file referenced within the tsconfig file up-front.
Without the project, we just act like a normal eslint parser - we load the file you tell us and parse it in isolation.
We don't use the project option to resolve filenames, so there won't be anything that breaks without it.
The project config is completely optional, and only required if the user wants to use rules that require type information. As the import rules don't use type information, it won't impact anything.
Thanks, makes sense to me.
https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509298338
That's the result I was looking for!
Copy pasting comment content here for posterity.
This change will make an absolutely huge perf impact!
Some more measurements:
with
projectset, unmodifiedparse.js
$ eslint --ext js --ext jsx --ext ts --ext tsx --report-unused-disable-directives src
Rule | Time (ms) | Relative
:---------------------------------|----------:|--------:
import/namespace | 15160.952 | 88.9%
react/display-name | 202.946 | 1.2%
import/no-duplicates | 196.474 | 1.2%
import/no-self-import | 192.724 | 1.1%
import/export | 192.706 | 1.1%
react/no-deprecated | 158.083 | 0.9%
react/no-direct-mutation-state | 151.298 | 0.9%
import/no-unresolved | 109.693 | 0.6%
@typescript-eslint/no-unused-vars | 109.244 | 0.6%
react/no-string-refs | 107.180 | 0.6%
Done in 32.28s
with
projectset, modifiedparse.js:
$ eslint --ext js --ext jsx --ext ts --ext tsx --report-unused-disable-directives src
Rule | Time (ms) | Relative
:---------------------------------|----------:|--------:
import/namespace | 4184.799 | 76.2%
import/no-duplicates | 155.571 | 2.8%
import/no-self-import | 150.559 | 2.7%
react/display-name | 149.332 | 2.7%
react/no-direct-mutation-state | 122.384 | 2.2%
react/no-deprecated | 115.475 | 2.1%
import/no-unresolved | 89.857 | 1.6%
react/no-string-refs | 84.541 | 1.5%
@typescript-eslint/no-unused-vars | 82.722 | 1.5%
react/require-render-return | 79.717 | 1.5%
Done in 12.85s
with
project undefined, unmodifiedparse.js
$ eslint --ext js --ext jsx --ext ts --ext tsx --report-unused-disable-directives src
Rule | Time (ms) | Relative
:---------------------------------|----------:|--------:
import/namespace | 4281.347 | 75.8%
import/no-duplicates | 179.059 | 3.2%
import/no-self-import | 175.444 | 3.1%
react/display-name | 145.123 | 2.6%
react/no-deprecated | 123.419 | 2.2%
react/no-direct-mutation-state | 118.101 | 2.1%
@typescript-eslint/no-unused-vars | 90.583 | 1.6%
react/no-string-refs | 84.826 | 1.5%
import/no-unresolved | 82.151 | 1.5%
react/require-render-return | 80.526 | 1.4%
Done in 9.27s.
with
project undefined, modifiedparse.js
$ eslint --ext js --ext jsx --ext ts --ext tsx --report-unused-disable-directives src
Rule | Time (ms) | Relative
:---------------------------------|----------:|--------:
import/namespace | 4170.759 | 76.6%
import/no-self-import | 158.713 | 2.9%
import/no-duplicates | 157.649 | 2.9%
react/display-name | 136.888 | 2.5%
react/no-deprecated | 118.751 | 2.2%
react/no-direct-mutation-state | 107.730 | 2.0%
@typescript-eslint/no-unused-vars | 87.863 | 1.6%
react/no-string-refs | 80.661 | 1.5%
react/require-render-return | 79.535 | 1.5%
import/no-unresolved | 77.654 | 1.4%
Done in 9.18s.
So yes, while project is set, this seems to be a BIG performance improvement.
Most helpful comment
https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509298338
That's the result I was looking for!
Copy pasting comment content here for posterity.
This change will make an absolutely huge perf impact!
Some more measurements:
So yes, while
projectis set, this seems to be a BIG performance improvement.