I think the goal of the thread is to collect pain points w/ server side Swift, not to argue what deficits other languages have or how Swift compares to those. Probably not productive to go down this route. I think most people over here know why they use Swift.
Compilation time is a major pain point of Swift, that is just a fact. Also a very long standing one, so hopes that it will become better are not reflected by reality (features like macros actually make it significantly slower).
decades of evolution led Linux systems towards dynamic linking for a reason: dynamic linking uses less memory.
the Swift runtime is about 10x larger than the C runtime, and even bigger if youâre linking FoundationEssentials or the entire Foundation. if youâre copying that into every executable, thatâs a lot of memory youâre wasting, memory that is not available for apps to do useful things.
one way to solve this issue is to deploy âmonolithâ binaries that combine lots of apps into one executable. but that raises build-time costs as many have mentioned in this thread.
now, dynamic linking with Swift is a huge pain right now especially since it is ABI unstable. so in a lot of ways, monoliths are the path of least resistance for a lot of people right now. but it would make some things easier if we could deploy server apps individually instead of recompiling everything running on one type of host configuration as a unit. static linking is not a silver bullet cure-all solution.
We do actually use dynamic libraries on linux, but we can guarantee an exact same build and deployment environment and have to use a (minimally) patched swiftpm currently - far from ideal and not practical for most.
Some relevant open issues/pull requests for more generic linux support:
We use Swift on server to power a healthcare platform down in New Zealand. We chose it because we're mobile-first and unifying Swift on server and iOS seemed like a great choice 8 years agoâŚ
Swift on server has come a long way but we still have major pain points:
The differences between macOS / Darwin / Xcode Foundation and Linux Foundation crop up bugs regularly that can be hard to track down and fix. It would be great if we had Linux Foundation linkable in Xcode (maybe this is possible now with the new FoundationEssentials?)
Lack of binary frameworks for Linux means no 3rd party libraries are vending xcframeworks which slows down development.
Development outside of Xcode is still lacking, VSCode with swift-lsp is improving but still not super ideal.
It may not help you in the short term depending on your required toolchain support version, but I can say that we went from a no-Foundation policy (for the reasons youâve encountered) to start using it freely as of Swift 6 - the new Foundation implementation which is shared across Darwin and Linux has been largely painless - but for the record we only use essentials.
can you provide a few examples of third party libraries you wish existed for Swift?
regarding tutorials: iâll also plug swiftonserver.com which was started this year and contains a wealth of examples for how to get started with Swift on the server.
Iâm always interested in the âlack of 3rd party librariesâ point because I feel most of the stuff I use from the js world is built into swift or hummingbird or vapor.
For me personally the only pain point would be fewer hosting platforms to choose from compared to node/express.
Another issue I can see is lack of corporate buy in and hurdles with using public GitHub from an enterprise environment. There just isnât as much support in some workplaces to make swift as usable as a server language as Java, python, js, C# etc. I view this as a temporary problem that can be fixed with time and by improving the public perception of swift on the server.
I think this is a valid pain point. In the mainstream server side langs you get modules for arbitrary obscure features. Just because the communities are so large and cover every weird desire.
E.g. you don't usually get XML-RPC out of the box. Is that obscure? Yes! But it is also widely supported everywhere else and still used in obscure setups
This is getting way off-topic, but sure. Primarily in older systems of course (e.g. my home automation system is accessible via XML-RPC, OGo also has an XML-RPC API, etc). It is still quite a good choice if you quickly need to do IPC between different languages, because it is supported everywhere, well, except Swift , though I did write a small lib for my purposes, but I had to do that on my own.
Getting back on topic (sorry!) â one pain point is, of course, binary size with the Swift runtime linked in. This has improved markedly with FoundationEssentials but there are still lots of packages that use Foundation. And auditing this can be difficult as itâs linked implicitly (well, itâs not that difficult, but you need to look at the symbols).
ArgumentParser seems particularly bad for such a limited functionality, but it isn't really related to server side Swift either. For a CLI size matters, but for a server it doesn't really. Who cares whether the server binary is 10 or 100MB, both are irrelevant for a start-once thing.
Hence the (IMO mislead) tendency to link statically.
Yes, I was using âserverâ as a proxy for embedded (but not Embedded). Many similar issues except size is also important. Although, ironically, on our device (which has multiple services that share the same package dependencies), being able to override to force them to build as shared libraries (type: .dynamic) would also be super-useful.
iâm not sure where âbinary size doesnât matter on the serverâ came from, but i couldnât disagree more.
on the server, binary size equals memory. if everything is statically linked, you use the entire size of the executable, eagerly at launch time.
letâs say you have a host with 500 MB of memory (a t4g.nano). youâve got to leave at least 1/3 of that for the OS, and for headroom, which gives you ~300 MB for applications. if youâve got a 100 MB executable, that leaves you with just 200 MB of memory to do useful things.
The focus here was more that argument parser in particular is excessive for its target audience, CLI. You end up w/ CLI's megabytes big that do little, it's pretty bad (megabytes vs kilobytes).
An instance w/ only 500MB RAM seems special purpose to me (i.e. it is an embedded usecase). The (smallest) $5 Scaleway instance I run for like 10+ years has 2GB of RAM. And 200MB of RAM still sound like plenty for a typical Swift server and a nano setup.
I do agree w/ the static linking issue, that just shouldn't be the default (it is great that this works now, but it seems extremely special purpose and generally undesirable).
well i guess thereâs no clear line between embedded and non-embedded, but t4g.nanos are embedded than i guess i am an âembeddedâ developer
folks are often amazed at what you can do with Swift on tiny machines. did you know the entire public-facing Swiftinit website runs on a t4g.micro with 1GB of memory? it co-habits with a MongoDB instance which gets 500MB of RAM, so the Swift app itself is only allocated 250MB of RAM to serve all of the siteâs visitors.
of course the infrastructure is not just one t4g.micro, there is a second instance which replicates the data from the public-facing node (so we do not lose all the package documentation if one machine fails), and there are builder nodes that actually run the Swift compiler and build packages and upload the documentation to the micros. but those arenât public-facing, and if they went away, the site would still be functional (for a while), the documentation would just get stale over time.
i think itâs really cool how Swift is so memory-efficient that binary size becomes the new limiting factor. but static linking undercuts this huge selling point for the sake of ease of deployment, so i totally agree that this is not a globally-optimal direction for server-side Swift to be headed in.
No, I'm not surprised at all. The binary size for servers is minor since we are not talking about gigabytes but megabytes, and so is the common memory consumption of Swift servers.
This is totally off-topic again, but I'd be interested why you use AWS for that. What does that t4g.micro cost you per month?
I don't really see how static linking per se undercuts the selling point. Static linking is way more efficient if you only run that one binary per, say, docker container / lambda, and I think that's what Apple's focus likely is (hence the investment in that).