David Nedrow
David Nedrow

Reputation: 1158

Swift functions taking a long time to compile

We have a mixed Obj-C/Swift project. The Swift compilation takes an inordinately long time.

I used the following to build the project and glean the function timing.

xcodebuild -workspace Pay.xcworkspace -scheme Pay clean build OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" | grep .[0-9]ms > build.log

If I then sort this file using sort -nr, I get a file with the function build times sorted from highest to lowest.

For example, using Xcode 8.3.2 and given the following function:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let scrollDiff = scrollView.contentOffset.y - self.previousScrollOffset

    let absoluteTop: CGFloat = 0;
    let absoluteBottom: CGFloat = scrollView.contentSize.height - scrollView.frame.size.height;

    let isScrollingUp = scrollDiff > 0 && scrollView.contentOffset.y > absoluteTop
    let isScrollingDown = scrollDiff < 0 && scrollView.contentOffset.y < absoluteBottom

    if !successView.isHidden && canAnimateHeader(scrollView) {

        // Calculate new top constraint
        var newTopConstraint = self.headerTopConstraint.constant
        if isScrollingDown && scrollView.scrolledToTop {
            newTopConstraint = -(max(self.minHeaderHeight, abs(self.headerTopConstraint.constant) - abs(scrollDiff)))
        } else if isScrollingUp {
            newTopConstraint = -(min(self.maxHeaderHeight, abs(self.headerTopConstraint.constant) + abs(scrollDiff)))
        }

        // Header needs to animate
        if abs(newTopConstraint) != abs(self.headerTopConstraint.constant) {
            self.headerTopConstraint.constant = newTopConstraint
            self.updateHeader()
            self.setScrollPosition(self.previousScrollOffset)
        }

        self.previousScrollOffset = scrollView.contentOffset.y
    }
}

This timed at 560ms for compilation.

Thinking it might be a type inference issue, I declared the types for scrollDiff (CGFloat), and isScrollingUp/isScrollingDown (Bool).

That reduced the compilation time to 485ms.

I can't think of what else might be causing the long compile time. We have a number of functions that all time above 1ms, some significantly higher as in the above example.

I'd appreciate any pointers people may have.

Upvotes: 0

Views: 177

Answers (1)

Charles Srstka
Charles Srstka

Reputation: 17050

I know this isn't much consolation right now, but when you can upgrade to Xcode 9 you may see an improvement right out of the box. The reason I say this is because, as my RetinaBook is currently in the shop getting its battery replaced, I'm testing this on an ancient 2008 MBP that's not supposed to even be able to run this software (I had to apply a hack to get Sierra to install), and even with this geriatric duct-taped hardware, Xcode 9 compiles your example in only 181.73ms.

With that said, I was able to knock that down to 87.93ms by separating out the abs() calls, like so, so you may want to try that to see if it similarly halves compilation time on your end.

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let scrollDiff = scrollView.contentOffset.y - self.previousScrollOffset

    let absoluteTop: CGFloat = 0
    let absoluteBottom: CGFloat = scrollView.contentSize.height - scrollView.frame.size.height

    let isScrollingUp: Bool = scrollDiff > 0 && scrollView.contentOffset.y > absoluteTop
    let isScrollingDown: Bool = scrollDiff < 0 && scrollView.contentOffset.y < absoluteBottom

    if !successView.isHidden && canAnimateHeader(scrollView) {

        // Calculate new top constraint
        let absConstraint = abs(self.headerTopConstraint.constant)
        let absDiff = abs(scrollDiff)
        var newTopConstraint: CGFloat = self.headerTopConstraint.constant
        if isScrollingDown && scrollView.scrolledToTop {
            newTopConstraint = -(max(self.minHeaderHeight, absConstraint - absDiff))
        } else if isScrollingUp {
            newTopConstraint = -(min(self.maxHeaderHeight, absConstraint + absDiff))
        }

        // Header needs to animate
        if abs(newTopConstraint) != abs(self.headerTopConstraint.constant) {
            self.headerTopConstraint.constant = newTopConstraint
            self.updateHeader()
            self.setScrollPosition(self.previousScrollOffset)
        }

        self.previousScrollOffset = scrollView.contentOffset.y
    }
}

Upvotes: 1

Related Questions