Cartography icon indicating copy to clipboard operation
Cartography copied to clipboard

Very long compile time in large functions

Open samuelbeek opened this issue 8 years ago • 18 comments

Hi, using this tool, I found that a some of the larger constrain functions in my app take a really long time to compile, in the 500ms spectrum on a pretty new MacBook Pro. Do you know if there's specific things that cause these longer compile times? I'd love to contribute some improvements and can do some tests myself, but if you happen to know where to look that'd be great.

Thanks

samuelbeek avatar May 23 '16 04:05 samuelbeek

Just wanted to chime in and say I am seeing this also. Currently a huge chunk of my build time is spent in these methods. I use the same tool as @samuelbeek posted.

MPiccinato avatar Jun 07 '16 13:06 MPiccinato

Both @MPiccinato and I dove into this and it is slowest when combining assignment and comparison operators. So for instance in a line like this one view1.centerX == view.centerX + 10.

Anything we can do about that?

samuelbeek avatar Jun 14 '16 09:06 samuelbeek

I've added a couple of functions to my project to replace the == operator in cartography. You can find them in this Gist (WIP). It slimmed down the compile time of most Cartography blocks to 30% of the original time, which are pretty impressive results.

samuelbeek avatar Jun 14 '16 12:06 samuelbeek

I'm seeing the same things. Compile times over 100ms for not overly complex stuff

Noticed one thing:

    constrain(self.contentView, self.titleLabel, self.contentLabel, self.newMessages) { (view: LayoutProxy, titleLabel: LayoutProxy, contentLabel: LayoutProxy, newMessages: LayoutProxy) in
        titleLabel.bottom == contentLabel.top
        
        titleRight = titleLabel.right == view.right - (intraCellSpacing + MessageCountIndicator.counterWidth) // Much faster
        contentLabel.right == titleLabel.right
        
        newMessages.centerY == view.centerY
        newMessages.right == view.right - intraCellSpacing
        newMessages.width == newMesagesWidth
        
        contentLabel.bottom == view.bottom - intraCellSpacing
        contentLabel.left == titleLabel.left
    }

vs

    constrain(self.contentView, self.titleLabel, self.contentLabel, self.newMessages) { (view: LayoutProxy, titleLabel: LayoutProxy, contentLabel: LayoutProxy, newMessages: LayoutProxy) in
        titleLabel.bottom == contentLabel.top
        
        titleRight = titleLabel.right == view.right - intraCellSpacing - MessageCountIndicator.counterWidth  // Slow version
        contentLabel.right == titleLabel.right
        
        newMessages.centerY == view.centerY
        newMessages.right == view.right - intraCellSpacing
        newMessages.width == newMesagesWidth
        
        contentLabel.bottom == view.bottom - intraCellSpacing
        contentLabel.left == titleLabel.left
    }

This shaved off 200ms from originally >300ms. Still not really great having them over 100ms but at lot better at least.

LucasVanDongen avatar Dec 22 '16 00:12 LucasVanDongen

Is it to do with type inference? Swift is still a dog with that

CVertex avatar Dec 22 '16 04:12 CVertex

I've come into this as well (having big compile times on all Cartography closures).

Looks like function overload could be the cause (constrain has various method overloads). I've been thinking how can we change it to solve the problem, but it is so good like it is right now...

Does someone think there's a good way of fixing it? Or should we just keep relying on thinking it'll get better on a future Xcode release? I've thought of just having the constrain(_ view: [View] ...) one, and rename the other ones so it's clear which one is used, but I don't really like it :(

Lascorbe avatar Feb 28 '17 12:02 Lascorbe

I'm not sure it's the constrain overloads. I've tried reducing it to only the array call with no meaningful difference in compile time.

ianyh avatar Mar 06 '17 19:03 ianyh

For what it's worth, anecdotally this seems to be a lot faster for me nowadays.

ianyh avatar Apr 20 '17 19:04 ianyh

@ianyh What did you change to reduce the compile time?

rvi avatar Apr 20 '17 23:04 rvi

Nothing. Swift compiler changes seem to have improved the type inference, which is what I think was slowing it down.

ianyh avatar Apr 20 '17 23:04 ianyh

Again, this is somewhat anecdotal. I haven't done any thorough timing tests.

ianyh avatar Apr 20 '17 23:04 ianyh

Building my app after cleaning is more than 11min... Xcode 8.3.2 ?

rvi avatar Apr 20 '17 23:04 rvi

Yes. It's possible I've just adjusted to my capricious robot overlords. I'll do some more thorough timing when I get a chance.

ianyh avatar Apr 20 '17 23:04 ianyh

Any update on this issue? We have some large (30 line) constrain functions that are giving us 600-700ms compile time. Is there anything we can do to decrease this? Btw it looks like it hasn't been mentioned before but you can measure the compile time of functions by following this guide here: https://www.jessesquires.com/blog/measuring-compile-times-xcode9/?utm_campaign=iOS%2BDev%2BWeekly&utm_medium=web&utm_source=iOS_Dev_Weekly_Issue_320

pedromcunha avatar Oct 16 '17 21:10 pedromcunha

No updates, so you're welcome to take a look 👍

orta avatar Oct 16 '17 23:10 orta

Hi, reading this thread it seems very similar to an issue we had on Stevia a while ago, due to operator overloading, we're all in the same boat ! The way I understand it is that == is a common operator so the compiler has a hard time finding the right overload. For instance, in our project replacing '-' operator by '--' made it easier on the compiler yielding faster compile times. The bad news is this approach means touching the api :/ My best guess is to wait for the compiler to get better and better with each release as it seems to have improved over the past releases. More details on the similar issue here: http://freshos.org/SteviaDocs/knownIssues/ Hope it helps :)

s4cha avatar Nov 20 '17 13:11 s4cha

I've added PR #293 as a potential solution. At Instacart we use Cartography heavily in one of applications and after migrating most of the code over to the new syntax the (clean) build time has been halved (from about 5 min to 2.5). All of our view constraint setups run in a few milliseconds where most were in the hundreds, if not thousands (worst case we had was 8800ms for one view).

Strongly recommend the core team looks over this issue and applies some (maybe not my) solution.

Feel free to use github "instacart/Cartography" "acr/custom-operator" (carthage) if you wish to get the improvements, unfortunately you must add the ~ prefix to all your ==, +, -, *, /, <= and >= operators, but hopefully we'll see a more permanent solution to this.

Thanks for a great library!

acrookston avatar Jun 15 '18 21:06 acrookston

It's difficult to find a satisfying solution without compromising the API. As a workaround, one thing you can do is to help the type checker:

- label.baseline == otherLabel.firstBaseline + 10
+ let _:NSLayoutConstraint = label.baseline == otherLabel.firstBaseline + 10 as Expression<Edge>

Less readable but improves compile times considerably. If it looks like the compiler performance problems won't be addressed (soonish) then a new API is probably in order.

jberkel avatar Dec 21 '18 13:12 jberkel