Berik
Berik

Reputation: 8143

Xcode build slow for .c and .m files

After updating OSX to High Sierra and updating Xcode to 9.2.0, project build times for bigger projects got out of hand. The build times went from ~10 minutes up to ~120 minutes.

While researching I noticed that Xcode spawns xcexec child processes which take most of the cpu usage. xcexec spend almost all of the time calling the system close call. Each xcexec process calls about 2 million close calls per minute.

Upon inspecting the xcexec binary, this seems to be a wrapper tool for launching other build actions (e.g. clang).

I have fully reinstalled Xcode with no change. The build system is set to default.

What causes this behaviour?

Upvotes: 0

Views: 290

Answers (1)

Berik
Berik

Reputation: 8143

The installation instructions for watchman instructs you to set kern.maxfiles like this:

 $ sudo sysctl -w kern.maxfiles=10485760
 $ sudo sysctl -w kern.maxfilesperproc=1048576

The default setting for (both of) these values is 131072 on macOS High Sierra. Watchman's suggestion is a 80x change to a performance critical setting of your kernel. Adjusting these values can result in different performance characteristics, especially for file heavy operations like compilation.

Watchman changes the limit so that it is allowed to watch more files at the same time.

Xcode however will start indexing your project and open as many files as allowed (via kern.maxfiles). During the compilation phase, Xcode launches xcexec which will close any open file descriptors for indexing and only then launch the build step sub-process. That operation should take almost no time. But after changing kern.maxfiles it suddenly does.

I benchmarked on an MBP mid 2015, macOS 10.13.3, Xcode 9.2.0.

According to my benchmarking kern.maxfilesperproc has no influence on Xcode`s build performance.

The performance of Xcode builds is heavily impacted as soon as kern.maxfiles is above 327680.

I recommend setting kern.maxfiles to (no value bigger than) 327680 if you need to support watchman with bigger projects.

Note that setting kern.maxfiles with sysctl is not persistent across reboots. Adjust the values in /Library/LaunchDaemons/limit.maxfiles.plist.

Upvotes: 1

Related Questions