Description
TypeScript Version: 3.9.7
Search Terms: external source maps, performance, setSourceMapSource
Code
I am investigating Angular compiler performance and noticed an interesting performance cliff related to TypeScript's ability to map into external sources. External source map sources are used in ngc
(Angular's tsc
) to map into the external .html
template files, using the ts.createSourceMapSource
and ts.setSourceMapRange
public APIs.
During emit, emitSourcePos
is used to build the source map, using a fast-path if no external source map source is used:
TypeScript/src/compiler/emitter.ts
Lines 5290 to 5300 in a7d8011
With an external source map, however, the slow-path that calls into setSourceMapSource
is run twice, for each emitted ts.Node
. This calls into ts.SourceMapGenerator.addSource
which manages the source indices per source map source, based on their canonicalized relative path:
TypeScript/src/compiler/sourcemap.ts
Lines 52 to 69 in a7d8011
The path manipulation is somewhat expensive and it calls repeatedly into ts.CompilerHost.getCanonicalFileName
, so its performance characteristics also have quite a significant impact.
TypeScript/src/compiler/path.ts
Lines 817 to 832 in a7d8011
Using a program with the following characteristics (obtained with tsc --diagnostics
):
Files: 1095
Lines: 200035
Nodes: 501580
Identifiers: 164978
Symbols: 202287
Types: 62907
Instantiations: 49308
we're seeing 4.8 seconds spent in emitSourcePos
using ngc
(of which 4.3 seconds is spent in setSourceMapSource
), where the full emit phase takes 13.4 seconds; i.e. source mapping takes 36% of emit (using a profiler, so there's some overhead there). More importantly, the slow path in setSourceMapSource
is responsible for 4.3/4.8 = ~90% overhead.
Using Angular CLI it's much worse with emitSourcePos
taking ~16s, given that the ts.CompilerHost.getCanonicalFileName
implementation is a lot slower—that is for Angular itself to improve.
Expected behavior:
The overhead in setSourceMapSource
should not be 90% of total source mapping time.
Actual behavior:
Using external source map sources does have a significant performance overhead, increasing source map times ten-fold or worse.
Playground Link:
n/a
Related Issues:
n/a