Description
TypeScript Version: 3.9.5
Search Terms: compiler performance namespace run-time property access
Code
I have looked into TypeScript compiler performance in the past and I've always wondered why the TypeScript compiler code uses namespaces heavily, since run-time property accesses are slower than statically-bound identifiers in JavaScript.
I finally got around to writing a proof of concept:
let fs = require('fs')
let tscPath = __dirname + '/node_modules/typescript/lib/tsc.js'
let tsc = fs.readFileSync(tscPath, 'utf8')
let vars = new Set()
tsc = tsc.replace(/\bts\.(\w+)/gm, (_, id) => {
id = `ts_${id}`
vars.add(id)
return id
})
tsc = `var ${[...vars].join(',\n ')};\n${tsc}`
fs.writeFileSync(tscPath, tsc)
This post-processes tsc.js
to convert run-time property accesses into statically-bound identifiers. I ran this on the Rome code as a benchmark of a reasonably-large TypeScript code base and got a noticeable speed boost:
Before | After | Difference | |
---|---|---|---|
Time to run tsc.js |
29.5s | 27.5s | 2s faster |
Each time is the best of 5 runs, and each run was time node node_modules/typescript/lib/tsc.js -noEmit -project rome
.
The TypeScript compiler is leaving some performance on the table by using run-time property accesses where it could use statically-bound identifiers instead. I'm sure you are using namespaces for code organization for good reasons, but it does come at a cost. An alternative to namespaces that might have less performance overhead could be to use ES6 modules and bundler, for example.
I'm posting this issue because I think the results of this experiment are interesting. The issue tracker seemed like the most appropriate place to post this. Feel free to just close this issue if you'd like.