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

Slowness when using typescript parser with project option #1408

Closed
bradzacher opened this issue Jul 8, 2019 · 4 comments · Fixed by #1409
Closed

Slowness when using typescript parser with project option #1408

bradzacher opened this issue Jul 8, 2019 · 4 comments · Fixed by #1409

Comments

@bradzacher
Copy link
Contributor

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.

@ljharb
Copy link
Member

ljharb commented Jul 8, 2019

Might deleting those result in different paths tho, potentially causing lint errors?

@bradzacher
Copy link
Contributor Author

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.

@ljharb
Copy link
Member

ljharb commented Jul 8, 2019

Thanks, makes sense to me.

@bradzacher
Copy link
Contributor Author

typescript-eslint/typescript-eslint#389 (comment)

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 project set, unmodified parse.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 project set, modified parse.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, unmodified parse.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, modified parse.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.

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

Successfully merging a pull request may close this issue.

2 participants