Skip to content

Allow incremental compilation without emitting updated tsBuildInfo file #40198

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

Closed
5 tasks done
oleg-codaio opened this issue Aug 23, 2020 · 4 comments
Closed
5 tasks done
Labels
Needs More Info The issue still hasn't been fully clarified

Comments

@oleg-codaio
Copy link

Search Terms

tsbuildinfo noemit noemitonerror incremental

Suggestion

TS 4 shipped with @sheetalkamat's excellent change #38853, allowing us to use --incremental --noEmit to take advantage of incremental compiling for type checking scenarios.

While this is great, currently any updates to the graph are always emitted to an updated tsBuildInfo file. While this makes sense (to keep the cache always up to date), IMO as a next step it should be possible to use any existing tsBuildInfo file without in turn emitting an updated one.

The motivation is as follows. Our codebase takes a certain amount of time to compile without incremental compilation:

I/O read:          0.76s
I/O write:         0.00s
Parse time:       15.18s
Bind time:         5.41s
Check time:      159.70s
Emit time:         0.01s
Total time:      180.29s

With incremental compilation (no changes), things speed up considerably:

I/O read:          0.86s
I/O write:         0.00s
Parse time:       17.88s
Bind time:         5.34s
Check time:        0.00s
Emit time:         0.00s
Total time:       23.22s

However, a change to a file deep in the DAG (i.e., a central utility file) significantly increases the compile time:

I/O read:          0.91s
I/O write:         0.30s
Parse time:       18.49s
Bind time:         6.09s
Check time:       27.73s
Emit time:       383.41s
Total time:      435.71s

You'll notice that the emit time is the bottleneck here; without it, this would only take ~52 s. Note that the initial emit time (for getting the whole graph built) was about triple the total time above, and the generated file is just <100MB.

Use Cases

My specific scenario is as follows: to minimize TS build time for our developers, our CI on the main branch would run tsc --incremental --noemit to generate updated tsBuildInfo files and write them to a central location. Developers would then make use of the latest generated tsBuildInfo file to quickly run type checks. However, they need not generate updated files locally on the machine, since they'll eventually get updated anyway via the CI's main branch job.

I'm not familiar with the implementation, but it appears that the bottleneck is serializing the updated graph. I'm hoping that by "disabling" the emit stage, we would still be able to take advantage of incremental compilation, resulting in a net win over never using it (i.e., worst case incremental compile takes as long as non-incremental compile).

Examples

I'd like to use something like: tsc --project . --incremental noUpdate --noemit or tsc --project . --incremental --noEmit --incrementalNoUpdate

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.
@RyanCavanaugh
Copy link
Member

@sheetalkamat curious on your thoughts here

@sheetalkamat
Copy link
Member

I think the delay you are seeing seems like declaration emit taking longer rather than updating tsbuild info file. So if you run tsc --declaration --extendedDiagnostics that should show you time it takes to get d.ts for your project which is used to determine what all to build. So i dont see why you should not emit tsbuild info file at all.
You could use advanced setting assumeChangesOnlyAffectDirectDependencies but this can have incorrect error reporting if something breaks in non direct dependencies that you would need to detect with full build.

@sheetalkamat sheetalkamat removed the Needs Investigation This issue needs a team member to investigate its status. label Oct 3, 2020
@sheetalkamat sheetalkamat removed their assignment Oct 3, 2020
@RyanCavanaugh RyanCavanaugh added the Needs More Info The issue still hasn't been fully clarified label Oct 16, 2020
@charrondev
Copy link

charrondev commented Apr 13, 2021

I would jump in here and also share that on our project https://github.com/vanilla/vanilla that the typecheck takes 30-40 seconds for the whole project, but then if we turn on incremental we add 8-10 minutes of emit time on typescript 4.2.

Maybe it's worth exploring a warning if so much time is spent in emit when the --noEmit flag is passed? The assumption when that flag is passed is that nothing will be emitted.

@sheetalkamat
Copy link
Member

As mentioned #40198 (comment) the most probable cause of this is declaration emit that is used to determine change in shape of a module/file and not emitting tsbuild info file.. you can take a look at that by running tsc --declaration --extendedDiagnostics

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs More Info The issue still hasn't been fully clarified
Projects
None yet
Development

No branches or pull requests

4 participants