Feasibility of Swift in Robotics, IoT, Self Driving and more

Hey all,

I’m exploring the feasibility of building an robotics platform entirely in Swift 6 and higher.. My goal is to simplify the development and deployment of robotics platforms, including actuators that operate at frequencies exceeding 100 Hz. However, I’d like to understand potential performance pitfalls of using Swift in these scenarios compared to the industry-standard approach of C++.

Most robotics companies prototype in Python and transition to C++ for production. Even worse, is that most companies will even pick tons of different languages like JS, Java, Ruby, and Rust fragmenting any chance of community or interoperability of packages. I believe Swift offers a more modern, developer-friendly alternative while still allowing interop with C++ for performance-critical components. Swift also has an escape hatch for high performance code with Swift/C and Swift/C++ interop provides an escape hatch for developers who need extreme performance, making the case for Swift even stronger.

Key Questions and Concerns

  1. Bounds Checking and Heap Allocation: Swift arrays perform bounds checking and are heap-allocated, which can introduce latency. I came across the proposal for fixed-size arrays (or vector types) here. Could these types significantly improve performance, especially in real-time contexts?
  2. Automatic Reference Counting (ARC): Swift’s ARC adds overhead compared to manual memory management in C++. However, with borrow checking and the consume keyword introduced in Swift, can this overhead be mitigated effectively for robotics use cases?
  3. Deterministic Performance: Robotics systems often demand deterministic, low-latency performance. Does Swift currently offer sufficient control over memory and resource management to meet these demands, or are there scenarios where C++ will always have the upper hand?
  4. Concurrency: Swift’s structured concurrency model is compelling, but how does its real-time performance compare to C++-based approaches like std::thread or custom event loops?

Correct me if I'm wrong on any of my assumptions.

Looking for feedback and insights

  • Any benchmarks or use cases where Swift has been evaluated for high-performance, real-time systems.
  • Experience using Swift for applications requiring deterministic performance.
  • Specific pitfalls or limitations when using Swift for performance-critical robotics or actuator systems.
  • What are somethings I can do to overcome challenges of Swift 6.0.0 today for extreme performance scenarios?

I’m convinced that Swift has the potential to disrupt the current JavaScript/Java/Python/C++ pipeline in robotics by offering both developer productivity and performance. If we can leverage its features effectively while addressing performance bottlenecks, we could make robotics and IoT development significantly more accessible. What Apple has done with standardizing edge mobile development I think is an excellent analogue for what could be done in IoT, Robotics and Edge devices.

Correct me if I'm wrong anywhere on my assumptions. Absolutely tell me if Swift could never deliver in this area.

5 Likes

bounds checking is not a major consumer of CPU cycles, and it rarely makes sense to go out of the way to optimize away bounds checking. i often find myself regretting skipping the bounds checking. in cases where it does matter, it is an option to use unsafe memory views to bypass bounds checking.

fixed-size arrays will allow mid-size arrays to be allocated on the stack, which might reduce memory fragmentation, although this will not affect latency. small vectors, like 3D coordinates, would have already been implemented as structs containing scalars, so they were never heap allocated in the first place.

Swift ARC is a famous performance villain in Swift apps, but it’s important to remember that many who experience these problems are doing Obviously Stupid Things with ARC, like absurd overuse of classes. ARC is not something to fear, and borrow checking and consume were not needed to avoid it, although they formalize undocumented features that had previously been used in their place.

in general, i have not found optimized Swift code to be inherently slower than optimized C++ code.

many who believe that Swift code is slower than C++ code are using high level standard library features that have no equivalent in C++, for no real reason except that Swift makes it easy to take shortcuts that have performance pitfalls. if you code in Swift as you would in C++, you will not find that the language is inherently slower than C++.

others are complaining about a more subtle issue, which is that unoptimized Swift code (meaning, built in debug configuration) is dramatically slower than unoptimized C++ code. most people run into this when they are using libraries (like a ZIP library) that really ought to have been built with release optimizations, but weren’t, because they wanted to build the driver in debug mode for development, and SwiftPM (the most popular build system for Swift) does not know how to build dependencies at a different optimization level than the client code. if you are building the client code in release mode, it will not experience this problem.

i do not know enough about Swift’s structured concurrency runtime to answer this part of your question. that said, i maintain things powered by Swift that operate on frequencies over 1 KHz, so it doesn’t sound like 100 Hz is asking anything unreasonable of Swift Concurrency.

15 Likes

Just gonna leave this here in case you don't know about it yet: Swift.org - Get Started with Embedded Swift on ARM and RISC-V Microcontrollers

4 Likes

I wouldn't trust Swift for such an application domain ­– yet. I'm not able to back this up with hard data (since my MCU platform is not supported by clang, and may never be), but I'm in camp C++, when it comes to soft realtime requirements.

Plus, the part where it really gets interesting (concurrency) hardly supported on MCUs. The abstractions in Swift 6 have, uhm..., "problems". Swift has the potential to become a great language for embedded, but this is still infancy level, so depending on your production requirements, it may not be for you.

my MCU platform is not supported by clang, and may never be

Which MCU is that?

1 Like

Currently we don't see a lot of demand for MCUs just yet. The biggest demand from Robotics is in the core logical area which requires a lot of GPU power, lots of RAM and lot of storage. Some of the projects that I'm encountering require almost the power of a mid-size to ultra-end gaming PC.

Robotics today are 300 lbs Linux Boxes; if you take that into consideration, Swift should suffice yes?

I'm sure that Swift will get more mature and embedded space for MCUs, but currently, it doesn't seem like that's where the biggest pain points are.

2 Likes

There are four levels: a) general good performance, b) repeated execution, c) changing code, d) Swift versions.

a) Swift can be quite fast, the philsophy of Swift is that all constructs should have a good optimization when compiled. But beware of which constructs or methods you choose for a certain purpose, there can be large differences in performance. Regarding classes vs. structs: Use classes where they really make sense, optimize by making classes “final” where further inheritance is not needed, else use structs. The performance penalty for using classes is then not too bad, it is worse to always rely on structs even where they are not a good fit. But always think about if structs are maybe a better idea (learn about protocol oriented programming, think about concurrent contexts), do not use classes just because you are used to classes coming from another language, structs should be the “default”.

b) Without a tracing garbage collector and with (in newer Swift versions) deterministic destructors, Swift programs can count (besides concurrency) as “deterministic” without unexpected delays or errors that are hard to reproduce, other than e.g. Java.

c) Regarding stable performance after code changes, it is a goal of Swift that code changes should not “surprise” you with worse performance at seemingly independent places (bad example: Haskell), the idea is that optimizations by the compiler should be “composable”. I cannot say how perfectly that goal is achieved, but I am not aware of bad experiences.

d) That said, Swift is still evolving rapidly, there were some performance digressions in the past with newer Swift versions for certain features. Test new Swift versions early and report any problems.

3 Likes

ESP32S3 (Xtensa Tensilica).

ESP32S3 (Xtensa Tensilica).

There is impressive steady progress on upstreaming the Xtensa support to LLVM and recently also to Clang, Tracking Issue for merging to upstream (LLVM-57) · Issue #4 · espressif/llvm-project · GitHub, and I believe that even our Embedded Swift community in this forum is actively contributing to the motivation for upstreaming.

5 Likes

Thanks for all the help here. This builds a lot of confidence that we could build an open source Framework in Swift for all edge development (with the escape hatch of C and C++ interop for existing libraries or code that needs more particular control)

It seems like .binaryTargets for Linux Libraries is one of the big issues that I'm facing right now. Do you know who would be able to help assess the work needed to make package management a lot easier of an experience?

1 Like

Indeed, I also think that memory safety may be one of the benefits of using Swift on embedded, though of course, if you implement something wrong using "unsafe pointer"-like features such as Swift MMIO's unsafe address, you're opening yourself to vulnerabilities again.

There’s a reason why these features are called unsafe, but fortunately, this minimizes the potential areas where such vulnerabilities may occur.

If you need, say, realtime performance for some really-fast realtime sensors (potentially bit-banging them) and you find out that Swift somehow lacks that on its own, as you already said, you can always use Swift's interoperability to code that part in C/C++ or even in assembly. Or, perhaps, use MCU-specific features, such as Programmable I/O (PIO) in Raspberry Pi's Pico series boards.

But either way, you said you're interested in Linux devices, so I guess realtime GPIO performance also depends on how you're going to do it in Linux in general, either with C++ or Swift. Linux is not an RTOS, so there's that.

2 Likes

You may find this relevant. Note that the dyld cache stuff does not currently exist on Linux.

1 Like