EnableSwiftBuildSystemIntegration slows down incremental builds

It seems that enabling the build system integration feature in Xcode 13.2 (13C90) severely harms the duration of incremental builds. Our project is split into multiple framework targets. These framework targets mostly don't depend on one another neither in build settings nor in the "Build Phases - Dependencies" tab and do build in parallel.

When the new integration feature is enabled it seems that builds without any changes or with changes to completely unrelated frameworks result in either a complete or almost a complete rebuild of the project. Without the integration feature the incremental build works as expected and build-time wise it seems that only those targets are affected by the change in source code rebuild.

To reproduce this issue I built our project in 3 scenarios switching the integration feature via defaults write com.apple.dt.XCBuild EnableSwiftBuildSystemIntegration 0/1:

  1. Clean
  2. Change in sources of a single framework
  3. No changes

Without integration feature it is roughly:

  1. Clean - 190 seconds
  2. Change in a single framework - 40 seconds
  3. No changes - 10 seconds

With integration feature it is roughly:

  1. Clean - 190 seconds
  2. Change in a single framework - 130 seconds
  3. No changes - 190 seconds

Why a change in a framework is faster than a no changes build puzzles me but it seems to be that way. I've attached the resulting .xcactivitylog files in the feedback assistant FB9804591 but I also decided to file this post in case someone has a similar issue. Please let me know if I can supply any other information.

4 Likes

I've just noticed that flag in the Xcode 13.2 release notes and tried it out in the excitement. However, I was disappointed as I actually observed ~20% slower builds with the setting enabled. I'm talking about clean builds in the debug configuration on the new M1 Pro.

I'm getting ~50 sec clean build times with the setting turned on, while the same build takes ~40 sec with the setting turned off.

I'm building a Swift package that has ~15 pure Swift dependencies.

1 Like

I'm also observing similar behaviour - our app is heavily modularised into two local Swift packages, each with many targets/libraries.

On a clean build with timing summaries enabled, enabling the new setting gives us a marginal speed improvement. On an 8 code iMac Pro it reduces the clean build time from 132s to 125s. On an M1 Max it reduces the build times from 78s to 72s.

However on a re-build without any changes - only tested on my M1 Max - with the setting enabled it consistently takes around 9-10s, whereas with the setting disabled it only takes 0.4s. With the setting enabled it seems to rebuild each of the dependent modules - even though these are fast individually, they add up.

Without the setting enabled it doesn't rebuild a single dependency and just instantly builds the main app target. In fact, I'm not sure the compiler is doing anything and the 0.4s is just our SwiftLint script phase.

I suggest you report your findings through an Apple bug report, as it isn't clear whether the engineers working on the integration read this forum much.

3 Likes

In my own testing, I see the same thing on my 10/20 iMac.

Firewalk, Xcode 13.3b2

Integration Off
Clean Build: 40.1s
Rebuild: 0.2s

Integration On
Clean Build: 30.0s
Rebuild: 3.3s

1 Like

Actually 13.3b2 is working for me with EnableSwiftBuildSystemIntegration enabled now ... at least for the 'always rebuild' problem.

CC @benjamin_herzog

That's great to know! We fixed many issues in 13.3b2 - especially incremental builds. There's still an outstanding issue in regard to that the build system always replans a target although inputs haven't changed. So null builds (without any changes) are still unnecessarily slow. Normal workflow should be much better now though.

1 Like

I'm very interested to see this continue to shape up. I'm working on a very large Swift codebase, and the new swift driver, "new" build system and the swift build system integration is the only combo that has gotten us close to the performance of the legacy Xcode build system.

Clean builds are almost identical now, where previously (with Xcode 13.0) the new build system resulted in a 30%+ build time regression. Incremental builds are still slower than clean builds even with 13.3b2. It seems the build system is still doing work for every target, even though only a small subset of the build graph was affected by a source code change.

For rough numbers on Xcode 13.3b2:

Legacy Xcode build system:

  • ~420s clean build
  • ~45s incremental build

New Xcode build system, swift build system integration:

  • ~420s clean build
  • ~740s incremental build

I’ve tried beta 3, but am still seeing the same slowdowns. I’ve submitted an issue via the Feedback Assistant with details. Hope that helps!

The issue continues to persist even in Xcode 14 beta 1. I benchmarked our build again in clean and incremental scenarios with as many build environments as I could think of. To get consistent results I didn't do anything but xcodebuild. For incremental builds I changed the same file in the same module every time. This is what I got:

Clean build time Incremental build time Xcode Swift compilation mode Build System EnableSwiftBuildSystemIntegration
144 30 13.4 wholemodule legacy
195 192 14 beta 1 wholemodule new
204 195 14 beta 1 wholemodule new
211 46 13.4 incremental legacy
224 72 13.4 incremental new
232 121 14 beta 1 incremental new
274 315 14 beta 1 incremental new

We normally use mixed linking where some of our modules are static libraries and others are dynamic frameworks. I reconfigured our project to link everything statically and this change seems to have quite a bit of impact on build performance:

Clean build time Incremental build time Xcode Swift compilation mode Build System EnableSwiftBuildSystemIntegration
264 52 14 beta 1 incremental new
285 266 14 beta 1 incremental new

It surprises me that we get best build times with legacy build system and wmo but it seems to be that way and also incremental builds with EnableSwiftBuildSystemIntegration are still slower. I filed the feedback FB10103172.

See if you can get into one of the Xcode build performance labs and talk to an engineer directly.

In my testing Xcode14b1 doesn’t improve things much yet and has some weird regressions.

1 Like

Also, checkout the new build visualizer in Xcode 14 to see if it shows any bottlenecks.

I don't know if it's just us, but we are still having the issue with incremental builds in Xcode 14.0.1. I tried out different linking configurations, compiler modes and whatever com.apple.dt.XCBuild defaults settings I could find but nothing helped.

It seems that sometimes on incremental builds the build system falls into a weird state where it just builds targets serially.

The other issue is that our clean builds get slower by ~15% just by selecting Xcode 14.0.1 instead of 13.4.

I think I'm seeing a similar bug where parts of clean builds will build serially, resulting in build times going from 20s to 60s (on an M1 Ultra). It's odd. Initial build, even if clean, will be super fast, 18 - 20s. If I clean, in Xcode or xcodebuild, the next build will be 60s. Been an issue since beta 1, still an issue in 14.1b3. FB10215613

3 Likes