Hi,
I work on a project with a pretty big codebase.
Our team has recently adopted macros on a single module in the project, and i would like to share our finding from this experience.
First of all, let me share some info on the module and the macros in question:
- the module is ~100k LOC
- there are ~700 macros applications in the module
- all macros are attached member/memberAttribute
- macros generate inits, getters, setters, nested classes, properties
-0- When adopting macros, we were already aware of the build time overhead that comes from building swift-syntax, and given that we use Bazel in the project, we were able to almost entirely mitigate that overhead by precompiling and caching our macros.
-1- When we applied the macros in the module, we saw the following changes in the build times:
Clean build time (mean, s):
- Before: 85.001
- After: 152.284
Incremental build time (mean, s):
- Before: 17.283
- After: 84.018
-2- Then we realised that we were building the macros for Debug, and after switching to Release, we saw the following changes in the build times:
Clean build time (mean, s):
- Before: 149.204
- After: 110.498
Incremental build time (mean, s):
- Before: 80.036
- After: 34.682
-3- Then we were curious, if all overhead was coming entirely from our implementation of the macros, so we converted them to essentially no-op, and we saw the following changes in the build times:
Clean build time (mean, s):
- Before: 110.453
- After: 86.511
Incremental build time (mean, s):
- Before: 43.259
- After: 18.090
So, firstly, as you can probably see, it's really important to be building macros for Release, as that apparently significantly impacts their performance and therefore build times.
Secondly, as you can probably see, we did not observe any overhead by the macros themselves, therefore it can entirely be attributed to our implementation of them. And, since we didn't yet invest in optimising them for performance, given these results, we are hopeful we can still improve.
And, finally, obviously, precompiling and caching macros can really help with not having to build swift-syntax again and again.
I hope our finding will be helpful. Thanks.
Notes:
- All measurements were taken with precompiled macros
- All measurements are given as mean value over 5 runs
- All measurements are given in seconds
- "After" indicates the measurements for the commit with mentioned changes
- "Before" indicates the measurements for the the immediately preceding commit