What is the best way to diagnose slow build times? I've got an all-Swift Xcode 15 project with around ~350 files and it has become very slow to build, even for incremental builds. The vast majority of files build in the first second or two but there's always 10 or so left over for around another 20 seconds.
I've done pretty much everything outlined in this medium article but I don't seem to see any new timing information anywhere, other than the overall build time, and in the Report seeing that the Comiling Foo.swift, Bar.swift, ... step took pretty much all of the build time. Have those flags been deprecated, or am I just doing something stupid?
Sadly I've already tried everything in that link. Those compiler flags (-Xfrontend -warn-long-function-bodies=<limit> etc) don't seem to have any effect for me - I've tried reducing the threshold down to basically nothing but still don't see any warnings. I've also added the compiler flag to show build times for individual methods (-Xfrontend -debug-time-function-bodies) but I don't see any results anywhere for this either.
Has it become slow to build just recently? The first thing I would do in such case is to review changes prior to slowdown and look for complex types resolution, e.g. long chain of map/filter/etc. without type annotations, or array/dict literals.
Type checking can often take large amounts of time, e.g.:
complex expressions
implicit conversion between CGFloat / Double
let diff = abs(UIScreen.main.brightness - value)
let diff: CGFloat = abs(UIScreen.main.brightness - value) // much faster
generic functions
...
There may also be other reasons, such as assets compilation, build phases and codegen (like Sourcery / SwiftGen / R.Swift), LTO optimisation, build settings, 3d party dependencies, macro etc.
To investigate it faster and reduce the number of questions, is it possible to share build graph and build log?
The logs are definitely reporting that it's the compilation step that is taking all the time, not asset catalogs or anything like that, also I don't have any external dependencies or any codegen going on.
This is the setup I've been using...
...but I can't find timing information for any specific files or methods anywhere in the logs. Where should the timings appear? Do these settings work for you?
Is your code in one module or are you using packages to split them up? Those flags won't be passed to packages, so if you're modularized like that, you'll need to find a way to pass them to each package individually.
Storyboard / Xib can also increase time compilation
Making properties and Types private / file private
mark classes as final
App separation into several modules can also help to reduce build time, but I highly not recommend to do it:
unless the root reasons of slow compilation are found
if slow compilation is the only reason, as modularisation has its own costs
It's worth to mention that common recommendation is to not care about type checking and use type inference by default. Unfortunately sometimes because of it build time can increase significantly, e.g.:
let isLeftSide = (point + velocity) < (view.bounds.width / 2)
let isLeftSide: Bool = (point + velocity) < (view.bounds.width / CGFloat(2)) // faster
case .hidden: arrowOriginY = -ArrowConstants.arrowHeight
case .hidden: arrowOriginY = ArrowConstants.arrowHeight.negated() // faster
guard let filter = CIFilter(name: "CIPDF417BarcodeGenerator") else {
guard let filter: CIFilter = CIFilter(name: "CIPDF417BarcodeGenerator") else { // faster
This project is an indie game I've been writing, it's all SpriteKit so absolutely minimal storyboard/xib stuff going on. No modules, no external packages or dependencies, no codegen, just very boring, vanilla code!
Given how easy it is to trip the swift compiler into taking a long time to type check, it's a shame and kinda surprising that it's so hard to get diagnostics on build times for specific files or methods (happy to caveat that with it possibly being me being stupid!)
Two things jump out: processing the Info.plist shouldn't take 8s, and a 5s, blocking shell script seems suspicious as well. @Pampel you can try turning on the parallel script setting in the project, but really you should see what's going on there.
Yes, it is better to say compiler don’t need to run these checks. Optimisations are another topic, e.g. final classes have static method dispatch as there are no overloads.
Saying "one module" do you mean there is only App-target containing all of the code or there is an App-target that import a framework with the most of codebase?