TypeScript Version: 3.8.3
Search Terms: slow compilation, slow incremental compilation, declaration diagnostics, slow noEmitOnError
Code
I'm trying to debug why incremental TypeScript compilation is slow on my project when using noEmitOnError option. A clean compilation takes around 12s and an incremental compilation after a simple change takes around 10s. Turning off noEmitOnError takes the incremental compilation time down to 1.6s.
Based on the CPU profiles, it looks like bulk of the time is spent in getDeclarationDiagnostics, which is only triggered pre-emit when noEmitOnError is turned on.
tsconfig.json:
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"target": "ESNext",
"importHelpers": false,
"module": "esnext",
"jsx": "react",
"newLine": "lf",
"moduleResolution": "Node",
"strict": true,
"noErrorTruncation": true,
"noLib": true,
"preserveConstEnums": true,
"resolveJsonModule": true,
"sourceMap": true,
"noResolve": false,
"typeRoots": [],
"alwaysStrict": true,
"declaration": true,
"isolatedModules": true,
"composite": true
},
"include": [
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules"
]
}
Using tsc --incremental --noEmitOnError and tsc --incremental:
Diagnostics:
| | Clean noEmitOnError true | Incremental noEmitOnError true | Clean noEmitOnError false | Incremental noEmitOnError false |
|:---|---:|---:|---:|---:|
| Total time | 12.34s | 9.90s | 13.31s | 1.63s |
| CPU Profile | Link | Link | Link | Link |
| Files | 294 | 294 | 294 | 294 |
| Lines | 61074 | 61075 | 61074 | 61075 |
| Nodes | 220691 | 220694 | 220691 | 220694 |
| Identifiers | 69349 | 69350 | 69349 | 69350 |
| Symbols | 191258 | 184217 | 191182 | 46246 |
| Types | 84567 | 81264 | 84493 | 103 |
| Memory used | 225553K | 205273K | 226985K | 92313K |
| Assignability cache size | 127401 | 127401 | 127401 | 2 |
| Identity cache size | 1820 | 1820 | 1820 | 0 |
| Subtype cache size | 1203 | 1204 | 1203 | 0 |
| Strict subtype cache size | 10236 | 5766 | 10236 | 0 |
| I/O Read time | 0.15s | 0.15s | 0.04s | 0.03s |
| Parse time | 0.81s | 0.85s | 0.96s | 0.78s |
| Program time | 1.15s | 1.17s | 1.21s | 0.97s |
| Bind time | 0.56s | 0.63s | 0.64s | 0.55s |
| Check time | 7.96s | 8.02s | 8.41s | 0.03s |
| transformTime time | 0.96s | 0.31s | 0.93s | 0.01s |
| commentTime time | 0.18s | 0.00s | 0.24s | 0.00s |
| printTime time | 2.66s | 0.08s | 3.03s | 0.07s |
| Emit time | 2.67s | 0.08s | 3.04s | 0.07s |
| Source Map time | 0.10s | 0.00s | 0.13s | 0.00s |
| I/O Write time | 0.26s | 0.01s | 0.25s | 0.00s |
Please remove
.txtextension from CPU profiles to be able to load them in Chrome dev tools. I had to use.txtextension to be able to attach them to the issue.
Expected behavior:
Enabling noEmitOnError should not signficantly increase incremental compilation time. In the project above, I would expect a simple incremental compilation to take 1-2 seconds, i.e. similar to when noEmitOnError is false.
Actual behavior:
Incremental compilation after a simple change takes around 10 seconds, which is almost the same as the 12 seconds it takes to perform a clean compilation.
Playground Link: -
Related Issues:
Not a directly related issue but https://github.com/microsoft/TypeScript/issues/31849#issuecomment-527657520 indicates declaration diagnostics are collected by doing in-memory emit.
A different kind of slowness report related to noEmitOnError: https://github.com/microsoft/TypeScript/issues/24444
Should look into writing tsbuildinfo file when there are errors with noEmitOnError so semantic errors are cached.. Needs more depth investigation since this affects --build as well
I also ran into the issue (in my case it increases the re-compilation time in watch mode from 25 to ~70 seconds). Please ping me if I need to provide any additional information.
I should say that disabling declaration compiler option speeds up the build as well as disabling noEmitOnError in my case.
Diagnostics (in watch mode, incremental build):
Name|declaration: false|declaration: true
---|---|---
Files| 3944| 3944
Lines| 460896| 460896
Nodes| 1966966| 1966966
Identifiers| 654712| 654712
Symbols| 307304| 856053
Types| 1150| 342100
Memory used| 696512K| 1552378K
I/O read| 0.00s| 0.00s
I/O write| 0.01s| 0.00s
Parse time| 0.15s| 0.22s
Bind time| 0.04s| 0.02s
Check time| 0.45s| 41.94s
Emit time| 0.96s| 0.00s
Total time| 1.60s| 42.18s
Cpu profile for declaration: false: declaration-disabled.zip
Cpu profile for declaration: true: declaration-enabled.zip
Should be fixed by #38853
Thank you @sheetalkamat. "noEmitOnError" is a popular feature, so your fix hugely improves performance for many users.
Most helpful comment
Should be fixed by #38853