126 points by todsacerdoti 9 days ago | 7 comments
silisili 9 days ago
I was curious how large these static binaries would be since the last announcement. Being honest, 100MB is quite a bit larger than I was expecting. Probably fine for CI business apps and such, but kinda rules out a lot of linux util type things.
repelsteeltje 9 days ago
I seem to have missed the part where he explains why he's targeting Alpine Linux for his Swift app. Alpine isn't mainstream (the way Ubuntu or rhel are) and stands out mostly for being compact and clutter free.

So... indeed... If you somehow end up with 100MB package for what is essentially just 250kB, I'd say something did not go right. Feels very square peg in round hole.

Tildey 9 days ago
If I had to guess, Alpine is a very popular choice for building container images in Docker/Kubernetes/whatever the new hotness is since I last worked with containers. Mostly because the aforementioned small size and low overhead add up if you’re at any sort of scale (even one instance on top of your desktop OS).

If you’re wanting to containerise the program, maybe it’s less resource intensive to add those things to Alpine than to run another distro with more support? Obviously only speculation

iudqnolq 9 days ago
Doesn't Kubernetes deduplicate layers by hash? I thought the key to minimizing overhead was standardizing on a limited set of images across everything you'll be running on the same host.

Just from reading HN it seems like Alpine had a brief fad a few years ago but never got much traction.

arccy 9 days ago
the underlying container runtime (usually containerd) will dedupe shared layers, but there's a lot of things you don't get to directly control, like third party apps, and the bottleneck when spinning up new nodes is real. Plus, envs where there isn't that much caching, like CI.
lolinder 9 days ago
The Alpine Linux docker image is 7.8 MiB to Ubuntu's 76 MiB, so they get a savings of about 68 MiB in image size by using Alpine Linux over Ubuntu.

From the stats in TFA it looks like about 43 MiB of the file size is the Swift runtime itself, which would need to be installed in any OS. This leaves ~57 MiB extra in their static binary approach vs what they'd get out of dynamic linking.

68 MiB (saved by using alpine) - 57 MiB (lost to static linking) = 11 MiB (net gains from Alpine), so their Alpine Linux solution is actually about 10% smaller than the equivalent that uses an Ubuntu image.

Is that worth the extra work they put into it? It probably depends on the application.

jonhohle 9 days ago
Depending on how builds and deployments are done, there is a high likelihood that the lower userspace layers are much slower moving than the upper application layers. After your second build, dynamic linking wins and everything after that it pulls even further ahead.

Smart builds can make application deltas really small. I helped design a system where our several hundred MB monolith could be hot patches with a layer of a few thousand kilobytes and most builds were 10-20MB. Obviously this wouldn’t have worked for a statically linked app.

yjftsjthsd-h 9 days ago
Some of us are just using Alpine as our primary OS, and would need a compelling reason to do anything else.
philjohn 8 days ago
Because as much as it is great, musl isn't a drop-in replacement for glibc and requires extra work from maintainers to get software working on it (see PyTorch, AWS CLI etc. etc.).
9 days ago
dagmx 9 days ago
A big chunk (roughly a quarter) of it is the Unicode handling library.

I think eventually the stdlib will be split up more so that it’s not one giant blob, but there’s a lot of areas that will be reducing in the future.

arp242 9 days ago
75M is still huge for this type of thing.

My smallest Go CLI is 1.6M. This is probably about as small as you can get in Go and still do something useful. Some of my other (larger) Go CLIs range from ~2.5M to ~6.5M. Go is not known for producing small binaries.

BoingBoomTschak 9 days ago
For fun, I made an executable hello world with SBCL and it came out weighing 40MB (no compression, of course); this also includes Unicode data and a complete compiler. Something's wrong here.
dagmx 9 days ago
My point is that the issue is the stdlib is monolithic at the moment. As it gets split up in the near future, the binaries will reduce in size.
arp242 8 days ago
I thought Swift compiles to machine code? Can't it eliminate the unused stdlib code?

Well, I guess not if the statically linked binaries are so large, but this seems like the more major reason for these very large binaries instead of stdlib being monolithic? (Not entirely sure what that means in this context)

9 days ago
9 days ago
yjftsjthsd-h 9 days ago
Similar to chroot, I wonder if flatpak is a good option? Obviously native is better but I know that that works because that's how I've run Steam on Alpine
xena 9 days ago
Flatpak isn't really intended for command-line apps. Maybe this is where something like dockerc (https://github.com/NilsIrl/dockerc) can shine?
tadfisher 9 days ago
Nix is another option for static builds. There is a `pkgsStatic` tree for building static musl-linked binaries, which would be a perfect integration point for Swift's static Linux target.
neonsunset 9 days ago
Hmm, so it includes the entirety of Swift's standard library? Isn't there an option to tree shake/trim it? That's what .NET AOT compilation does (standard library is always included, sans the dependency on glibc or musl, which you can statically link into the binary as well should you need that)
JCWasmx86 9 days ago
The biggest symbol of a statically linked swift binary that I have, is icudt_swift65_dat with 27.98MB, so I think that's not so easy to remove (nm v3.1.2 --size-sort --radix=d|swift demangle) And I think if you strip debuginfo it will be smaller (For a statically linked program of mine: 98MB -> 56MB)

But I think for a distribution it makes more sense to link swift programs dynamically against the runtime libraries, like it's the case for e.g. the C standard library, OpenSSL etc., as you can assume they all work with the same version and are ABI-compatible.

I tested it with a nearly static build (Still links against glibc and friends): 55MB get stripped to 44MB, so not that much. 27MB of that is icudt_swift65_dat, so I guess you would have to optimise that first

0xTim 9 days ago
With the new Foundation work going on, when you migrate to that, if you don't import `FoundationInternationalization` then you won't pull in all of ICU and it won't be bundled in
georgelyon 9 days ago
If I’m not mistaken, the embedded swift mode aims to make ICU (the 27mb file for Unicode support) optional (and thus easily removed where it isn’t needed)
9 days ago
xvilka 9 days ago
There's no reason to use Swift outside of the Apple platform. Rust is much better option and more cross-platform. And they work hard on reducing the binary size as well.
dagmx 9 days ago
This is like a C++ dev saying there’s no reason to use rust.

Swift offers a lot of ergonomic values over rust in ways that have made me switch over as my default choice.

Things like default argument values, lazy static initializers, computed properties, optional chaining. I’ve personally also come around to ref counting by default being a sensible choice for most programs.

Though the thing that won me over was the recent C++ interoperability. Rust doesn’t have a good story there yet that’s as comparable. Hours/days/months writing Rust bindings for a C++ library are often minutes in Swift.

Each language has its own place and own benefits, but to say there’s “no reason to use a language” feels short sighted and defensively dismissive

xvilka 9 days ago
I would agree with you but in the case of Swift is largely confined to the Apple ecosystem with other platforms as an afterthought, while both C++ and Rust try to cover as many targets as possible.
dagmx 9 days ago
But that is exactly what is changing right now.

Foundation is being rewritten in Swift, Swift has moved out from under apples GitHub and is pushing more cross platform tooling for windows and Linux.

It’s not as flexible in terms of targets yet as Rust, but it’s also not just locked to Apple platforms.

And for a big chunk of developers, that trade off is fine.

bobajeff 9 days ago
It remains to be seen weather Swift will break out of being just a language for programming Apple applications.

There is still no way to make gui applications outside of Apple devices. Unless you want to make your own library or generate/maintain Swift bindings for an existing UI library.

Maybe, it will be okay for console only programs or servers but why use that over Java/JVM, nodejs or go?

dagmx 8 days ago
UI libraries are a poor reason to pick Rust over Swift, given that Rust has a very poor UI story.

Doesn’t your comment apply very equally to Rust? There’s basically Slint and Tauri, and several bindings in various states of disarray. Not exactly very compelling.

The Rust ecosystem has very many strengths, but UI is not one of them.

Regardless, you’re incorrect about there being no way to make GUI applications

Here’s a Gnome binding https://swift.org/blog/adwaita-swift/

The C++ interop allows easy binding to Qt https://github.com/qt/qtdeclarative/tree/dev/tests/manual/he...

Win32 https://github.com/compnerd/swift-win32

The fact that Swift has easier C++ interop than Rust makes the cross platform UI story much easier and more compelling than what I’ve found in Rust.

Bindings are much simpler to manage and can be handled by a single module map file with a single line in it most of the time.

Adding to that, many well established UI libraries depend on classes to implement them. Rusts lack of classes, while wonderful otherwise, makes binding to heavy class based libraries very onerous.

Don’t get me wrong, I really enjoy rust. It’s just, it’s very ill suited for UI work today itself. I almost always write my UI side in C++ if I have to and bind over when needed instead.

bobajeff 8 days ago
My comment wasn't about comparing it to Rust at all. Adwaita for Swift sounds good an all but it still looks immature. Also, the win32 bindings look even more immature. I agree UI is not there yet for Rust and from what I see it's even worse for Swift (unless we're taking about Apple devices).

I'm still not sold on the idea of managing bindings to C++ UI libraries. I'd rather have either the Swift organization or the UI library authors themselves write, maintain and document the bindings. Otherwise, it just seems like fighting against the ecosystem.

graboid 8 days ago
I am quite curious about Swift as a "more ergonomic Rust". How would you say it fares for typical backend stuff?
dagmx 8 days ago
Currently the state of server side dev is a bit here and there.

Vapor is the preferred framework and in general will seem familiar to anyone using any of the Rust server frameworks like actix web etc…

A tutorial for reference https://swift.org/getting-started/vapor-web-server/

From an ergonomics perspective, I write less code with Vapor than the equivalent Rust frameworks. It is slower today though but plenty for my needs, with some speed ups coming with Vapor refactors down the pipe.

I find that I need to spend less time managing shared resources with concurrency , and my code is clearer while being less verbose in general. Features like the trailing closure syntax are much easier to read for me.

I find it closer to how I’d write my Flask servers in the amount of code I need to do myself.

graboid 8 days ago
Thanks for sharing.
JoeMattiello 8 days ago
It really isn’t though. All my iOS swift code that doesn’t touch UIKit has been running unit tests with Linux Debian on GitHub actions for a few years now with almost no extra effort.

Any api or data model code, pretty much 80% of my app code works crosss platform

lenkite 8 days ago
Wish Swift provided a way to use custom allocators. Then it would be really terrific. A fair number of middle-ware projects work well with strategies like arena allocation which significantly improve performance and also structural ergonomics. ARC adds a fair bit of performance burden - you can see dozens of examples of people refactoring continuously to reduce ARC time in the swift forums.
wredue 8 days ago
Is Linux still a fifth class citizen for swift?

The last time I used it (and I admit this was a couple years ago), silly expectations like “my program will behave the same on Linux as it does on Mac” were not being met.

opless 8 days ago
Indeed there's no compelling reason to use C++ or Rust. It comes down to user preferences.

Quite frankly if you can't track the lifetime of your own allocated memory, are you even a competent software developer?

isodev 9 days ago
Also self-inflicting Apple’s “what happens not a Mac” developer experience may not be what one wants to go through during the lifetime of an app.
mannuch 9 days ago
Well I for one appreciate Swift’s focus on ergonomics and progressive disclosure. I think Rust is great, but I don’t see it as a great application-level programming language.

I think it’s wonderful that Swift is trying to be more cross-platform. No need to shoot down the efforts of people trying to bring a language they like to more places.

8 days ago
bsaul 8 days ago
Side question: what’s the status of android compilation target with swift 6 ?
9 days ago