Different tools for different needs!
I appreciate this, as looking for better tools in embedded space is welcome. Just pity that so many of them come with so many dependencies and large library sizes.
It seems to be getting better though. For example... https://tweedegolf.nl/en/blog/65/async-rust-vs-rtos-showdown
What about rust today makes it suitable for replacing some code but not all of it? What’s better, what still isn’t there yet?
I guess from my limited experience register fiddling ergonomics in rust were miserable, but I was blessed with working with an extremely safe and ergonomic set of c macros at work (you could do something like rmw(i2s, clockconfig, enable, set) and know if it compiled that such a value corresponded to a valid value in a field that existed in such a register in such a peripheral) and I know some vendors provided c “pac” equivalents that were pretty sloppy and error prone, if still nicer than all the punctuation needed to set a bit in a register in rust. How is HAL quality for popular platforms? How much does that matter? The stm provided c HAL is extremely limiting in my experience, anything fancy requires bypassing it, and I worked places without touching the vendor provided libraries ever but I guess having it as an option for popular platforms is important.
Could you elaborate on that? That's not something that's supposed to happen and if it has, I would like to make sure we register it in our issue tracker.
[0] https://users.rust-lang.org/t/psa-breaking-change-panic-fmt-...
https://github.com/tock/tock/blob/3a0527d586702b8ae8cb242391...
Reads and writes turn into volatile reads, so everything works out under the hood. You get the benefits of everything having good names, declared sizes, and proper typing on your register accesses. You can extend that to bit accesses as well.
Rust still has a few areas it isn't competitive in, like your hyper limited or obscure chips (e.g. 8051s, XAP), mature tooling around formal methods, and a certification story for safety critical code. People are working on these latter two issues (e.g. ferrocene) and supposedly very close to public delivery, but you know how slow the industry is to adopt new things even then.
I know several easy ways to boost ipnsort's performance by 10% but don't because they don't align with my binary-size and compile-time goals.
https://esp-rs.github.io/book/ https://github.com/avr-rust/ruduino
Rust also has a "core" library which is the absolute minimum the compiler assumes. It's well defined, well documented and how you use it is standardised. All C implementations have a similar library. For gcc you get it with -lgcc. But it is not "well defined, well documented, with standardised usage".
So I'd disagree with you. I've done it, and avoiding libc for in different C implementations is tricker than Rust.
Support outside of ARM is a bit rough, but it's improving for RISC-V and Espressif.
Regarding `ValWithPtr` my goal was to make it as close semantically as I could to the Rust code while keeping the example to a minimum to avoid distracting from the main point. If you have a concrete idea how `ValWithPtr` could have been modeled better given these criteria, please let me know.
How does this differ from implementing GC in C++ then showing how much better Java does?
No one sane would mutate elements, free memory or throw exceptions in a sort comparison function. To demonstrate fairness, you therefore need to at least also show how you could use Rust "unsafe" to break the sort, which is also a language feature you probably wouldn't want to use in this context.
No one sane would intentionally do so, but we are not talking about that. The OP has a section that links to a blog post by Danila Kutenin, which mentions `std::sort` often just segfaults if a comparator doesn't satisfy irreflexivity or asymmetry, yet such comparators were found in the wild, even passing all reviews and even tests (!) because this behavior greatly depends on the number of elements. Given this occurrence of the actual bug in user comparators, it should be no surprise that they may also contain mutations, memory deallocations and exception throws (all of which can easily be a side effect from internal routines).
It is great that rust can prevent them those additional issues, but in the grand scheme of things it is not something I lose sleep about.
1. How do you compile the C++ code? E.g. what flags do you use with GCC, clang and MSVC
2. How exactly is C++ binary run through a Rust benchmark suite? FFI?
3. Is it possible for rust code-under-test to be at any advantage here because it is run and built natively from the benchmark written in the rust itself?
What I find questionable though is the actual C++ code found in the benchmark:
1. Exception-handling code around std::sort and std::stable_sort - nobody does that. What problem are you trying to solve with this? Comparators do not throw exceptions.
2. Using function pointers for the comparators - surprising to see such code in C++ benchmark - it's very non-idiomatic and essentially making it impossible for a compiler to inline the code. std::sort is rarely used like that.
3. Passing over some magical third argument to the comparator function - ?
4. Passing over the context to the comparator "function" - I fail to see if "ctx" has been used anywhere?
5. "Making" the comparator function with make_compare_fn which in turn instantiates a lambda that, again, throws an exception from its body.
6. Storing a comparison result - why? You only need to return true or false from a comparator.
7. Modeling rust "panics" by storing a boolean is_panic plus exception-handling code plus throwing exceptions when is_panic is "ON" - why?
8. Confusing exceptions with rust panics - even if you wanted to do so, which still would be an arguable thing to do, std::abort or std::terminate is a replacement for std::panic. Not throwing exceptions and implementing the is_panic logic around it.
9. What is https://github.com/Voultapher/sort-research-rs/blob/main/src... being used for?
I think you're making a bit dishonest representation here for the reasons above. And I have not delved very much into depth nor have I covered all the code but just the fragment of it. Also, it is not quite clear how everything is put together and run because, ideally, you would want to have multiple binaries built with their representative toolchains/scripts _regardless_ of your benchmarking framework. And only then I would want to point the benchmarking framework to the respective binary to run the test. Here, it seems it's the other way around.
For ValWithPtr to make sense it needs its semantics defined. Correct C++ types can be deep copying, move only, reference counted, singleton instance etc. For example typed deep copy version without attempting any verification (link to compiler explorer): https://godbolt.org/z/3sesYY8of
If it is not helpful for you please feel free to ignore all of the above.
* The number of items being sorted must be a power of 2 (2^n).
* The number of comparisons it makes is larger than other sorting algorithms like merge sort, which will make it slower in non-parallel environments in many cases.
Bitonic sort has the advantage that it can be implemented to run in highly parallel environments (hardware, FPGAs, etc.), where the cost of comparisons is offset by them operating in parallel, so the sort completes faster even though more comparisons are occurring.
The power of 2 requirement only applies to the core kernel.
All CPUs in usage today are parallel (in 3 to 4 different ways), and bitonic sort is the best performing sort on both amd64 and aarch64.
The obvious thing is to use SIMD.
Intel publishes its own fast library for this, which isn't even in the benchmark list.
Vqsort performance on M1 is indeed about half that of AVX-512. The NEON instruction set is missing some important operations for Quicksort, including Compress and popcount of vector masks.