Skip to content

perf_hooks.PerformanceObserver is very slow #464

Closed
@rbuckton

Description

@rbuckton

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
  1. Indicates whether --turbo-fast-api-calls was passed to NodeJS
  2. Emit Time is a subset of Total Time and shows where we're seeing the largest impact
  3. Median of 9 runs on an Ubuntu Server machine running tsc with --extendedDiagnostics
  4. typescript@4.0.5 used our custom performance measurement API
  5. typescript@4.1.3 uses perf_hooks.performance and perf_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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions