Readit News logoReadit News
danpalmer · 2 years ago
This is a nice critique of the Swift toolchain UX on Linux, but perhaps not of the server-side Swift developer experience in general. Each of these problems looks like the sort of thing that you solve quickly once and move on from.

I have recently been developing a server-side Swift application, a few months of sporadic evenings and weekends. My starting point was having a year or so of professional iOS experience and a ton of web/server/infra experience.

My experience with it has certainly been mixed, but in many ways a breath of fresh air compared to some web development ecosystems. At work I'm mostly using Java on the backend and I think Swift could be a really nice replacement for that for larger systems – the type system is better, the ergonomics are better, the developer tooling is much better at the lower end (although there's plenty of specialist JVM tooling that is better).

Ecosystem-wise, Swift has few but high quality libraries available in general. Apple's first party libraries are exceptional. Vapor is in a weird place though. Some parts are really mature and well considered for their relatively young age (e.g. parts of the ORM, async stack), others feel very early days for things that have been around for a number of years now (e.g. queues). Others feel like an impedance mismatch in the framework design – I find the Content system both too limiting and not providing enough.

Overall, I'm loving it for a personal project. Would I use it as the foundation of a new startup? Probably not. Would I use it in a iOS heavy company? Yeah probably. I think you can do productive, high-quality backend engineering in Swift, today.

cvwright · 2 years ago
Agreed on all points. I’ve been using Vapor for a small work project for a couple of years and overall it’s been a good experience.

I think a lot of the author’s problems started when he bailed on Vapor and went down into the depths of SwiftNIO. I’m not really sure this was necessary. I could be wrong, but it feels to me like Vapor should let you do pretty much everything that you would need for an ActivityPub server.

Writing request handlers in Vapor with async/await is delightful - it’s really not any harder than writing Flask code. But going down below that level is pain. Lots and lots of pain.

danpalmer · 2 years ago
I've actually tried to write an ActivityPub server in Vapor! I must admit I didn't get very far on the outbound part using Vapor, as the inbound part took up most of my time. My impression was that ActivityPub is way too poorly specified for a good ecosystem to develop, which is probably why we see a monoculture of Mastodon for post-based ActivityPub, and similar semi-independent monocultures for things like Reddit replacements (Lemmy?).

You're right about the NIO part. I've had to dig into it a few times, but rarely found it productive in solving problems. Vapor is pretty flexible if you drop past it's first layer of abstractions, and as long as you pick one of futures/async and stick to it, it's fairly straightforward.

joe_fishfish · 2 years ago
Have you looked at Kotlin? Very, very similar to Swift and interoperates very well with Java.
danpalmer · 2 years ago
Briefly. There are Kotlin areas in the codebases I work on, particularly in Android code. It's not something I've needed to use yet, but I've heard good things and I'm interested to get into it once we start using it more.
kagakuninja · 2 years ago
If you work in Java and like the syntax of Swift, then you should consider using Scala. Of course convincing coworkers and managers to use it can be a problem.
danpalmer · 2 years ago
Scala isn't a language I can use here, we have too much Java tooling and are conservative on new languages. I see your point about Scala, there are niceties to it in my (brief) experience, however it's not so much the syntax as it is the way that software tends to be written in Swift given the language features – I didn't find the same in Scala, it tended to be more complex than I wanted.
Taikonerd · 2 years ago
How's the Scala community doing? I had the impression a couple years ago that they were losing momentum. But I also heard that Scala 3 fixed a lot of footguns that Scala developers hated, so maybe that gave them a second wind...
usefulcat · 2 years ago
> Each of these problems looks like the sort of thing that you solve quickly once and move on from.

Erm, including the apparent signal race and the illegal instruction?

lmm · 2 years ago
> Erm, including the apparent signal race and the illegal instruction?

Yes. They're probably both caused by this person setting their CPU microarchitecture wrong.

wiseowise · 2 years ago
> the developer tooling is much better at the lower end

Haha, what?

danpalmer · 2 years ago
I find the performance tooling and package management situation in Swift via Xcode and Instruments is, in my experience, much better than a typical out-of-the-box Java setup with a popular IDE. IDE features may be better in something like Intellij (I'm not a fan personally), but the language tooling isn't better in my experience. The swift+llvm+lldb setup is nice, Swift Package Manager is really nice, much nicer than Maven/Gradle in my experience. So yeah, better at the low end.

Linux/Windows tooling is lacking, I'll give you that, but given where Swift started from I feel like they're already outside the norm for Swift development and debatably "low end" on complexity (although not deployment, I haven't had a problem with Linux deployment).

By "high end" I mean anything that is trying to do complex runtime analysis, and the sort of tuning that you can do on the JVM that is way outside my comfort zone.

ta34346 · 2 years ago
I had a similar chuckle/double-take; admittedly it's been a few years since I looked at XCode, but it didn't strike me as much more than a Notepad wrapper around a toolchain.
pphysch · 2 years ago
> Overall, I'm loving it for a personal project. Would I use it as the foundation of a new startup? Probably not.

I know of a medium-size startup that is (attempting) building an industrial/IoT software stack on just Swift. Last I heard things weren't going great...

sulam · 2 years ago
What language you write in doesn’t seem like a great place to use your few innovation tokens for that kind of startup.
nicoburns · 2 years ago
Adding to the recommendations for other languages you're already getting on this thread: have you tried Rust? It's type system and syntax are very similar to Swifts. You do have to deal with the borrow checker, but that typically isn't too challenging for backend web development work where logic tends to be pretty linear anyway, and in return you get a much more developed ecosystem.
jwells89 · 2 years ago
Maybe I just haven't looked at the right codebases, but most of the Rust I've seen reminds me more of C++, being more dense, technical, and "noisy". The language most similar in syntax to Swift I've seen is Kotlin, but it's still more quirky and rigid than Swift is.
hedgehog · 2 years ago
That roughly matches my experience trying to use Swift outside Mac and iOS development. I really like the language but the tooling and library ecosystem just aren't there. Go or Rust are not as nice to write in different ways but much more easy to get work done with. On the Rust side the language is more fiddly than Rust but with the help of Copilot the gap is not that big.
fefe23 · 2 years ago
I found this write-up hilarious.

I have been toying with the idea of experimenting with Swift under Linux myself for a while now. I guess this puts that idea to rest.

I'm not even talking about the illegal instruction thing or the capricious looking syntax changes. Just the fact that his hello world app caused 350MB of build artifacts in the filesystem, and the five minute build time for the project, are enough to turn me off of Swift.

I come from the good old Turbo Pascal under MS-DOS days. Building even complex applications took mere seconds on an 16 Mhz 80286 with 1 MB (yes, one megabyte) of RAM. I see no excuse for binaries to be big. This is turning me off of Go and Rust, too.

Gotta admire the cojones on those people to call their product "Swift".

I come from a time where the whole application fit into 512 KB RAM. It had to. And it was good that way, because the human brain can't grog that much context at the same time. Nowadays people are pulling in javascript frameworks larger than the whole payroll system of those old days without even a second thought.

IshKebab · 2 years ago
Rust binaries can be just as small as C ones:

https://darkcoding.net/software/a-very-small-rust-binary-ind...

Computers do much more than they could in the 80s.

elcritch · 2 years ago
Yah, but that's definitely not the default in Rust land.
codr7 · 2 years ago
That's most likely 5 min for the initial build of the dependencies though, a one time thing.

I find the build times on Linux quite reasonable.

IshKebab · 2 years ago
Does that include the Swift compiler or standard library or something? I can't think of a single other language that has a 5 minute compile time for hello world...
estebank · 2 years ago
> Swift was sold to me as a safe language. But I think it would be more accurate to describe it as a thin veneer of safety over a deep pit of peril. The linux version of swift replicates a large number of native mac frameworks using whatever mix of C and C++ gets the job done.

I still don't understand why this argument is used as much as it is. Every language ends up having to deal with either hardware or system libraries, which means that any language that provides further assurances beyond what the platform does has to have glue code to maintain its invariants. Whenever these languages have to dereference pointers they use runtime checks which would otherwise not hold its invariants. Interfacing with existing libraries is the same. Using a C library from Swift doesn't make it an "unsafe language", it makes it a flexible one that can leverage the existing ecosystem without reinventing every wheel.

jchw · 2 years ago
Since Go came up earlier, likely it is being contrasted with Go in this case, where Go has a fast and robust crypto library in the standard library.

And yeah, safety is clearly a continuum: hardware is not perfect, operating systems are not perfect, etc. However, being defeatist about this point is not really the way to go. We should aim to replace less safe things, especially in safety-critical parts of applications like the cryptographic operations and TLS implementations, with safer things. That's definitely why in the Rust ecosystem there's been a huge emphasis on pushing rustls forward; it's a shame to put all of the work into making safe and robust software, only to have a giant OpenSSL or BoringSSL-shaped liability sitting in the same address space as your program. Battle testing alone has proven insufficient over and over and over and over, whereas statically verifying the absence of (at least some kinds of) flaws remains very promising still.

In practice I'm sure it's obvious that to make any application secure and/or robust it's going to take multiple layers of defense where ideally there is no single point of failure. But to make progress, you have to... you know, make progress. Programming languages, toolchains, and standard libraries can't stop your operating system from being insecure, but they do have the ability to not put less safe/verified things into your address space.

Maybe some day, all of these safe Go/Rust/Swift programs will have much more robust hardware and operating systems to run in that are, themselves, "verified" to have certain security assurances. For that to really be all that meaningful, though, the programs themselves have to actually be "safe".

And hopefully, even when standard library code can't be proven to be "safe" using the language's normal mechanisms, we can still prove it using heavier duty tools. But, it certainly isn't happening over night...

trealira · 2 years ago
> Maybe some day, all of these safe Go/Rust/Swift programs will have much more robust hardware and operating systems to run in that are, themselves, "verified" to have certain security assurances. For that to really be all that meaningful, though, the programs themselves have to actually be "safe".

On some older operating systems, the system was safer in some ways.

On the Genera operating system for Lisp machines, almost all code ran in a single address space, which was possible because Lisp is garbage collected and doesn't allow arbitrary reads and writes through arbitrary pointers. You could still write code in unsafe languages like C, but those programs did need their own address space, like in traditional OSes.

On the Burroughs MCP operating system from 1961, it had a similar mechanism. It was written in the language NEWP, which had certain unsafe constructs marked, and if code used unsafe constructs, it had to be approved by the system administrator to be executed.

https://en.wikipedia.org/wiki/Single_address_space_operating...

https://en.wikipedia.org/wiki/NEWP

Someone · 2 years ago
That’s true, but Swift moves out of Swift code way before it has to interact with system libraries.

If you use Java, your xml parser, json parser, character encoder, date/time formatter, jdbc library, etc. likely are mostly written in a JVM language.

If you use Swift, they were (at least in the first versions) almost entirely written in (Objective-)C, so the amount of unsafe code is larger. Wrapping that in a safe language doesn’t remove all security concerns of that code.

nvm0n2 · 2 years ago
And don't forget that Java has its own SSL stack, also written in Java. So you can go a long way with no native code at all.
Mathnerd314 · 2 years ago
Recently I was looking at how to do streaming I/O in Swift, reading a file line by line (but not the whole file at once). In C on Linux, this is one function, fgets, which does the buffering itself and uses SIMD-accelerated memchr to look for the newline. You call it with a file handle and it's done.

In Swift the best advice I found was https://forums.swift.org/t/read-text-file-line-by-line/28852...: use the C functions. I experimented with using FileHandle in Swift and manually scanning the return Data value for newlines, and found it added a 6x slowdown. The loop for scanning the newline does not optimize even the array access, it was calling a lookup function for every byte and there was of course no SIMD acceleration. Converting the Data value to a native Swift array did at least eliminate most of the lookup overhead, but from the profile it seems like it still does bounds checking on every access, so it doesn't optimize to SIMD or anything like that.

So that's the issue - the Foundation library isn't a portable wrapper over the native system calls, it is a thick wad of gunk that adds significant overhead to even simple programs. There was an effort to make a better API, https://github.com/apple/swift-system/, but it seems to have stalled (or perhaps an improved cross-platform API was never its goal).

ptrpavlik · 2 years ago
Swift is currently safe in terms of type safety and dealing with pointer, I think that they've done an overall great job there. There's just few architectural decisions where doing things like accessing an array out of it's bounds crashes the app by design. In the server world, one might prefer throwing an exception you can capture instead of bringing the whole process down.

What Swift currently isn't is thread safe. They're working on it for Swift 6, but it's still probably years away, and will be a massive breaking change. Vapor has done a great job putting a thread-safe layer on top of this mess, but once you go down to say that mentioned SwiftNio level, you really need careful with concurrent memory access.

viraptor · 2 years ago
> Every language ends up having to deal with either hardware or system libraries

There's a big difference between using a C library which does extra processing + maybe uses some syscalls and doing the syscalls directly. The interface is much stricter for the system interface and the memory ownership is better defined. You don't have to think about the library using a different allocator than the app does.

So no, I wouldn't say every language needs to do that. Golang definitely didn't https://github.com/golang/go/issues/36435

bhawks · 2 years ago
The OpenBSD way of one blessed libc as the interface to the operating system is perfectly fine for their project.

The Linux kernel is a separate project from the several different libc implementations and the Linux kernel project treats the syscall API as a first class contract. If a language wants to use it directly for some reason that is an option on the table.

woodruffw · 2 years ago
I don’t know much about Swift, but the “normal” way to handle those invariants in safe programming languages is safe constructions: unsafe operations are wrapped in safe abstractions that cannot violate the language’s semantics, no matter how they’re misused. It’s of course possible to build those abstractions incorrectly, but there’s a large language design space between “you can build safe abstractions” and “all correctly implemented abstractions are safe by construction.”

If Swift falls into the first category (maybe it doesn’t!), then this seems like a fair criticism to me.

estebank · 2 years ago
The critique was that it relies on C code for cryptography at all, no further investigation on whether the usage of those APIs is limited to providing safe abstractions. That's what I take issue with.
favorited · 2 years ago
> The linux version of swift replicates a large number of native mac frameworks using whatever mix of C and C++ gets the job done.

Note that this is changing, on Darwin and Linux alike. Foundation.framework is transitioning from being a Swift interface over a C / Objective-C implementation to an Objective-C interface over a Swift implementation (https://github.com/apple/swift-foundation).

The language still has native C interop, and is gaining the same for C++, so it can delegate stuff like crypto to existing solutions like BoringSSL, but Swift-native solutions are becoming more common.

BrianHenryIE · 2 years ago
> like BoringSSL, but Swift-native solutions are becoming more common.

I've seen this one, "Move away from BoringSSL", actively in development (PR opened two weeks ago):

https://github.com/vapor/jwt-kit/pull/99

favorited · 2 years ago
Nice! It looks like they were vendoring their own copy of it, and don't have to anymore. Now they're using `swift-certificates` and `swift-asn1`, which both got open-sourced in May.

That's why I try to push back when people say Apple "doesn't care" about server-side Swift – they're regularly releasing these packages that they wouldn't bother open-sourcing and maintaining if they "didn't care." Things like NIO-based implementations of IMAP and SSH, an OpenAPI generator & runtime, HTTP type abstractions, a Cassandra client, etc. Most of those are from the last year, in addition to those certificate packages. They're paying teams of full-time employee salaries to work on this stuff, including open-sourcing it.

frou_dh · 2 years ago
Correct me if I'm wrong, but adoption of "server-side" (aka non-App) Swift by people who weren't already Mac/iOS app developers seems to have been microscopic. Surely the language must be considered a colossal failure in that regard, because the goals espoused in the early years went far beyond just being an Apple person language.

(Or to summarise the situation in another way, it got mercilessly shunned in terms of wider community enthusiasm versus Rust)

oflannabhra · 2 years ago
Yes, Swift is definitely losing the mindshare race for server side compiled languages, but to be fair it started way behind. However, just because it is not winning mindshare doesn't mean it isn't useable or that it is a failure.

The real story of server side Swift is a small but dedicated working group [0] continuing to make real measurable progress. Most of the frameworks have fallen out of favor or have been abandoned, except for Vapor, but the workgroup is active with representatives from several major tech companies. Obviously the workgroup's scope is much broader than just a single framework, and their current initiatives identify and address most of the shortcomings noted in the article. [1]

[0] - https://www.swift.org/sswg/

[1] - https://www.swift.org/blog/sswg-update-2023/

ezekiel68 · 2 years ago
> However, just because it is not winning mindshare doesn't mean it isn't useable or that it is a failure.

A supposedly wise man once said "...you can not fool all of the people all of the time." [0] Plenty of things that are usable are also failures (e.g. Microsoft Zune was, by all accounts, a competent media device). Any technology that is not winning [sufficient] mindshare over time will be considered a failure soon enough.

[0] What, you don't know who said this? Copy pasta plus a three-second search on any search site or AI chat will set you straight.

pjmlp · 2 years ago
It can't be a failure when it never was a use case that Apple actually cared about.

The Swift FOSS folks are the ones that have tried to look into it, as there is hardly any other use case outside Apple's ecosystem.

jwells89 · 2 years ago
The team developing Arc browser seems to be making a lot of headway on making Swift work for native Windows development, which is promising. Not server side, but not Apple stuff either. If they succeed and open source their work I can see using it myself for Windows desktop development.
seec · 2 years ago
Considering Apple's approach to most things it seems about right. Even if the language was extremely good and better at many non-Apple stuff, you would still be right to question its viability. Apple doing what is best for Apple regardless of what people need or what you could expect from a reasonable partner is the only reason you need to not bother with swift anywhere else than on Apple hardware. This is a company that switched off the ability to execute 32bits software on hardware that was natively capable just with an arbitrary OS update. I used to be very naive, but I would not rely on anything Apple that is not clearly linked to their hardware (so that their interest at least somewhat aligne with yours). Nowadays I would go as far as saying that if you do not directly make money from using Apple hardware, you should not bother at all.

I believe most end up learning this either the hard way or by simple observation ; and one cannot come to any other conclusion than avoid Apple stuff outside of Apple hardware...

davedx · 2 years ago
It’s a real shame the auto differentiation project wasn’t pushed harder.
nickpeterson · 2 years ago
I seem to remember something about the original designer leaving Apple and a bit of bad blood but I might be misremembering.
b3morales · 2 years ago
You are probably thinking of this by Chris Lattner: https://forums.swift.org/t/core-team-to-form-language-workgr... (on HN here: https://news.ycombinator.com/item?id=30416070) Swift has always been developed by a team of course, but he was the lead and probably the most public face.
fleeno · 2 years ago
I have like messing with server-side Swift, and I asked it at the WWDC Swift table. I was pretty much met with blank stares. Either they just have no interest in it, or I ran into the wrong engineers.
vkoskiv · 2 years ago
I tried out Swift + Vapor back in 2017 when I was still a Mac user and a Swift enthusiast. I remember that at the time, I had quite a positive experience with Vapor 2 on Swift 3. I built a backend websocket server[1] for a hobby project[2], and managed to get it mostly working even though I was quite inexperienced in general.

The pain came later. They eventually deprecated Vapor 2, and I found that the new version of Vapor required essentially a complete rewrite, using some kind of async paradigm I couldn't quite grok. I kept using the program I wrote for longer than I anticipated, and more pain came when I could no longer figure out how to set up the toolchain needed to even build the thing. Eventually the only way to build and run it was to use an old Ubuntu 16.04 installation.

This experience left me with a distaste for modern tooling with lots of churn, so last year I decided to rewrite the thing in C with minimal dependencies, so it's guaranteed to compile with minimal modifications even in 30 years time. Really happy with the result[3]. I added new features, optimized the websocket messaging with binary messages and zlib compression, and generally made it way faster than needed.

It compiles in less than a second vs. the minutes it took to build the Vapor version, and the resulting binary is 324K with debug symbols, 144K when stripped + -Os, and 68K when UPX-compressed. It also uses a local SQLite db instead of a separate MySQL server, which makes deployment quite trivial (git clone && make run). The web client is still built with React, I've been thinking of rebuilding it with a single .html file and minimal JavaScript.

[1] https://github.com/vkoskiv/NoMansCanvas

[2] https://pixel.vkoskiv.com

[3] https://github.com/vkoskiv/nmc2

cco · 2 years ago
So funny that this came up today! I just had a developer reach out to me about whether we had a backend Swift SDK at my current company (stytch.com), or if we'd seen anybody else use us with Vapor.

Googled around to get some more context on Vapor's history and sure enough, found this thread from today.

Sounds like I should point him away from Vapor in your opinion?

favorited · 2 years ago
I'm not the person you asked, but Vapor hasn't had a major version change since 2020 (Vapor 4). Vapor 5 is at least another year out, probably more like 2 or 3.

Vapor 5 is definitely going to be a breaking change, but that's not a bad thing. The current major version predates async/await, actors, Sendable, macros, move-only types, variadic generics, and lots of other language features. It's been able to adopt some in incremental releases, but it wasn't designed with those things in mind.

vkoskiv · 2 years ago
I don't have a valid opinion on the current state of Vapor - 2017 was a long time ago, and the people developing it have worked very hard to improve it in that time.
wredue · 2 years ago
I’m honestly surprised you got this far with swift 3 on Linux, as swift 2, 3, and 4 on Linux were all bug ridden messes. You couldn’t reasonably compile between minor versions, let alone major ones, and expect your same lines of code to have consistent behavior.
AJRF · 2 years ago
Using swift feels like you are living in a house that once had a interior designer build it from the ground up, but then his meth head friends come over for a party one weekend and never left.

The direction of the language is of breaking changes that really should be breaking, secret development of features that then get thrown onto the community during a keynote and just an unfathomable amount of complexity and cruft building up in every corner. Seriously, I would hate to learn Swift now, I barely tolerate it having grown up with it.

Swift 3 was almost perfect. I loved it. If they had of added async/await to Swift 3 I would use it for everything.

miffy900 · 2 years ago
They tried to reinvent C++, when really they should've reinvented C and sprinkled Obj-C classes and protocols on top.
pjmlp · 2 years ago
Christian Laettner is quite clear that Swift was a reinventation of Objective-C, and most Objective-C 2.0 improvements and latter ones, were already with Swift interoperability in mind.

As for C remark, our computers have long stopped being a PDP-11 clone.

jbverschoor · 2 years ago
"A hard to kill web server sounds like a feature", nope, sounds like a misbehaving application. Even a server which has some checks in place to clean up after a while shouldn't be taking that long.

Trap signal -> stop handling new requests -> wait for the requests to finish -> (force children to quit if needed at timeout -> exit

andoma · 2 years ago
For SIGTERM I agree that it should perform a clean shutdown. Though for all software I write, I make sure that SIGINT is either not trapped at all (so the process just exits via the default signal handler) or pretty much _exit() from inside the signal handler. I can't stand programs that linger when I ^C them.
geodel · 2 years ago
I thought it was slightly tongue-in-cheek comment on Swift webserver's unreliability.