Cartography
Cartography copied to clipboard
Very long compile time in large functions
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
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.
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?
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.
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.
Is it to do with type inference? Swift is still a dog with that
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 :(
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.
For what it's worth, anecdotally this seems to be a lot faster for me nowadays.
@ianyh What did you change to reduce the compile time?
Nothing. Swift compiler changes seem to have improved the type inference, which is what I think was slowing it down.
Again, this is somewhat anecdotal. I haven't done any thorough timing tests.
Building my app after cleaning is more than 11min... Xcode 8.3.2 ?
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.
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
No updates, so you're welcome to take a look 👍
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 :)
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!
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.