cdktf compile optimization with swc
Laying the grounds works, there are a number of tools in analysis here:
- cdktf - Allows for defining terraform infrastructure as code in Typescript, Python or Golang.
- typescript - And in particular tsc, the cli that transpiles typescript to javascript.
- swc - A new js/ts transpiler that is gaining traction rapidly, and recently even made its way into NextJS test suite, with awesome results here
I am interested in using the cdktf, with typescript, to enhance infrastructure as code declarations for ease of use.
Seeing large projects take on the challenge of changing their compiler made me think if it was worth it; what are the pros and cons.
Summary ¶
Sample code can be found here: https://github.com/simonireilly/cdktf-swc
- Using
tsc --incremental
is statistically faster thanswc
. - Using either
swc
ortsc --incremental
will reduce time spent waiting by a factor of 5.
Trade-offs:
- Pro - swc is fast on initial build
- Pro - tsc --incremental is faster, after the first build
- Con - swc does not produce type declarations
SWC vs. TSC ¶
- swc was on average 5.6 times faster than tsc for synth(esizing) the terraform cdk stack.
- swc was on average 2.5 times faster than tsc for plan(ing) the terraform cdk stack.
Compiler | Command | Mean [s] | Min [s] | Max [s] | Relative |
---|---|---|---|---|---|
swc | yarn synth |
4.9 ± 0.2 | 4.7 | 5.2 | 1.0 |
tsc | yarn synth |
28.0 ± 3.8 | 24.9 | 32.2 | 5.6 ± 0.8 |
TSC incremental vs. SWC ¶
- tsc --incremental was on average 1.1 times faster than swc for synth(esizing) the terraform cdk stack.
- tsc --incremental was on average 1.2 times faster than swc for plan(ing) the terraform cdk stack.
Compiler | Command | Mean [s] | Min [s] | Max [s] | Relative |
---|---|---|---|---|---|
swc | yarn synth |
5.098 ± 0.439 | 4.661 | 5.540 | 1.07 ± 0.12 |
tsc --incremental | yarn synth |
4.744 ± 0.341 | 4.360 | 5.008 | 1.00 |
Read on if you want to know about the implementation details
Setup ¶
There is a guide here I followed for getting started with cdktf: https://learn.hashicorp.com/tutorials/terraform/cdktf-build?in=terraform/cdktf
This isn't really the subject of the blog, but it is a nice intro to get you started if you plan on using the cdktf.
Experiencing slow synth ¶
I was doing some development on the train, and I was thinking, wow, this seems slow. When I discovered this was actually the compiler, not the network I was pretty shocked.
Digging under the hood there is actually some fairly good reasons this feels like a slow experience, and there are a number of solutions.
- The cdktf was setup to re-compile the code, including all files in the
.gen
folder, on every synth. - The cdktf was setup with a tsconfig.json that wasn't using incremental builds (tsc keeps a build manifest to help it detect relevant changes and only recompile what is necessary).
- The cdktf was setup with a tsconfig.json that would produce type declarations (*.d.ts); which is super useful if you are distributing your code for use in js environments. If you are not, and you are just using typescript, you might not need these.
Solution 1 ¶
Just set incremental to true in the tsconfig.json
.
I am not going to lie, this is the simplest, and biggest win for compile time, and improves the overall performance straight away.
{
"compilerOptions": {
"incremental": true
}
}
Solution 2 ¶
Since the initial build is still slow, another transpiler, swc, could be used to speed up builds:
yarn add --dev @swc/core @swc/cli
// .swcrc
{
"jsc": {
"parser": {
"syntax": "typescript"
},
"target": "es2018"
},
"sourceMaps": true,
"module": {
"type": "commonjs",
"strict": false,
"noInterop": false,
"strictMode": false
}
}
Update the compile script to use swc:
{
"scripts": {
"compile": "swc main.ts --out-file dist/main.js & swc .gen/providers/**/*.ts -d dist/.gen/"
}
}
Analysis ¶
I used hyperfine on my local machine:
$ lshw -short
H/W path Device Class Description
====================================================
system Latitude 7490 (081C)
/0/4d/0 memory 16GiB SODIMM DDR4 Synchronous Unbuffered (Unregistered) 2133 MHz (0.5 ns)
/0/4d/1 memory 16GiB SODIMM DDR4 Synchronous Unbuffered (Unregistered) 2133 MHz (0.5 ns)
/0/54 processor Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz
TSC --incremental vs. SWC ¶
Testing against incremental, we allow for the build to be present before each run:
hyperfine 'COMMAND=compile yarn synth' \
'COMMAND=build yarn synth' \
--export-csv results/complete.csv
TSC vs. SWC ¶
To test without incremental we perform cleaning of the dist
directory between runs:
hyperfine 'COMMAND=compile yarn synth' \
'COMMAND=build yarn synth' \
--prepare 'yarn clean' \
--export-csv results/complete.csv
Wrap-up ¶
Thanks for reading the methods, hopefully this is useful analysis if you are considering implementing swc
of tsc --incremental
.