Async Rust vs RTOS showdown (2022)(tweedegolf.nl) |
Async Rust vs RTOS showdown (2022)(tweedegolf.nl) |
A useful number to measure on a scope is worst case interrupt latency. This is what matters if there's a hard real-time constraint. They measured standard deviation, but not worst case. The usual test setup is that an input signal (typically a square wave) goes to an input pin, interrupt happens if interrupts not prevented, task starts, task turns on an output pin. You watch input to output delay on a scope and look for outliers.
If you're running entirely run to completion, the outliers are determined by the longest compute task. This is a problem if there's a compute task.
This is historically where QNX shines. Interrupt is processed and schedules a thread. About all that happens at interrupt level is thread activation. The thread turns on the output pin. You can look on a scope for scheduling outliers. The best case latency is higher than doing the work at interrupt level, but the worst case latency is constant, even if lower priority threads are compute bound.
This is the difference between real time and "near real time" scheduling.
One approach is to do everything in ISRs, a la RTIC. That requires efficient, vectored, nested, tail-chained, base priority-ed interrupt silicon, and a lot of it, but it is feasible and elegant where this exists, such as Cortex NVIC. Emerging RISC-V devices with xCLIC (ch32v, gd32v, newer ESP32 and others) are potentially even better.
I really appreciate that the author took the time to add the Embassy vs RTIC addendum.
That only works for really simple systems. On more complex systems there is a pretty good chance you will end up with locked up hardware if your ISR is long enough. Interrupts need servicing to keep the data flowing, prioritization is a job for the OS, not the hardware.
For the times where there is a background load: RTIC has task priorities and pre-emption, so you can run your compute-intensive task with a lower priority and react to interrupts in a timely manner.
better to acquire these or use timestamped gpio and compute real statistics- but for the sake of illustrative metaphor, sure.
Perhaps "Embedded async Rust vs. C RTOS"
You just need to read the Reddit comments to see why this is not a useful comparison [1] [2].
[1] https://www.reddit.com/r/rust/comments/sik3g0/async_rust_vs_...
[2] https://www.reddit.com/r/embedded/comments/she3u9/async_rust...
The title on HN should probably be updated to that
Rust seems to have modest support in some places.
With AI I don’t know language really matters anymore.
bump up to EmbeddedLinux and i think Rust wins ovr C
2022 explains that perfectly, albeit leaves me less happy.
Slightly off topic but threads were never supported by the web (even now you only have message passing between workers) so it's a bit hollow to say async won.
Is there somewhere that async/await is implemented as a different concurrency mechanism?
A number of RTOS allow the use of restricted C++ with complex features disabled; often called C with classes. The compiler used will most likely _C/C++_ versus only _C_. Example: µC/OS-II used in military, aerospace, and medical applications. [0]
[0] https://micrium.atlassian.net/wiki/spaces/osiidoc/pages/1638...
If a particular interrupt has a hard real time constraint, it sounds like a great candidate for a higher priority interrupt which will let it meet that requirement.
The biggest constraint is that this is really a single core model. You need something different if you go to SMP. Though there, AMP where the main core runs this 'interrrupt controller is your scheduler' scheme, and the other cores run against a work stealing scheduler for compute bound work items still is a very nice system to program against.
That is true of all such systems, from MCUs to the greatest CPUs ever made, and all prevailing software stacks running on them. Nothing about RTIC precludes servicing interrupts in a timely manner. It is based on a mathematical model of concurrency called Stack Resource Policy (SRP) and is entirely capable of reliably implementing whatever interrupt regime you imagine your "complex" system requires, with zero risk of priority inversion.
> prioritization is a job for the OS, not the hardware
So say you. The long and storied history of fragility and failure related to scheduling and interrupt handling suggests there is opportunity for greater rigor than the conventional muddle you assert as best.
But Embassy, with different task switching mechanism, mean i need to learn another new concept, understanding the pros/cons. That is not what i want to do when busy adapting to Rust.
(I’m being sarcastic, obviously. x86 interrupts and interrupt returns are hilariously slow. FRED may improve this by quite a bit.)
All combined with the fact that there's a good chance the memory the interrupt handler is going to touch isn't in the cached working set anymore, both in the actual L* caches and in subtler places like the branch predictors and TLBs.
Check out the pseudocode in the SDM — there are pages of it, and the pseudocode isn’t even complete.
FRED simplifies the state transitions such that the new state is mostly a foregone conclusion based on MSR contents.
Also, any good technical resources that concisely describe FRED?
I found this, which isn't bad but it's a bit more dumbed down than I'd like: https://www.tomshardware.com/pc-components/cpus/amd-adopts-f...
The other problem is that A series and x86 runs out of DRAM typically whereas M is generally set up to run its ISRs out of SRAM so it can actually realistically hit its low latencies. But even though A also has significantly better nominal interrupt latency (competitive with M actually), in practice it’s similar to x86 because DRAM dominates anyway. Also of course best case latencies are when you don’t use the FPU which is more common on M series than it would be on A or x86 (and x86 also has generally more SIMD stuff to handle)