Swift for C++ Practitioners, Part 1: Intro and Value Types
douggregor.net
douggregor.net
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!
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.
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.
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.
(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)
(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).
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
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.
As a dataset, I just use find to generate a list of paths from the file system:
find / > large.txt
I tested with Swift 5.7 and 5.9, and Python is always between 4x and 10x faster.
https://mastodon.social/@dgregor79@sfba.social/1122530402830...
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.
[1] https://github.com/apple/swift-evolution/blob/main/visions/e...
[2] https://www.swift.org/blog/sswg-update-2024/
[3] https://www.swift.org/blog/mlx-swift/
[4] https://www.swift.org/blog/adwaita-swift/
[5] https://www.swift.org/blog/swift-everywhere-windows-interop/
[6] https://marketplace.visualstudio.com/items?itemName=sswg.swi...
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).
I think you would only need xcode-build-server [1] in order to get autocompletion in VSCode.
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.
Today if I search for Swift jobs, it's a list of exclusively iOS app developer jobs.
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 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.
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.
"Product/Platform we are targeting" => set of allowed languages as per their SDKs, official support documents.
The approach "pick language" => "select problem" tends to only work at startup levels, or being very lucky with the IT department policies.
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.
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.
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?
A big part of the semantics in the language is “copy on write”.
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= 3For 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.
Ultimately Swift is dependent on having all significant abstractions be built as part of the language-enabled standard library.
enum List<T> { case empty; indirect case cons(T, List<T>) }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.
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)
This is the first time I’ve heard you could do recursive enum cases. Very neat! I wonder if that’s recent or not.
Nowadays on Java and .NET worlds, we live through our own versions of Python 2, thanks to Java 8 => 9 transition, and .NET Framework => .NET Core.
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.
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.