4

I have a open source project and the counter of files in project are more than 40.

I build the project when the configuration is Debug and the compile time is 2m22s. And I also use the BuildTimeAnalyzer, the longest time of all is 28ms.

But when I build the project with the Release configuration, it stuck in Compile Swift source files more than one hour.

I have no idea about this, please help me.

Pluto Y
  • 61
  • 1
  • 4

2 Answers2

2

In the DEBUG build, if you add up all the time spent on each function, you get about 7s. The numbers don't quite add up — you have spent 142s to build the whole thing, but these functions just take about than 7s to compile??

That's because these timing just accounts for type-checking each function body. In the Swift frontend there are three flags you could use:

  1. -Xfrontend -debug-time-compilation
  2. -Xfrontend -debug-time-function-bodies
  3. -Xfrontend -debug-time-expression-type-checking

Let's use the first to see the whole picture. Pick one slow file, say Option.swift, and look:

===-------------------------------------------------------------------------===
                               Swift compilation
===-------------------------------------------------------------------------===
  Total Execution Time: 30.5169 seconds (43.6413 wall clock)

   ---User Time---   --System Time--   --User+System--   ---Wall Time---  --- Name ---
  23.5183 ( 80.1%)   0.7773 ( 67.6%)  24.2957 ( 79.6%)  34.4762 ( 79.0%)  LLVM output
   3.7312 ( 12.7%)   0.0437 (  3.8%)   3.7749 ( 12.4%)   5.4192 ( 12.4%)  LLVM optimization
   1.8563 (  6.3%)   0.2830 ( 24.6%)   2.1393 (  7.0%)   3.1800 (  7.3%)  IRGen
   0.2026 (  0.7%)   0.0376 (  3.3%)   0.2402 (  0.8%)   0.4666 (  1.1%)  Type checking / Semantic analysis
... <snip> ...
  29.3665 (100.0%)   1.1504 (100.0%)  30.5169 (100.0%)  43.6413 (100.0%)  Total

Turns out it's not Swift that is slow, but LLVM! So there is not point looking at type-checking time. We can further check why LLVM is slow using -Xllvm -time-passes, but it won't give us useful information, it's just saying X86 Assembly / Object Emitter is taking most time.

Let's take a step back and check which files take most time to compile:

Option.swift             30.5169
Toolbox.swift            15.6143
PictorialBarSerie.swift  12.2670
LineSerie.swift           8.9690
ScatterSerie.swift        8.5959
FunnelSerie.swift         8.3299
GaugeSerie.swift          8.2945
...

Half a minute is spent in Options.swift. What's wrong with this file?

  1. You have a huge struct, with 31 members. Compiling that struct alone takes 11 seconds.
  2. You have a huge enum, with 80 variants. Compiling this enum alone takes 7 seconds.

The first problem is easy to fix: Use final class instead! The second problem would not have a simple fix (I don't see any time improvement with alternatives e.g. replace the enums with class hierarchy). All other slow files have a similar problem: large structure, large enums.

Simply replacing all struct with final class is enough to bring the compilation time from "over hours and still compiling" to "2.5 minutes".


See also Why Choose Struct Over Class?. Your "struct"s may not qualify as structs.

Note that changing from struct to class do change the semantics of users' code since classes have reference semantics.

Community
  • 1
  • 1
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
0

Try this.... under Build Settings -> Swift Compiler - Code Generation for your Release choose SWIFT_OPTIMIZATION_LEVEL = -Owholemodule. Then under Other Swift Flags enter -Onone. Doing this carved off big chunks of time off my project.

Vader
  • 77
  • 1
  • 7