Originally posted by computerquip
View Post
Announcement
Collapse
No announcement yet.
Making The Case For Using Rust At Low Levels On Linux Systems
Collapse
X
-
Originally posted by mmstick View Post
We all know that C++ can export a C interface. That isn't what the argument is referring to.
Comment
-
Originally posted by SystemCrasher View PostSome few objections & observations:
1) Low level code is not supposed to be large and complex in first place. If it is not a case, it is not a language to fix but project management I guess.
2) Strong types are double edged sword and could be annoying as well.
3) Furthermore, all low-level runtime environments are written in C. They are using C types anyway. Be it syscalls, low/mid level libs or something, you have to call it unless you're in mood to write whole OS and usermode from scratch (good luck with it, come back in ~10 years and show your superb achievements).
4) Dealing with conversion of types is absolutely last thing one may want in low level program. Whatever, Pascal/Delphi are pain to use for low level things due to the fact virtually all OSes are using C as native implementation language. Therefore all low level calls are using C types all over place and doing conversions is no fun and even gives birth to whole new class of mistakes and errors.
5) Sometimes it could be handy to be able to enter kernel side. A bit of kernel superpower does not hurts on low level. But wait, I could only use C to do that. Needless to say learning 2 different languages is a bit ridiculous and redundant, right?
6) Writing perfect programs is cool. However there're thousands of C progs and libs. If you're McLeod, you would not mind rewriting everything in Rust. Mortals are really better off changing mere 20 lines of code in lib or prog which "almost does the thing". C got huge advantage here, you could literally write few lines of code yourself, while reusing the rest. Rust seems to be bad at it. It lacks bindings to most libs. Could it be used to create "universally reusable" lib like C, callable from almost any language around? Ability to create new building bricks which are reusable by others matters.
Although it can be argued that rewriting from scratch using idiomatic Rust is more ideal and can lead to faster implementations, large projects can easily start by just adding rust to the build system and converting one function at a time.
As for bindings to C libraries, there are tools to automatically generate bindings from C headers so this really isn't a problem. Providing a binding on Crates.io is best if you also go a step farther and wrap the C bindings up so that the library is more idiomatic to Rust, such as adding error handling.
7) Mozilla have shown us what they're up to, by enforcing signatures on extensions, with no way around. Relying on toolchain from someone like THIS looks shortsighted and hazardous to say the least. Especially when they pedal "package manager" theme. Wouldn't they introduce signatures on their package manager as well, with Mozilla being the only central authority deciding what is "good" and what is "bad", with no means of override?
8) I'm really fine with installing somelib and somelib-dev using my system-wide package manager. I really do not want some third-party crap to bring some files and execute code in my system. It screws up OS management and brings winduz-like practices on my head.
- Likes 1
Comment
-
Originally posted by computerquip View Post
Uh, you said, "C++ really isn't good for software libraries either due to C++ not having a stable exportable interface." Unless I'm taking advantage of the verbatim quote? Your argument is that C++ doesn't have, or isn't capable of, a stable exportable interface which is bologna.
With Rust software, you do not even need to have the Rust standard library installed. Rust software is linked statically at compile-time, and thus will never break because a package was updated on the system, unless that package is a dependency to Rust that is dynamically linked. Cargo then allows you to perform application-wide LTO on your build to optimize it and reduce binary size greatly.
- Likes 1
Comment
-
Originally posted by mmstick View Post
The argument isn't about the existence of a C ABI, which is very hard to perform in comparison to Rust. The issue that C++ poses on the system is bad enough that there is a section in the Gentoo wiki dedicated to it. Ever tried updating a Gentoo installation after a GCC update and having all the C++ software on the system break because libstdc++ was updated? Anyone who maintains packages for a Linux distribution or uses Gentoo will understand that any time GCC is updated, you have to also re-release all your C++ packages, and the same goes for when a C++ library is updated, all packages relying on that library have to be rebuilt and re-released.
With Rust software, you do not even need to have the Rust standard library installed. Rust software is linked statically at compile-time, and thus will never break because a package was updated on the system, unless that package is a dependency to Rust that is dynamically linked. Cargo then allows you to perform application-wide LTO on your build to optimize it and reduce binary size greatly.
That said, you don't *actually* have to recompile those packages.
The very wiki page you're talking about explains it better than I can: https://wiki.gentoo.org/wiki/Upgrading_GCC#ABI_changes
Comment
-
Originally posted by mmstick View PostThere are a lot of projects that have to be large and complex while also being written in a low level language. The Linux kernel, for example, would largely benefit from being rewritten in Rust.
Has Rust been crafted with all these use cases in mind? Where you could really get rid of smartass helpers and services and just do things in simplest, robust, extremely predictable ways? Say, C could be put into mode it works like a "code generator" similar to "high-level assembler". One could take really precise control over environment. Like very exact memory layout, memory accesses and so on. This is very important in uninitialized system, because one wrong move and everything is FUBAR.
Even -nostdlib is non-standard GCC (and maybe clang?) extension, not something C mandates. Yet that's what makes it possible to use gcc to create truly low-level code like kernels, boot loaders, all kinds of self-sufficient firmwares and so no. And, honestly, it is very convenient when all this crap using same language, using same understanding of e.g. data structures (a bit tricky in C, but C99+ makes it much better). Even usermode things MAY need e.g. custom memory allocator to get best performance. When language pedals huge runtime lib and memory management so much, I'm getting worried about these issues, to say the least. I doubt Mozilla ever cared about something like this.
Even usermode low-level programs sometimes may want to do "wrong" things. Say, one of my programs had to read exact PHYSICAL memory address. This is different from VM address, and takes rather unusual Linux-specific trickery & calculations. This is also Fundamentarlly Wrong Way of accessing mmaped devices. However it has been 100x easier compared to any other options and since it has been read-only access on perfectly RO HW status register, it is safe. And saved me shitload of time compared to e.g. writing kernel driver and so on. I needed just one fucking value from HW status register at certain physical address, to understand how to proceed next. Fortunately most of you would never stumble on this code because it has benen really task-specific stuff for embedded Linux device. I wonder if Rust could handle this at all. Let's assume I want to read unsigned 32-bit value from physical mem address 0xDEADC0DE. I know HW is little-endian and ok with unaligned mem accesses (may or may not be a case, btw). How it supposed to look in Rust?
We could easily drastically reduce the amount of SLOC and design APIs that are more generic, and yet just as fast, much easier.
Rust's types are not annoying in the least. If you actually try developing software with it, it's easy to hate languages that do not provide the same level of guarantees and finesse that Rust's type system is able to pull off.
Rust's libcore interfaces directly with LLVM primitives, which is much lower level than C,
and very much like a modern version of Assembly.
It is what allows Rust to achieve C-like performance today, and better-than-C performance in some areas, and will allow better-than-C performance across the board in the future. SIMD support and other CPU-specific instructions can be exposed to Rust through the LLVM primitives.
C is good in that you virtually never hit the wall with decent C toolchain like GCC. Basically, toolchain like GCC allows one virtually everythnig assembly language permits to do but in more portable and convenient ways (i.e. you only have to break portability when you really have to do something truly HW-specific). Once some lib behaves poorly or gets in the way, one could get rid of it, redefining runtime environment from lowest levels as needed.
That's what allows to use C to create boot loader, firmware, kernels and so on. What is LLVM if we've just been powered on? There is only code and some unused memory. Everything else is have to be created by launched code. There is no notion of "LLVM" or "memory allocation" at this point. Actually, whole memory allocation kind of thing is optional in C. One could use fully static memory allocation instead. This way one could create system which can't run out of memory. At least not by usual means. At most one could provoke "stack overflow" based things, but if there're no malloc, it can't fail either. Very handy in applications like microcontroller firmwares demanding reliability (erm, default Linux attitude about overcommit isn't reliability best friend btw, but only low-level system ppl suspect this :P).
Rust does not perform any sort of type conversions at runtime. Everything, including C types, are desugared to LLVM primitives and then converted to machine code. If you've ever actually tried to work with C libraries inside Rust, it is actually quite easy and convenient.
It does not open up a 'whole class of mistakes and errors' in the least.
The main downside is just knowing the standard quirks of C libraries such as what different error codes returned by C functions actually mean, as C libraries do not have a concept of sum types like Option and Result.
The beauty of Rust is that you can do both programming lower level than C with libcore, and programming higher level than C++ with libstd. There's no need to have two different languages if you keep everything in Rust, which supports both low level and high level programming without hindering either's capabilities.
It's actually not that hard to convert existing C libraries into Rust. There was a recent talk at the last Rust convention about this very subject. The Zopfli library from Google was translated to Rust piece by piece, one function at a time. She wrote Rust unit tests along the way to not only ensure that the Rust replacements were tested, but also that the C functions could be tested too.
Although it can be argued that rewriting from scratch using idiomatic Rust is more ideal and can lead to faster implementations, large projects can easily start by just adding rust to the build system and converting one function at a time.
As for bindings to C libraries, there are tools to automatically generate bindings from C headers so this really isn't a problem. Providing a binding on Crates.io is best if you also go a step farther and wrap the C bindings up so that the library is more idiomatic to Rust, such as adding error handling.
How does this relate to Rust? Do you even know how Cargo works? It would be impossible for them to require signatures to Cargo crates when Cargo merely pulls libraries directly from git URLs. The Crates website is just an index of crates that conveniently map versions to precise git commits.
You clearly do not understand how or what Cargo is. Cargo is not a system package manager like APT, DNF, or pacman. Cargo does not manage packages on your operating system. Cargo is a build tool that manages crate dependencies automatically.
Rust software still has to be packaged into debs and rpms and PKGBUILDs when distributing Rust software to users on their platforms.
Comment
-
Has Rust been crafted with all these use cases in mind?
In fact, it's been specifically designed to allow you to reason about your program's low-level behaviour even more effectively than with C, by specifying much less undefined behaviour for the compiler to play around with than the C spec.
Even -nostdlib is non-standard GCC (and maybe clang?) extension
IMHO, imcompatibility with shitload of pre-existing libs is a disaster.
Bindings in rust aren't like bindings in other languages. Rust's compatibility with C libraries is very similar to C++'s and Rust bindings exist mostly to enforce invariants and bridge the gap between how idiomatic C and idiomatic Rust do things. (eg. A wrapper around a database library would hook it up to Rust's RAII-style model for closing handles when they go out of scope.) Given that one of Rust's design goals is "zero-cost abstraction", the compiler's also very good at optimizing the wrappers to code at least as good as what you'd hand-write. (In the case of iterators, for example, you get safety without bounds checks because the compiler can prove, at compile time, that they're unnecessary. In addition, the closure-based API gets optimized to the same code you'd get by writing a for loop without closures.)
And who told I want it to download some crap from network without my consent? Then, what about centralized locations and means of override? Could I have my own repos/lists, getting all Mozilla spiggots out of the way? If no, I wouldn't touch it with 10' pole for the time being. Getting locked down on centarlized repo/list managed by Mozilla thing is absolutely last thing I may want.Last edited by ssokolow; 26 June 2016, 01:20 AM.
- Likes 1
Comment
-
Originally posted by atomsymbol
From my perspective, the most severe problem of C++ is the amount of time it takes to compile. In theory there do exist methods for making typical C++ code compile 10x faster but unfortunately C++ compiler implementations aren't there yet.
Comment
-
Originally posted by mmstick View Posttl;dr: It's apparent that you have no idea what you are talking about. Talk about FUD, you're full of it..
Comment
Comment