If you’ve got enough time to go downstairs and get a cup of coffee, don’t optimize it as follows, because it’s a great life. If your company gives you a MacBook Pro 16-inch top or Mac Pro (radiator, trash can), please don’t optimize it as follows, because I’m sour…

Without further ado, let’s tune up our good friend Xcode.

Xcode configuration

1. Display the compile timer

You can enable timers directly in Xcode’s user interface. By default, this timer is not visible, but if you run the following command from the command line, the time will be displayed each time you build the application.

defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES
Copy the code

After the timer is enabled, you will see in Xcode’s build status bar how long it took to compile the application. Go to terminal and type:

2. Increase the number of threads used for Xcode compilation

Mac Test Parallelization and Simulator Test Parallelization are available in Xcode Settings, so let’s use them. The number of threads Xcode uses to run the Test and Simulator.

defaults write com.apple.dt.Xcode PBXNumberOfParallelBuildSubtasks 8
Copy the code

By default, Xcode uses the same number of threads as the NUMBER of CPU cores for compilation, but since compilation tends to involve more I/O operations than CPU operations, increasing the number of threads can speed up compilation to some extent. If you’re running a 4-core CPU on your Mac, changing the number of threads to 8 will make compiling slightly faster.

3. Change Build Active Architecture Only to Yes

In Build Settings of the Target of the project, find Build Active Architecture Only and change No to Yes.

This sets whether only versions of the current schema are compiled, or if No, all versions of the schema are compiled. Note that this option must be Yes in Release mode, otherwise the released IPA will not run on some devices. Once this change is made, it can significantly improve compilation speed.

The default instruction set for Apple mobile devices so far:

  • Armv6: iPhone2G/3G, iPod 1G/2G
  • Armv7: iPhone 3GS/ 4/4S, iPod 3G/4G, iPad 1G/2G/3G, iPad Mini
  • Armv7s: iPhone5, iPhone5c, iPad4
  • Arm64: iPhone5s and later, iPad Air, iPad mini2

Armv6, ARMV7, ARMV7S, and ARM64 are all instruction sets of ARM processors. In principle, all instruction sets are backward compatible. Note that the iOS emulator does not run the ARM instruction set. Compilation runs on the x86 instruction set, so the arm instruction set will only be executed on iOS devices.

4. Use a new build system

Apple started the new build system in Xcode 9, but it is not activated by default. Apple’s “New Build System”, written entirely in Swift, aims to improve overall performance and dependency management. However, with Xcode 10, new build Settings are activated by default and can be turned on from Xcode Files-> Project/Workspace Settings.

xcodebuild -UseNewBuildSystem=YES
Copy the code

5. Identify functions and expressions that lead to longer compile times

Xcode has built-in capabilities that let you identify functions and expressions that lead to longer compilation times. You can specify a compile-time limit and identify areas in the code base that exceed this limit.

Add the following line to the project build setting “Other Swift Flags” :

-Xfrontend -warn-long-function-body = 300 
-Xfrontend -warn-long-expression-type-checking = 300
Copy the code

This flag warns you if a function or expression takes longer than the specified time. This means that you must optimize a function or expression.

6. Increase the number of concurrent build tasks run for the Swift project

In Xcode 9.2, Apple introduced an experimental feature that allows Xcode to run Swift build tasks in parallel. By default, this feature is not enabled and you need to turn it on from the command line.

defaults write com.apple.dt.Xcode BuildSystemScheduleInherentlyParallelCommandsExclusively -bool YES
Copy the code

7. Delete “Run Script Phase”

Remove “Run Script Phase”, like SwiftLint, Twine, etc., but keep them if you need them.

8. Parallel build

This option allows Xcode to speed up the total build time by building targets that do not depend on each other at the same time. This saves time on projects with many smaller dependencies that can easily be run in parallel.

When you open your project in Xcode 10, build parallelism should already be enabled. To check or change this option, open the schema editor, select “Build” in the sidebar, and make sure “Parallelize Build” is selected at the top.

Appropriate build Settings

1. Change Debug Information Format to DWARF

In the Build Settings of the Target of the project, find the Debug Information Format and change the DWARF with dSYM file during debugging to DWARF.

If the program crashes, the function stack corresponding to the crash location will not be output. However, since the debugging information can be viewed in Xcode in Debug mode, the change of DWARF does not have much impact. Once this change is made, it will make compiling much faster.

2. Whole module Optimization (WMO)

In Xcode, we can choose from three optimization levels: None, Fast and fast, whole module optimization. Using holistic module optimization makes compilation very fast. However, choosing fast or fast, whole module optimization will not allow the developer to debug the application.

Code optimization

Tips and tricks

A. Download Xcode’s Build time analyzer, which visually tells you how long each part of your code took to compile. Github.com/RobertGumme…

2. Third-party dependencies

There are two very popular dependency management technologies/tools: Cocoa Pod, Carthage, Swift package manager, and Git submodules.

The most common way to handle third-party dependencies in iOS projects is to use CocoaPods. It’s easy to use, but not the best choice if you’re concerned about build time.

One alternative that can be used is Carthage. It’s a little more tedious than CocoaPods, but it cuts down on build times.

3. The optimized CocoaPods

If you use CocoaPods, you can optimize all dependencies by adding the following to the end of your Podfile.

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      if config.name == 'Debug'
        config.build_settings['OTHER_SWIFT_FLAGS'] = ['$(inherited)'.'-Onone']
        config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] = '-Owholemodule'
      end
    end
  end
end
Copy the code

4. Make small changes to the code

A. Use “final” when you know that you do not need to override a statement. The final keyword is a class declaration, a method or property that makes the declaration unoverridden. This means that the compiler can make direct function calls instead of indirect ones. B. Use Private and Fileprivate when you do not need to access the file externally. Applying the privateor or Fileprivate keyword to a declaration limits the declaration’s visibility in the file in which it is declared. This enables the compiler to determine all other possible overridden declarations. C. Use value types in arrays: In Swift, types fall into two distinct categories: value types (structures, enumerations, tuples) and reference types (classes). One key difference is that value types cannot be included in NSArray. Therefore, when using value types, the optimizer can eliminate most of the overhead in the Array that is necessary to handle the possibility that the Array supports NSArray. D. If the NSArray bridge is not required, you can use a ContiguousArray with a reference type. If you need an Array of reference type that doesn’t need to bridge to an NSArray, use a ContiguousArray instead of Array:

class C { ... }
var a: ContiguousArray<C> = [C(...), C(...), ..., C(...)]
Copy the code

reference

  • Speed up the XCode compile links (and modify) : blog.51cto.com/zhuxianzhon…
  • Restricted Up Xcode Builds:medium.com/@ricardocas…
  • Build the Active Architecture Only:www.jianshu.com/p/d22acd19e…
  • CHANGE MACOS USER PREFERENCES VIA COMMAND LINE: pawelgrzybek.com/change-maco…