I love Swift but had to stop every time before getting serious for several reasons. As a language it’s just amazing.
But whenever it’s come to performance on the backend, it would be not enough by a large margin. Take JSON serialization for instance, even using a yyjson wrapper it’s been nowhere near the original C performance, slower than Jackson, nlohmann::json, Go’s stdlib, and serde of course. I tried several Swift libraries. Model definition for custom deserializers alone for the few common ISO timestamp representations is a bit cumbersome but bearable. With some other formats and protocols I use, Swift is similarly underwhelming. Logging takes a large toll in performance as well, regardless of what a library appears to suggest when speaking of “efficiency.” I just can’t seem to squeeze out enough performance out of Swift. Async Postgres IO was quite good until I ramped up the load. TechEmpower benchmarks place Vapor relatively low. I get much better performance from low-effort Spring on Kotlin, needless to mention more performant backend frameworks.
Then the IDE story is very bleak. While I’m on Macs, Xcode just doesn’t cut it for me to be productive. Jetbrains discontinued their dedicated IDE and their Vscode pendent is still experimental. Vscode proper support for Swift is not really worth mentioning in my opinion. So I’m basically left with Xcode as an IDE for Swift.
I so dearly wanted to introduce Swift on the backend at my company but that’s just unrealistic right now.
The server-side Swift ecosystem has matured over the past few years, with specific attention from teams at Apple.
For example, regarding JSON, there has been a rewrite of the JSON encoder/decoder that results in a 200% - 500% speed up in deserialization! You can read about the (still ongoing) improvements to Foundation at https://github.com/apple/swift-foundation
Regarding logging, Apple has been pushing the development of community around the swift-log package at https://github.com/apple/swift-log. Maybe you’ve seen this, but just wanted to share!
One last thing: the Swift VSCode extension is actually really good! Not sure when you used it last, but I’ve been using it on a regular basis and it’s been great — and is only getting better. Here’s the link to the extension if you’re curious: https://marketplace.visualstudio.com/items?itemName=sswg.swi...
It’s true that Swift has had its various issues, but there’s a very real push by the core team and community to bring the language to new heights and places. Cross-platform support is getting better and better (check out what The Browser Company is doing with Swift on Windows) and a big source of performance bottlenecks are being addressed with the development of non-copyable and non-escaping types (Rust-like move-only types)!
Sorry that’s a lot, but I just wanted to point out that there’s a lot of hope in Swift and really interesting things are happening for the project!
My recollection is as recent as a few months ago. Well I guess I’ll have to take another go at it this month, hopefully. I used three or four different JSON libraries aside from Foundation, including as I mentioned the quite popular yyjson wrapper which I expected to be on par with the pure C implementation. I’m out of the loop with the Swift ecosystem at the moment, can’t recall all the names.
I experimented with several logger implementations, likely to have used the one you’re suggesting. Thanks for pointing it out.
With the Vscode extension and the language server I suppose I had very palatable experience. It just didn’t work most of the time until I’d recompile the projects. Setting it up was a bit annoying as well, no build tool chain automations for project imports and setup, had to do the setup by hand. If I recall correctly, with one project an unpleasant issue I had was with the Swift Package Manager and CocoaPods, the Vscode extension wouldn’t recognize the project structure, and I ended up setting up a CMake project, good I have an affinity for CMake, and exporting it. But Xcode did just alright with it. So I just went back to Xcode for all my Swift projects. I think a plain SPM project actually got properly recognized in Vscode, but lots of dependencies are beyond SPM, which incidentally is also quite a significant annoyance in the Swift ecosystem.
I wish Swift enjoyed more attention, like .NET has been having. Oh and in terms of documentation I feel Swift is nowhere near .NET, even though the setting is comparable.
Referring to your closing remark, I don’t feel like that’s a lot, it’s a pleasure to learn more about Swift’s ecosystem, so thanks for taking your time to reply and providing extra context.
I feel like Swift enjoys much more actual good will and positive attention than C#. HN and other communities seem to be hell-bent on repeating the statements that weren't true even back in 2016 when it had its first FOSS version.
For example, this submission currently has 136 upvotes and 60 generally positive comments. The last .NET submission that reached frontpage had 158 upvotes and 255 comments, many of which would repeat personal experiences from 2007, complaining about products and languages that are not related to .NET but to something adjacent at best, or criticizing imagined spec and implementation issues that do not correspond to how the runtime and language actually work.
If anything, it seems like Swift can succeed if Apple puts more effort into it and community sentiment will be headwinds, not the other way around as is the case with .NET.
Microsoft's management keeps undercutting any good will that .NET manages to win, that is why.
Recent examples MSTest being proprietary for Native AOT testing, and no plans to help improve xUnit into that direction.
New VS Solution format, that might only be supported on the C# Dev Kit, also under VS license.
Killing VS4Mac, which although it has its own set of issues, VSCode still doesn't provide the same level of tooling for Mac and iDevices development as VS4Mac did, forcing anyone that cares to go out and buy Rider licenses instead.
The dotnet watch removal drama to only have hot-reload available on VS, thankfully back pedalled only thanks the engagement of high level .NET developers, with help of the community backslash on social media.
I was not looking for a response from your account, thanks.
(context: pjmlp likes to post about .NET, Java and other adjacent platforms with authoritative and confident tone not backed up by source material or simply reposting second hand or surface impressions of events, rather than just reading through publicly available information in full which could help some of the comments with being less detached from reality)
I was not looking for a response from your account, thanks.
(context: neonsunset professional life is highly dependent on where .NET goes, biased by involvement on .NET team's work, and how .NET is perceived by the world outside Redmond).
Codable fundamentally limits the maximum performance of any encoding or decoding, no matter how fast your parser is. If you need faster performance you need to use a completely different solution.
Same applies on the memory management front, while it is understandable the decision they have made, for compatibility with Objective-C frameworks and runtime, most tracing GCs with 20+ years deployment experience are still faster than Swift on server workloads.
And it is worth remembering that Objective-C only got ARC, because adding a tracing GC was a failure, given C semantics, and most applications being prone to crashes, when the GC got pointers wrong, thus automating retain/release pairs was a much safer approach.
considering that nlohmann::json not even a performance-oriented json library, generally benchmarking at 20% of the performance of RapidJSON (which itself is not even close to the fastest you can reach in C++) that's... scary
I noticed the same thing. Either Swift performances are atrocious, or I'm missing something.
Just the other day I was trying to sort a large array of strings in Swift and it was painfully slow. A 3 lines Python script managed to sort the same dataset _at least_ 10x faster.
I think it'd be curious to see the code, some example strings, and whether or not you compiled with optimizations enabled — if you're willing to share. There's no reason for this to have been the case.
If you're not aware, the author is Doug Gregor, one of the lead developers on the Swift team at Apple. Parts 1 to 5 in this series were all posted on the same day:
And former Boost and C++ standard committee contributor. In particular he was one of the main authors of the classic C++0x Concept proposal (as opposed to the concept-lite that eventually made it into the standard).
Many of the Swift features for generic programing and protocols are based on the way C++0x Concept proposal went down, as mentioned by Dave Abrahams in some of his interviews.
We're working on improving its support for other use cases, with work to better support embedded[1], server[2], and AI[3] use cases, along with Linux[4] and Windows[5] support.
We're also putting a lot of energy into improving support for these scenarios in Visual Studio Code [6].
Would love to hear more about scenarios folk are looking at, as well as specific gaps that are blocking you adopting Swift for non-Apple platforms. We're building a roadmap now and would love to make sure our work items are comprehensive.
Something I'd love to see is being able to use the VSCode extension for iOS / macOS development. I wouldn't expect all the bells and whistles of Xcode obviously (e.g. previews, run integration). However I'd love to use VSCode because I prefer their tradeoffs to Xcodes.
The advantage for Swift would be that potentially more developers use the VSCode extension which would hopefully improve the quality and incentivise more of them to maybe contribute to it.
If it's already possible then maybe a section in the readme on how to achieve this? (e.g. how to open an iOS project folder and get completions for Apple's frameworks).
What works quite well for iOS/macOS apps is breaking the project into a barebones Xcode project plus a Swift package that contains all of the code. SPM projects work well with VSCode and you get full auto-complete support with the official Swift plugin.
Thanks for the suggestion, I'll give that a try. Obviously this will not work with large existing codebases; but for new projects I'll try how well it works.
We already have a NeoVim plugin [0] that makes replacing Xcode somewhat possible. It's not perfect and requires that you have Xcode around for certain scenarios but I have been using it as my daily driver for the last month.
I think you would only need xcode-build-server [1] in order to get autocompletion in VSCode.
Overall it should provide a better experience than Objective-C even with GNUStep, never managed to offer without the NeXT or Apple's frameworks and IDE tooling.
So far, every time I play a bit with it, the experience doesn't seem much better, as naturally most packages assume Apple platforms, and VSCode isn't XCode.
Has the issue with manually reaching out for OS APIs instead of Foundation already been fully sorted out? Having samples directly referring to Glib and similar, instead of standard Swift, wasn't that interesting.
Also the lldb issue with Python bindings not being found seems to still exist, even on the container images.
However, I also acknowledge that many things seem to have improved, so there are also quite a few positives.
I think if you could honestly use Swift outside of Xcode it would already be a massive improvement. I know you "can", but you really can't. It's painful. The experience would have to be at least 1-to-1 in terms of developer experience. When I use cargo/rust-analyzer in vscode, I feel at home and empowered. When I try to write Swift in vscode, I feel handicapped
SwiftUI is an incredibly powerful paradigm. It feels like the future compared to most GUI programming today. It is also possibly the most easily seen and best-known value of Swift today. Enabling and empowering the community to create similar abstractions outside of Mac OS/iOS would go a long way to making the language more commonly used, but I understand that's a responsibility that doesn't fall squarely on the Swift team. Case in point, the adwaita-swift and the swift-everywhere-windows-interop projects. The first looks fine (although it is just a "Counter" sample project) but the latter looks DOA/unviable. As a dev, I wouldn't even consider the latter and adwaita has the disadvantage of not being cross platform
Look at the sheer number of tools, languages and frameworks trying to solve the modern day "write once, run anywhere" of declarative guis. Tauri/Dioxus, React Native, Flutter, iced-rs (my personal favorite)... the list goes on. There's a real need here that Swift could help solve without forcing people into JavaScript or Rust. The former being too browser-focused (for better or worse, but I argue worse) and the latter having too steep a learning curve
I feel like a lot of the Swift-outside-of-Apple effort has been on server/embedded work, but in those domains, why wouldn't I choose Python/Node+JS or C/C++/Rust which already have a strong foothold, respectively? That's a much harder battle to fight from an adoption perspective IMHO
I’d love if Swift supported easy cross compilation in the same way that Zig does. The fact that I can just download Zig and everything will just work without tinkering is nice
It actually has pretty decent support on Linux. It’s in Fedora’s official repos and Apple provides official builds for several other popular distros. The biggest issue seems to be that much of the larger ecosystem assumes Apple platforms.
I do all my swift CI/CD for non UI code in girthub actions on the Debian image for some time now due to lower cost and faster run times.
I even use Swift on a ARM raspberry Pi docker cluster.
Windows is officially supported for some time with networking and nearly all of foundation ported if that’s not complete yet.
The only real issue you have is at the UI level.
There are some web and even ncurses libraries using SwiftUI like DSLs
Now with the new macro features you can get a lot more flexibility for cross platform builds.
C++ interoperability is also possible with latest versions. It was a hidden flag for a couple years. I’ve wrapped many C++ emulators in Swift over the last year with Cmake to Xcode projects.
Yes, sometimes the languages are great and versatile, but when it comes to the job market, your options are much more limited.
Do you like Swift? Good, you better also like iOS development.
Dart? You better be happy with UI with Flutter.
Even with Rust to a degree... If I'm looking for jobs where I could exclusively work with Rust, it's crypto blockchain. Web listings might include Rust but usually come with Python, JavaScript or Go.
Even if you are lucky and you'll find one job that offers what you like, yourself painting into a corner and tie yourself to one employer.
It's popping up more and more because it's so flexible and great to work in. I've spent my weekend working on a Swift project for the Playdate (https://play.date)!
C# would probably be the closest thing feature-wise (and, often, syntax-wise) if you need first-class Linux support, and a lot of knowledge is directly transferable. Not a Java copy people claim it to be but something more low-level :)
With that said, Swift enjoys better FFI by virtue of using LLVM and lower base memory footprint since it does not need to maintain data structures used by GC. Performance however will vary case by case, ARC generally has way higher upfront cost than GC, especially in multi-threaded scenarios but lends itself to an overall more deterministic memory usage, which is important on memory-constrained systems.
I wonder why Swift went with the approach of struct is a value type and class is a reference type. This approach means that when I am defining my type, I have to decide whether it will be used as value type or reference type whereas in C++ same type can be used as reference type (pass by reference) or value type (pass by value) in different situations.
Probably because it causes the least "noisy" syntax. But I think it's a mistake. A language that lets you freely choose between using values and references should make it very clear at the call site which one is being used.
This one "feature" has caused more bugs in my Swift code than anything else. For frequently used types I can remember whether they are structs or classes. But for new code written by others or my own code when the design isn't quite settled yet, I need every syntactical clue I can get to avoid mistakes.
This is not the only place where Swift goes with "clean" syntax at the expense of local clues that help readability. Result builders are another example.
I only guess but maybe because in Swift they encourage you to use value types whenever possible, so you have to make a conscious decision when you are steering away from the default. This way it emphasises a particular way of reasoning about the code.
Also, it's pretty straightforward to create a reference type of a value type if you end up need it: Just create a new type that is a reference type and has the value type as a property. No?
Don’t forget that behind the scenes a value type might actually be used as a reference type when the code is compiled, for performance reasons, but conceptually the language encourages you to think of everything as value types when possible.
A big part of the semantics in the language is “copy on write”.
Swift actually passes value types by reference on closures (anonymous functions) if they aren't explicitly listed in capture group. It's per spec. It allows you to write closures with states:
var count = 0
let closure = {
count += 1
print("Current count=", count)
}
closure() // Current count= 1
closure() // Current count= 2
closure() // Current count= 3
let capturedVariableClosure = { [count] in
print("Current count=", count)
//count += 1 // syntax error, count is const variable. Use var count in capture group
}
capturedVariableCount() // Current count= 3
closure() // Current count= 4
capturedVariableCount() // Current count= 3
Generally you don't use reference types until you encounter a need for something to be a reference type, such as being a reference to a particular resource, or for usage compatibility with an external system.
For example, there are something like eight classes exposed in the minimal swift standard library, representing concepts like managed buffers, singletons like the MainActor, and for implementing concepts like task-local values. These are all examples of types which do not lend themselves to being value types.
Once you start getting to file and network I/O, or interfacing with Objective-C, you start to see the percentage of reference types climb.
Unfortunately the new Observation framework in SwiftUI currently forces you to use classes to model your data. Hopefully they can find some way to make it work with value types.
std::list (that is, a linked list) is pretty easy to write. Whether you want it to be a reference type or copy-on-write or a Collection (probably very difficult) is up to you. There’s not much that’s special in the standard library.
The problem is you cannot implement a reference type without dropping to UnsafePointer or use class. But using class is so discourage nowadays people probably would be better served by adding an Arc / Ref type wrapper like Rust did.
Use of class was strongly discouraged in the Swift world until they rolled out their new Observation framework for SwiftUI that requires using classes for modeling state and depends on two-way data binding to work. So all the arguments we've been hearing for years about the benefits of structs, immutable data, and controlled updates got tossed out the window.
This was bad timing with the switch to strong concurrency checking in Swift 6 because doing strong concurrency handling in a world of reference types and two way binding is really painful.
> As in C++, many Swift types are value types, including String, Array, and Dictionary, which are analogous to std::string, std::vector, and std::map
Dictionary is probably more analogous to std::unordered_map, since it’s an associated hashed-key container.
> The result is on the stack, not the heap, just like you'd expect in C++.
Even though this is likely true I don’t think it’s guaranteed, and if it does happen to be the case I would be cautious to bring it up anyway. Swift leaks things into the heap quite eagerly in ways that might be surprising to C++ developers, where this typically requires more ceremony (or is an express train to UAF :P)
Coming from a C (and derivative) background, this was a good article to help map idioms and introduce new patterns. I still mentally translate to C in my head though.
Not exactly what you asked for, but in my humble opinion Stroustrup’s Tour of C++ is one of the best books for getting up to speed quickly with C++ if you know other languages…
Swift is an incredible language for thinking again.
I dearly miss being able to write code in it on a daily basis.
Although I will say, the compilation time is a killer.
It would have been ideal if they had an interpreted mode for development.
To me the association is Nurse Practitioner, which in the UK is a Nurse upgrade. Nurse is a "normal" undergraduate degree, Nurse Practitioner requires a post-graduate Masters to top that up and grants Prescribing rights like you'd get if you were a Doctor. The Nurses end up with weaker Chemistry, but much stronger practical experience before being granted prescription rights. Their PGT does a bunch about how to read & understand research papers, so that they can stay on the cutting edge and contribute to their discipline.
The way it often is used as a politically correct way of saying "grunt programmer", as opposed to PhD-wielding "expert".
Why not just C++ "programmers" instead of C++ "practitioners" in the case of this article? I'm a PhD in CS who writes C++ all day long, and I think of myself neither as an "expert" or as a "practitioner", but as a programmer.
Thanks for the reply. I had no idea people used practitioner in a derogatory way. If anything I thought it was a little hoity-toity , so that’s good to know :)
But whenever it’s come to performance on the backend, it would be not enough by a large margin. Take JSON serialization for instance, even using a yyjson wrapper it’s been nowhere near the original C performance, slower than Jackson, nlohmann::json, Go’s stdlib, and serde of course. I tried several Swift libraries. Model definition for custom deserializers alone for the few common ISO timestamp representations is a bit cumbersome but bearable. With some other formats and protocols I use, Swift is similarly underwhelming. Logging takes a large toll in performance as well, regardless of what a library appears to suggest when speaking of “efficiency.” I just can’t seem to squeeze out enough performance out of Swift. Async Postgres IO was quite good until I ramped up the load. TechEmpower benchmarks place Vapor relatively low. I get much better performance from low-effort Spring on Kotlin, needless to mention more performant backend frameworks.
Then the IDE story is very bleak. While I’m on Macs, Xcode just doesn’t cut it for me to be productive. Jetbrains discontinued their dedicated IDE and their Vscode pendent is still experimental. Vscode proper support for Swift is not really worth mentioning in my opinion. So I’m basically left with Xcode as an IDE for Swift.
I so dearly wanted to introduce Swift on the backend at my company but that’s just unrealistic right now.