Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork2.8k
Description
What code were you trying to parse?
I first noticed this against my company's repo (which is private), but I've replicated a similar performance penalty on this repo itself.
What happened?
When run normally, I get a pretty fast lint on my machine (2018 Macbook Pro 15-inch, i7/16GB), about 4.5s:
✔ ~/code/typescript-eslint [master|✔] 16:34 $ time yarn lintyarn run v1.13.0$ eslint . --ext .js,.ts✨ Done in 3.04s.real 0m3.229suser 0m4.476ssys 0m0.260s
However, if I add"project": "./tsconfig.json"
to the parser options, I notice a 10x performance decrease (which is roughly consistent with what we noticed on our own repo).
✔ ~/code/typescript-eslint [master|✚ 1] 16:39 $ time yarn lintyarn run v1.13.0$ eslint . --ext .js,.ts✨ Done in 34.64s.real 0m34.807suser 0m43.377ssys 0m2.933s
Why does this happen?
I've dug into this a little bit, and it seems to come entirely from the time taken to generate the AST andts.Program
for each file; inparser.ts
whenshouldProvideParserServices
istrue
(which is only whenproject
is set),getProgramAndAST
takes ~300ms/file, compared to ~1.5ms/file when it's false.
WithingetProgramAndAST
, the source of the slowness is almost entirely from calls tots.createProgram
. I wrappedcreateProgramAndAST
as well as the call tocreateProgram
withconsole.time
/console.timeEnd
and got the following (this is a small but representative sample):
createProgram: 264.493msgetProgramAndAST: 264.883mscreateProgram: 267.681msgetProgramAndAST: 268.112mscreateProgram: 397.579msgetProgramAndAST: 397.939mscreateProgram: 252.260msgetProgramAndAST: 252.598ms
How could this be fixed?
In comparison, tslint (which lints our internal codebase about 8x faster than typescript-eslint withproject
set) offers an idea for what performance here could look like, only callscreateProgram
once per lint run (https://github.com/palantir/tslint/blob/master/src/runner.ts#L204), and gives it the names ofall the files that will be linted (https://github.com/palantir/tslint/blob/master/src/linter.ts#L97). This isn't possible for typescript-estree as it stands, as eslint only provides a single filename to a call to the parser.
Some possible approaches for a solution:
- Try to make
ts.createProgram
faster - Change eslint to pass down all filenames to the parser each time, allowing typescript-estree to create one
ts.Program
and reuse it
I'm happy to undertake one of these approaches (my thinking is that the second is more promising) and file a PR myself, but I wanted to check in with you, the package maintainers, and get feedback on this before investing a lot more time into it.
Versions
package | version |
---|---|
@typescript-eslint/typescript-estree | master |
TypeScript | 3.3.1 |
node | 8.12.0 |
yarn | 1.13.0 |