Friday, November 6, 2020

Slow Swift Compilation of Boolean Comparisons

DeskA:

Since we moved parts of our codebase to swift, our compile times have effectively quadrupled. Trying to combat this, we’ve used the function and expression debug time flags to figure out if there’s something to be saved by simplifying expressions.

Via Nick Lockwood:

TIL writing

if foo == false {}

Compiles dramatically more slowly in Swift than:

if !foo {}

DeskA:

There are multiple instances of boolean comparisons being slow in our project. I can easily cut our overall compilation time by 10s by getting rid of explicit comparisons unfortunately

Xiaodi Wu:

In fact, it does not know that both sides are of type Bool, because == can be implemented to compare heterogeneous types and false can be any type that’s expressible by a Boolean literal. Therefore, it has to figure out every possible combination of implementations of == and types conforming to ExpressibleByBooleanLiteral that is available for use here to see if it’s a better match.

[…]

For numeric types specifically, there is a hardcoded compiler shortcut to make compile times tolerable until a general solution is discovered. No such optimization is hardcoded for Boolean values because it’s not idiomatic to write == true and == false.

Previously:

Update (2020-11-25): Keith Harrison:

Before you jump to conclusions and blame the Swift compiler for slow build times it’s worth getting a summary of the whole build process. Xcode 10 added a build timing summary.

[…]

There are a couple of compiler flags you can enable to get some extra information when the compiler is slowing down[…]

[…]

There’s a good WWDC 2018 Session on speeding up your Xcode builds.

9 Comments RSS · Twitter

Maybe it's not idiomatic in Swift, but some years ago, I started forcing myself to write "if (NO == x)" in Obj-C, since "if (!x)" is easy to miss when reading code, and "if (x = NO)" is even worse. I've never liked the aesthetics of it, but it's hard to screw up and had no effect on my compile times.

The ! operator is so easy to miss that my C++ colleages now write it as "if ( ! x)". It's a bit better in Swift where you don't need the parentheses, but it's still a terrible operator.

I prefer `foo == false` over `!foo` because in Swift when I see `!` I think force unwrap. The comparison form is thus easier for me to read.

> because it’s not idiomatic to write == true and == false

Which is a shame really. The reason for this is that if you are explicit in writing out the condition then it is possible to express all of them in a form that evaluates to 'yes this is the case'. In my years as assistant-accountant I learned that the best type of test is a positive one. A test where you conclude succes if the answer to the question the condition poses is yes. That is why I try to avoid writing conditions that are not explicit but what I really dislike is inverting the test with an exclamation point just to save nine keystrokes. I prefer if (it == true} {} over if (it) {} but I truly hate if (!that) {} and instead use if(that == false) {}.

If you're going to write "if (it == false)", why stop there? What you really mean is "if (it == false) == true"...

> I started forcing myself to write "if (NO == x)" in Obj-C

Don't do that.
It will encourage the usage of "if (YES == x)" for style consistency, which is not the same as "if (x)" in Obj-C and may cause subtle bugs.

> It will encourage the usage of "if (YES == x)" for style consistency, which is not the same as "if (x)" in Obj-C and may cause subtle bugs.

Isn't it only a problem if x is not a boolean? I would hope writing (YES == x) for something that's not a boolean would be a big red flag, but maybe I've written too much swift now and have become obsessed with type...

@charles The problem is that, in Objective-C, a BOOL has 8 bits. Any one of them can make x logically true, without it being == to YES (which is 1). So you should either omit the == or, if comparing two BOOL values, use !! or some other method to normalize them.

@michael Thanks for the info! I thought I knew what Jean-Daniel was talking about, but clearly I missed one more thing...

Leave a Comment