Description
Back in October of 2020, TypeScript switched (1, 2) from using our own performance measurement API to using perf_hooks.performance
and perf_hooks.PerformanceObserver
. Since then we have had some users reporting that building with TypeScript using our --diagnostics
or --extendedDiagnostics
flags (which enables on our performance measurement functionality) has caused build time to regress by an additional 20% in some cases prior to this change.
We had two goals with our original change:
- Reduce the size of the TS compiler by leveraging built-in functionality in NodeJS/browser
- Leverage functionality like
--cpu-prof
with the hopes that we could generate cpu profiles with user timings information.
However, we may be forced to revert to our previous custom implementation due to the significant overhead incurred using PerformanceObserver
.
Our expectation would be that using performance measurement APIs shouldn't significantly impact the performance of observed code (though we are aware that its impossible for performance measurement to be completely free).
On a side note, I spoke with @devsnek offline and they suggested we try our scenario using a recent NodeJS 15 build and the --turbo-fast-api-calls
flag. The table below reflects the results of running the compiler with and without this flag on different NodeJS versions when compiling ant-design
/antd
:
TypeScript | NodeJS | Turbo 1 | Emit Time 2 | Total Time 3 |
---|---|---|---|---|
4.0.5 4 | v12.13.0 | No | 0.760s | 9.569s |
4.0.5 | v14.15.4 | No | 0.810s | 9.441s |
4.0.5 | v14.15.4 | Yes | 0.780s | 9.477s |
4.0.5 | v16.0.0-nightly2021012613ac5fbc57 | No | 0.790s | 9.568s |
4.0.5 | v16.0.0-nightly2021012613ac5fbc57 | Yes | 0.780s | 9.649s |
4.1.3 5 | v12.13.0 | No | 2.730s | 11.252s |
4.1.3 | v14.15.4 | No | 3.090s | 11.488s |
4.1.3 | v14.15.4 | Yes | 3.090s | 11.532s |
4.1.3 | v16.0.0-nightly2021012613ac5fbc57 | No | 2.660s | 11.184s |
4.1.3 | v16.0.0-nightly2021012613ac5fbc57 | Yes | 2.680s | 11.226s |
- Indicates whether
--turbo-fast-api-calls
was passed to NodeJS - Emit Time is a subset of Total Time and shows where we're seeing the largest impact
- Median of 9 runs on an Ubuntu Server machine running tsc with
--extendedDiagnostics
- typescript@4.0.5 used our custom performance measurement API
- typescript@4.1.3 uses
perf_hooks.performance
andperf_hooks.PerformanceObserver
I'd like to point out several take-aways from the table above:
- Using
perf_hooks.PerformanceObserver
is generally about 17.5% slower in the above benchmarks than our prior custom measurement API. - Using
--turbo-fast-api-calls
actually makes things worse rather than better.
In the event I'm doing something wrong with our use of PerformanceObserver
, you can find the source for our performance wrapper (which essentially just forwards calls to mark
and measure
and uses a PerformanceObserver
to capture information) here: https://github.com/microsoft/TypeScript/blob/cdd11e96ad3dd039da76c1506e35bc7e74dd57f1/src/compiler/performance.ts