Add @immutable attribute for structs and enums

-Os doesn't work for me - compilation error. Only -O works for me in there.

That's because in Swift the flag is called -Osize.

1 Like

Thank you, and it totally makes sense, as with Os it is absolutely non obvious what "s" stands for ("size? speed?").

I made a quick & dirty two hundred lines mock app (which is still not quite realistic example of course). godbolt link.

Got these stats for it:

struct -O 14189
struct -Osize 13212

classes -O 13033
classes -Osize 11768

With class version I had to put manual implementation for inits / EQ / Hashable - something I have a luxury not to do when using structs - but I left that code in the struct version as well just in case.

The class version size is indeed some 10% smaller - not too significant on my book but for some apps it's probably bigger or in some cases 10% can be a significant difference.

(Sometimes these numbers work like this, and I'm only half kidding: "we use our internal autoupdater and host those updates on our server, the amount of traffic increase due to app being 10% larger multiplied by 100 million users is extra $50K per update which we can't afford as we are committed to having weekly releases and our budget is limited by xxx amount".)

Worth to mention that in real app there's not just code, perhaps all those texts / icons / images / sounds and videos contribute a significant amount to the total "application binary size".

From what little I know about how some of the big companies like the mentioned are operating - the major reason to use classes (at least until recently) was Obj-C compatibility, as the code bases are quite huge and contain hundreds man years of code written when Swift was too young or did not exist.

I recon it would be quite a major undertaking for OP or anyone else to convert from classes to structs or wise a versa in a real world app just to see the more realistic stats. I wonder though what binary size increase (from using structs vs classes) do they have in mind, is it 10% or a significantly bigger number? cc @Logan_Shire and @tstromberg

1 Like

A place that interferes with such fundamental code design choices based on concerns about binary size would be a short-sighted place. And I'm baffled and saddened to hear that work places with such rules exist at all :cry:

Edit: I first expressed my shock and disappointment with inappropriate language and was flagged within minutes. I hope this is now clean and clear enough :wink:

2 Likes

As with everything, there are tradeoffs. If business metrics go down 20% (pulling a number out of thin air) once you surpass the over-the-air download limit on iOS (which used to be much lower), there are strong arguments to be made in support of anything that will decrease the binary size.

Were there strong objections to these decisions? Yep. Was it ultimately the right call to make? Also yep.

1 Like

We generated all our model code from templates, so switching between structs and classes was actually fairly trivial. I don't recall exactly how large a difference it made, but it was significant enough to push us to do it. This was 5+ years ago, so the compiler has likely improved in the meantime. Our model graph was highly nested (types with lots of properties, many of which were not primitives and had a bunch of properties themselves) — not sure how much that contributed to the size.

Just to clarify for other readers, memmove or memcpy IS linear complexity in the size of the struct. More data, more time to copy. This is a C++ problem too. If you want to pass a large struct to a function you typically use a const reference. As others mentioned, can potentially use inout parameters in swift too.

I've seen more awkward decisions than this. I remember starting a new project in Objective-C in 2017 (swift was already ok then) just because the main C++ developer who was on the backend side of things and didn't use swift or obj-c per se himself, didn't know how to read / review swift code and was more familiar with Objective-C.

Big companies (like mentioned above) understandably have lots of Obj-C code - and when you interop Obj-C and Swift code you can't even use value types - everything needs to be NSObject - so this decision I can understand (although personally would do it differently, as I've been in those cross language projects a few times and didn't like the end result every time).

Note that I was specifically talking about space complexity (not time) - the size of the generated code to copy those structs.

2 Likes

Note that I was specifically talking about space complexity

Ah, my mistake. Well it wouldn't even occur to me this problem would require non-constant space, so I'm as concerned as you are.

Ah, I've never thought about it this way and have luckily never had binary size as a requirement, but that makes sense.

I just hope these size limitations will lift before they become a burden to compiler developers. Sometimes these types of problems are swept away by the wave of inevitable technological evolution, just like movie streaming became a thing once internet bandwidth had caught up ...