[HN Gopher] The Linux Kernel Prepares for Rust 1.77 Upgrade
       ___________________________________________________________________
        
       The Linux Kernel Prepares for Rust 1.77 Upgrade
        
       Author : mindracer
       Score  : 109 points
       Date   : 2024-02-18 13:55 UTC (9 hours ago)
        
 (HTM) web link (www.phoronix.com)
 (TXT) w3m dump (www.phoronix.com)
        
       | SushiHippie wrote:
       | Do I understand it correctly that upgrading to a new rust version
       | is mostly implementing new best practices and new features,
       | instead of needing to "fix" your code, as rust is backwards
       | compatible?
       | 
       | I've only used rust nightly for my own projects and didn't give
       | too much thought about rust versions
        
         | codetrotter wrote:
         | For normal projects yes.
         | 
         | And you can use clippy to tell you about changes you should
         | make.
         | 
         | For example, in my projects I run this in the CI pipeline:
         | cargo clippy --all-targets --all-features
         | 
         | and                 cargo fmt --all --check
         | 
         | In addition to the regular test and build steps.
         | 
         | This both means that I follow clippy recommendations and cargo
         | fmt in the first place, and also that my CI tells me about any
         | clippy changes if I didn't notice them myself as well as any
         | formatting I'm not following. In my main IDE I auto format the
         | code of course. But sometimes I make small changes in vim and
         | don't run the format step myself so it's nice to have for that
         | reason as well.
         | 
         | For the integration of Rust into the Linux kernel I imagine
         | it's a bit more convoluted.
        
           | estebank wrote:
           | For Rust on Linux it's a bit more involved because they use
           | nightly features, which can change from day to day. In
           | practice there's an implicit tiered strata, with features
           | that rarely change and features that frequently change in
           | bursts. I would like it if we formalized that distinction a
           | bit. We already mark when a feature is _very likely_ to
           | change (unstable_features), but not when they are _very close
           | to being stabilized_.
        
         | CUViper wrote:
         | Rust is backwards compatible when you stick to stable features,
         | but the kernel uses unstable features that can and do incur
         | breaking changes.
         | 
         | https://github.com/Rust-for-Linux/linux/issues/2
        
           | surajrmal wrote:
           | It seems prudent to limit rust usage in the kernel until that
           | list can be burned down to zero. It makes sense that you need
           | to at least get rust in the kernel to find out what missing
           | features you need to have implemented and stabilized, but
           | excessive use will make folks lives painful as they try to
           | track upstream rust releases.
        
             | estebank wrote:
             | What you propose is exactly what's been done by the kernel.
             | They are integrating the language in a non-mandatory way,
             | to both exercise the kernel side and the language itself.
             | The unstable features haven't been stabilized because
             | either they have open questions on their implementation
             | (and having a customer using them helps define them) or no-
             | one has cared enough to complete them (and having a
             | customer using them gives them the extra push). Either way
             | what's happening now is exactly the process you are
             | proposing.
             | 
             | The article is about updating the Rust version the kernel
             | targets where a feature they use (offset_of) was
             | stabilized.
        
             | fl0ki wrote:
             | Please bear in mind that Linux has used non-standard GCC
             | extensions to C for decades as well. The tradeoffs here are
             | their call to make.
             | 
             | Besides, at this stage, it makes perfect sense for Linux to
             | use unstable Rust features. It was one thing to say Rust
             | should be great for writing kernels, it's another to
             | actually get feedback on how it needs to be better, and
             | that's only possible if the potential improvements are
             | motivated by those who need them and incubated without the
             | constraints of backwards compatibility nor the risks of
             | locking in permanent tech debt.
             | 
             | Rust's unstable feature concept was designed for exactly
             | this kind of freeform evolution and it's working exactly as
             | intended. As for the specific tradeoffs being made in
             | Linux, its contributors are in a much better position to
             | weigh those than we are.
        
         | pornel wrote:
         | Rust-for-Linux made it more complicated for themselves, because
         | they chose to enable unstable/experimental features of the
         | compiler without waiting until they're released, so they don't
         | get the stability and compatibility guarantees that normal Rust
         | projects get.
        
           | bonzini wrote:
           | The alternative was to do the same and also not merge what
           | they had. Stuff like custom allocator support is not
           | optional.
        
             | saghm wrote:
             | I was confused when reading this because I was pretty sure
             | that using other allocators had been supported for a while
             | in Rust. From refreshing myself on the details, it seems
             | that replacing the default allocator is stable
             | (https://doc.rust-
             | lang.org/std/alloc/trait.GlobalAlloc.html), but the API for
             | arbitrary allocators (which includes stuff like being able
             | to do "zero-size" allocations) is not yet stable
             | (https://doc.rust-lang.org/std/alloc/trait.Allocator.html).
             | I guess if there were ever a project that needed fine-
             | grained control over how allocators be work, it would be
             | the kernel.
        
               | charcircuit wrote:
               | More importantly allocator_api adds try_new which means
               | you can handle allocation errors.
        
               | remexre wrote:
               | There's also https://docs.rs/allocator-
               | api2/latest/allocator_api2/ -- I end up using this more
               | often than I end up using custom allocators, simply
               | because it has a stable version of the currently-unstable
               | functions for constructing uninitialized
               | Vec<MaybeUninit<u8>>s.
        
         | steveklabnik wrote:
         | Yes, generally. For example, recently David Tolnay shared the
         | amount of burden Meta has when upgrading the compiler:
         | https://old.reddit.com/r/rust/comments/19dtz5b/freebsd_discu...
         | 
         | > I estimate it's about 1/2 hour per 1 million lines, on
         | average.
         | 
         | That being said, Rust for Linux isn't using stable Rust, so
         | they have a higher burden than projects that do.
        
         | almatabata wrote:
         | If you ignore dependencies and stick to stable features yes.
         | 
         | If you include dependencies then it can happen that a
         | dependency relies on unstable features. In which case you might
         | have to upgrade the library version (if they support the new
         | compiler version). The library might have changed the API by
         | then which would force you to change your code.
         | 
         | Except for the above use case, upgrades to the latest version
         | of the compiler have been painless for me.
        
           | paavohtl wrote:
           | Dependencies are not allowed to use unstable features either
           | with the stable compiler. The only exception is the standard
           | library, which uses numerous unstable features even with a
           | stable distribution of Rust.
        
             | tialaramex wrote:
             | Worth briefly explaining the rationale for this (stdlib
             | gets to use unstable features)
             | 
             | Rust's stdlib is maintained with the rest of the language
             | and by the same broad team, so, if you're tweaking unstable
             | feature X, you are _also_ responsible for ensuring the
             | stdlib people using feature X sort that out. I 'm not sure
             | if Rust's internal policies mean you shouldn't land a
             | change to the main tree without accompanying stdlib
             | patches, or whether you're only required to give them
             | adequate notice, but either way it's not going out the door
             | in a stable release being incompatible with its own
             | implementation.
             | 
             | This couldn't really work with 3rd party libraries.
        
               | jcranmer wrote:
               | There's a second category of unstable features to mention
               | here.
               | 
               | Some of the features are essentially perma-unstable,
               | because they're exposing some compiler intrinsics for the
               | library to be able to use. This is the equivalent of
               | things like __builtin_* for C compilers.
        
       | kramerger wrote:
       | The LKM post mentions binary size improvements.
       | 
       | One issues I have had with Rust applications is the huge binary
       | size (yes, I know this has improved a bit lately). Is there a
       | good comparison between kernel C and kernel Rust code in this
       | regard?
        
         | makapuf wrote:
         | From (1) I guess most of the binsize comes from stdlib that the
         | kernel does not use, so I guess that's two different problems.
         | 
         | (1) https://github.com/johnthagen/min-sized-rust
        
           | vlovich123 wrote:
           | That wouldn't explain what the size improvements are from the
           | upgrade as the kernel always built nostd.
        
         | surajrmal wrote:
         | Most size issues come from not using release builds, using too
         | many dependencies, or overuse of generics. The rust std lib
         | being linked in statically also contributes.The kernel
         | shouldn't suffer from any of these problems. Plenty of embedded
         | use is able to use rust in highly constrained environments
         | without size issues compared to C.
        
           | zadokshi wrote:
           | Saying part of the problem is "using too many dependencies"
           | is not an overly helpful thing if the ecosystem keeps on
           | trying to download 3Gb of build dependencies because you
           | tried to use some simple little library. The problem is
           | obvious, it's the solution that is much more difficult.
        
             | Aurornis wrote:
             | > if the ecosystem keeps on trying to download 3Gb of build
             | dependencies because you tried to use some simple little
             | library.
             | 
             | Downloading 3GB of dependencies is not a thing that happens
             | in the Rust ecosystem. Reality is orders of magnitude
             | smaller than that. Why are you exaggerating so much?
             | 
             | Some people bristle at the thought of external
             | dependencies, but if you want to do common tasks it makes
             | sense to pull in common dependencies. That's life.
        
               | gregors wrote:
               | Maybe they meant node_modules as the joke goes.
        
               | nindalf wrote:
               | I think it was a false equivalence between node_modules
               | and Rust. Like any language where developers rely on a
               | package manager to pull in libraries will necessarily be
               | 3GB in size.
        
               | Narishma wrote:
               | The download size may not be a big issue, but all those
               | dependencies take up a lot of storage space once they're
               | compiled.
        
               | bscphil wrote:
               | > Downloading 3GB of dependencies is not a thing that
               | happens in the Rust ecosystem. Reality is orders of
               | magnitude smaller than that.
               | 
               | Assuming they're talking about the built size of
               | dependencies that are left lying around after cargo
               | builds a binary, they're really not exaggerating by much.
               | I have no difficulty of believing that there are Rust
               | projects that leave 3GB+ of dependency bloat on your file
               | system after you build them.
               | 
               | To take the last Rust project I built, magic-wormhole.rs
               | [1], the source code I downloaded from Github was 1.6 MB.
               | After running `cargo build --release`, the build
               | directory is now 618 MB and there's another 179 MB in
               | ~/.cargo, for a total of 800 MB used.
               | 
               | All this to build a little command line program that
               | sends and receives files over the network over a simple
               | protocol (build size 14 MB). God forbid I build something
               | actually complicated written in Rust, like a text editor.
               | 
               | [1] https://github.com/magic-wormhole/magic-wormhole.rs
        
             | surajrmal wrote:
             | It's not a problem when you compare it to C. You have few
             | available dependencies to choose from with C. If you are
             | equally picky and constrain yourself to parts of the
             | ecosystem which care about binary size, you still have more
             | options and can avoid size issues.
             | 
             | For things like a kernel, it is moot as most deps are
             | simply not possible to use anyway.
             | 
             | When you consider the full ecosystem, you need to really
             | compare it to alternatives in largely managed languages
             | like Java, go, node, etc. those binaries are far larger.
        
               | bscphil wrote:
               | > If you are equally picky and constrain yourself to
               | parts of the ecosystem which care about binary size, you
               | still have more options and can avoid size issues.
               | 
               | What's an example of this for, say, libcurl? On my system
               | it has a tiny number of recursive dependencies, around a
               | dozen. [0] Furthermore if I want to write a C program
               | that uses libcurl I have to download zero bytes of data
               | ... because it's a shared library that is already
               | installed on my system, since so many programs already
               | use it.
               | 
               | I don't really know the appropriate comparison for Rust.
               | reqwest seems roughly comparable, but it's an _HTTP_
               | client library, and not a general purpose network client
               | like curl. Obviously curl can do a lot more. Even the
               | list of _direct_ dependencies for reqwest is quite long
               | [1], and it 's built on top of another http library [2]
               | that has its own long list of dependencies, a list that
               | includes tokio, no small library itself.
               | 
               | In terms of final binary size, the _installed_ size of
               | the curl package on my system, which includes both the
               | command line tool and development dependencies for
               | libcurl, is 1875.03 KiB.
               | 
               | [0] I'm excluding the dependency on the ca-certificates
               | package, since this only provides the certificate chain
               | for TLS and lots of programs rely on it.
               | 
               | [1] https://crates.io/crates/reqwest/0.11.24/dependencies
               | 
               | [2] https://crates.io/crates/hyper/0.14.28/dependencies
        
           | wongarsu wrote:
           | If you do release builds, strip debug symbols and turn LTO
           | from thin to full, do dependencies and the static stdlib
           | still matter? You should be only paying for code that's
           | called at that point.
           | 
           | At that point I suspect the biggest culprits are overuse of
           | monomorphisation, and often just more stuff happening
           | compared to equivalent C++ code because the language makes
           | larger code bases more maintainable. I'd also count some
           | niceties in that category like better string formatting or
           | panic handling, which is an insignificant cost in any larger
           | software but appears big in tiny hello-world type programs.
        
             | surajrmal wrote:
             | Overuse of monorphisation by the community is typically the
             | right choice given the average use case for them is servers
             | where this need not make a meaningful difference. As with
             | any ecosystem, choices folks make may not be suitable for
             | everyone. Those differing requirements require fracturing
             | into smaller ecosystems which share common requirements.
             | Ultimately, that's what's happening with rust and it's very
             | healthy to see in my opinion. You can't force the overall
             | ecosystem to optimize for a minority of users.
             | 
             | This is also true for everything in general. Having the one
             | best thing for foo isn't as helpful as an array of choices,
             | each with different tradeoffs. You simply choose the one
             | best for your needs. Whether it's cheese at the
             | supermarket, an webserver framework, operating system
             | intrinsics, or command line argument handling. Some things
             | can be standardized and serve as a common base for
             | everyone, but it's challenging to do that without at least
             | one person's requirements. Standards also always feature
             | creep until someone tries to reset it with a new standard
             | which is less complex, but I guess that's a different
             | topic.
        
               | tialaramex wrote:
               | I believe the menu of options is _undesirable_ until you
               | actually know you have requirements you can evaluate them
               | against. As much as possible even if I do _have_ a
               | choice, there should be a default and I needn 't be
               | asked. When I make a Rust project, cargo notices I have
               | git and, since I didn't say otherwise, it mints a Git
               | repo for the new project automatically. It doesn't insist
               | on asking if I want one, and then asking if it should
               | have the obvious name, and then asking if it should use
               | my default local git settings, the defaults for all of
               | these are IMNSHO obvious and my tacit approval via not
               | having explicitly turned this off is enough.
               | 
               | Do you want a Doodad, a Gooba or a Wumsy? No idea? Me
               | either. So until I care, I'd rather not be asked to
               | choose. But once I discover that I need something with at
               | least 40% Flounce, I can see that Doodads and Goobas both
               | are rated at 50% Flounce, whereas Wumsy has only 10%
               | Flounce, now we're making an informed choice, it should
               | be easy enough to insist on a Doodad to meet my
               | requirement.
               | 
               | If I measure that Monomorphization is out of hand in my
               | codebase I can use dyn to get that back under control for
               | a fair price, but I think the default here is sound.
        
               | fl0ki wrote:
               | I agree, but I have yet to see a single real-world
               | example of a Rust project meaningfully reducing its
               | binary size by switching from monomorphization to dynamic
               | dispatch in its own code. Many Rust developers boast that
               | they virtually never use `dyn`, but then still appeal to
               | it when arguing that Rust has dynamic dispatch so
               | monomorphization is an avoidable cost.
               | 
               | Sometimes you can provide `T = Arc/Box<dyn Foo>` where
               | `T: Foo` is required, but only if the trait is designed
               | to be object-safe, not simply by default. If you get to
               | design the trait and all of its consumers yourself, you
               | might have this option, but it's very possible that
               | you're using a library that does not make this possible.
               | You can easily be the first person to bother trying the
               | `dyn` for a trait and running into these limitations.
               | 
               | Besides that, you might not even have that much control
               | of the concrete type used. For example, if you are
               | generating large schemas with serde, serde decides how
               | that code is monomorphized, not you. In contrast, for
               | better or worse, the path of least resistance in Go is to
               | use a reflection-based serialization framework which has
               | notable runtime costs (that may or may not matter to a
               | given project) but successfully avoids compile time and
               | binary size costs. (There are other reasons that Go
               | binaries end up even larger than Rust ones, this just
               | isn't one of them)
               | 
               | Despite Rust's general principle of giving its users
               | informed choices here, I am not aware of any option that
               | does 100% dynamic dispatch for (de)serialization, so in
               | practice this is a largely unavoidable cost in each
               | project that is decided only by how complex the schema
               | is.
               | 
               | It's also only fair to point out that C++ tends to end up
               | in this place too, mitigated only by dynamic linking and
               | not any magical property of the language itself. Even C
               | can head this way because monomorphizing with macros has
               | the same effect, though due to how such code is
               | structured, it's also less likely to be inlined than C++
               | or Rust.
        
               | tialaramex wrote:
               | That's a fair observation, I know when I was first
               | writing Rust my inclination was to return impl
               | IntoIterator<Item = T> from functions which are going to
               | actually return a Vec<T> because hey, if I change my mind
               | you can still iterate over whatever I give you now
               | instead with no code changes.
               | 
               | But of course that's an anti-pattern because they are in
               | reality likely to forever just return Vec<T> and knowing
               | that helps you. My early choice only makes sense if
               | either I can't tell you anything more specific than impl
               | IntoIterator<Item = T> or I already know I intend to make
               | a change later. So these days I almost always write down
               | what exactly is returned unless either I can't name it or
               | no reasonable person would care.
               | 
               | For serde in particular my guess is that if you need lots
               | of dynamism serde is the wrong approach even though it's
               | popular. It might be interesting to build a different
               | project which focuses on dynamic dispatch for the same
               | work and tries to re-use as much of the serde eco-system
               | as possible. Not work which attracts me though.
        
         | Aurornis wrote:
         | > One issues I have had with Rust applications is the huge
         | binary size
         | 
         | Turn off the standard library and your binaries can be
         | incredibly small. This is how it's used in microcontrollers and
         | the Linux Kernel doesn't use the full standard library either.
        
           | nequo wrote:
           | Due to dead code elimination, the compiler already omits all
           | of that part of stdlib that your code doesn't use.
        
             | pornel wrote:
             | Not quite. Every Rust program will have some code path that
             | may panic, and the default panic handler uses debug
             | formatting, which uses dynamic dispatch, which prevents
             | elimination of the rest of the printing machinery.
             | 
             | There's panic_immediate_abort unstable setting that makes
             | Rust panics crash as hard as a C segfault, and only then
             | you can get rid of a good chunk of stdlib.
        
               | nequo wrote:
               | Does this mean that only the printing machinery is not
               | eliminated or that other parts of stdlib are present in
               | the binary too even though unused?
        
               | fl0ki wrote:
               | The printing machinery alone is quite large when you
               | consider that it includes the code & raw data for
               | Unicode, whether or not similar facilities were already
               | available on the host libc. Though you're not likely to
               | avoid that in any non-trivial Rust program anyway, as
               | even a pretty barebones CLI will need Unicode-aware
               | string processing.
               | 
               | I generally find Rust binaries to be "a few" megabytes if
               | they don't have an async runtime, and a few more if they
               | do. It has never bothered me on an individual program
               | basis, but I can imagine it adding up over an entire
               | distribution with hundreds of individual binaries. I see
               | the very real concern there, but personally I would still
               | not risk ABI hazards just to save on space.
        
               | bpye wrote:
               | The printing machinery is quite unfortunate. Beyond being
               | large, dynamic dispatch makes any attempt at stack size
               | analysis much harder.
               | 
               | I've used Rust for some embedded side projects and I
               | really wish there was a way to just get some unique
               | identifier that I could translate (using debug symbols)
               | to a filename and line number for a crash. This would
               | sort of be possible if you could get the compiler to put
               | the filenames in a different binary section, as you could
               | then just save the address of the string and strip out
               | the actual strings - but today that's not possible.
        
         | mcqueenjordan wrote:
         | Another thing just to mention here is `strip`, which IIRC
         | `cargo build --release` doesn't do by default. I think
         | `stripping` binaries can reduce binary size by up to 80-85% in
         | some cases (but certainly not all; just tried it locally on a
         | 1M rust binary and got 40% reduction).
         | 
         | FWIW, you can configure this in Cargo.toml:
         | 
         | [profile.release] strip = true
        
           | habibur wrote:
           | You can strip C compiled binaries too. And that halves the
           | binary size. The point is for example a hello world Rust
           | binaries is 300kb after striping while C compiled one is
           | 15kb. A difference of 20 times.
        
             | pornel wrote:
             | Such comparison exaggerates the difference, because it's a
             | one-time constant overhead, not a multiplicative overhead.
             | 
             | i.e. all programs are larger by 275KB, not larger by 20x.
             | 
             | Rust doesn't have the privilege of having a system-wide
             | shared stdlib to make hello world executables equally
             | small.
             | 
             | The overhead comes from Rust having more complex type-safe
             | printf, and error handling code for when the print fails. C
             | doesn't handle the print error, and C doesn't print stack
             | traces on error. Most of that 200KB Rust overhead is a
             | parser for dwarf debug info to print the stack trace.
        
             | Narishma wrote:
             | But C doesn't statically link the standard library by
             | default like Rust does.
        
               | habibur wrote:
               | Hello world deps for C :                   linux-
               | vdso.so.1 (0x00007fff25cb8000)         libc.so.6 =>
               | /lib64/libc.so.6 (0x00007fe5f08d9000)         /lib64/ld-
               | linux-x86-64.so.2 (0x00007fe5f0ae2000)
               | 
               | And for Rust                   linux-vdso.so.1
               | (0x00007ffc109f9000)         libgcc_s.so.1 =>
               | /lib64/libgcc_s.so.1 (0x00007f8eda404000)
               | libc.so.6 => /lib64/libc.so.6 (0x00007f8eda222000)
               | /lib64/ld-linux-x86-64.so.2 (0x00007f8eda4a8000)
               | 
               | Rather Rust has 1 more dynamically linked library than C.
        
               | fl0ki wrote:
               | That might be true for Hello World, but libgcc_s is where
               | a lot of builtins for C itself go, so you'll find it ends
               | up linked into a lot of non-trivial C programs as well.
               | See https://gcc.gnu.org/onlinedocs/gccint/Libgcc.html
        
               | Kamq wrote:
               | You missed the word "statically" in the post you
               | commented on.
               | 
               | Dynamically linked libs rarely contribute heavily to
               | binary bloat
        
             | estebank wrote:
             | You might be interested in reading
             | https://darkcoding.net/software/a-very-small-rust-binary-
             | ind...
        
           | nindalf wrote:
           | Check out Making Rust binaries smaller by default
           | (https://kobzol.github.io/rust/cargo/2024/01/23/making-
           | rust-b...). Previously discussed a few weeks ago at
           | https://news.ycombinator.com/item?id=39112486.
           | 
           | That change will be live on 21st March, so manual strips
           | won't be required after that.
        
         | bluejekyll wrote:
         | This is a good guide on building small Rust binaries:
         | https://github.com/johnthagen/min-sized-rust
         | 
         | This talks about going to extreme lengths on making the
         | smallest Rust binary possible, 400 bytes when it was written,
         | https://darkcoding.net/software/a-very-small-rust-binary-ind...
         | 
         | The thing is, you lose a lot of nice features when you do this,
         | like panic unwinding, debug symbols, stdlib... for kernel and
         | some embedded development it's definitely important, but for
         | most use cases, does it matter?
        
           | ericbarrett wrote:
           | > debug symbols
           | 
           | In ye olden days it was common to distribute a binary without
           | debug symbols, but to keep a copy of them for every released
           | build1. If an application crashed (panicked, signalled, etc.)
           | you got a core dump that you could debug using the stripped
           | binary together with the symbol file. This gave you both
           | smaller binary sizes and full debugging capability at the
           | cost of some extra administration. I'm not sure if this is
           | possible with "stock" Rust, but if you need lean binaries but
           | want to do forensic investigation it's something to look
           | into.
           | 
           | 1. https://sourceware.org/gdb/current/onlinedocs/gdb.html/Sep
           | ar...
        
             | wongarsu wrote:
             | It's possible, but rust follows platform conventions in
             | only doing this by default on Windows. However it is now
             | easy to configure by setting split-debuginfo in your
             | Cargo.toml [1]
             | 
             | 1: https://doc.rust-
             | lang.org/cargo/reference/profiles.html#spli...
        
         | carterschonwald wrote:
         | So one issue I can imagine being the culprit with rust is the
         | specializing / c++ style semantics of rust generics. C code
         | generics tend to be void* flavored or point to a struct of
         | function pointers. Which will generate less code. Not sure how
         | this translates to the kernel setting thoughb
        
           | pornel wrote:
           | That is true. Rust makes it easy to overuse monomorphisation.
           | There are tools like `cargo-bloat` that find these.
           | 
           | However, most complaints are about size of "Hello World",
           | which in Rust is due to libstd always having debug info (to
           | be fixed soon), and panic handling code that includes
           | backtrace printing (because print to stdout can fail).
           | 
           | Printing of backtrace is very bloaty, because it parses and
           | decompresses debug info.
        
         | loeg wrote:
         | Are you talking about https://github.com/rust-lang/compiler-
         | team/issues/688 ? I think that issue provides a lot of
         | interesting context for this specific improvement.
        
         | forrestthewoods wrote:
         | > is the huge binary size
         | 
         | Can you quantify this? How big is too big? Ideally for a real
         | program, and not an experiment to make the tiniest possible
         | program.
         | 
         | On my Windows machine ripgrep rg.exe is just 4.2mb. Making that
         | smaller feels irrelevant.
         | 
         | I'm not convinced that binary size is a real problem. But I'm
         | open to evidence!
        
           | cout wrote:
           | It would be nice if it fit on a standard size 1.44MB floppy,
           | but given that I haven't used a floppy drive in about a
           | decade, yeah I guess it doesn't matter much.
        
             | raoulkent wrote:
             | Just out of interest, what kind of systems do you work on
             | if you've been using floppy discs in the last 25+ years?
        
       | bsd_source wrote:
       | Rust is going to kill LFS
        
         | horeszko wrote:
         | LFS is Linux from Scratch right?
         | (https://www.linuxfromscratch.org/index.html)
         | 
         | What are the implications of using Rust on building Linux?
        
           | rekado wrote:
           | The Rust bootstrapping story is ugly.
           | 
           | https://guix.gnu.org/blog/2018/bootstrapping-rust/
        
             | charcircuit wrote:
             | LFS does not need to do all of that. LFS already uses the
             | host computer's C compiler, so it seems just as reasonable
             | to also use the host computer's rust compiler.
        
         | ta8645 wrote:
         | Surely LFS will survive? Might need to update a few steps is
         | all.
        
           | twosdai wrote:
           | Change? Impossible. This is software after all. It never
           | changes. /s
        
         | 1letterunixname wrote:
         | Explain because I don't see that happening.
        
       | amelius wrote:
       | How many % of the kernel is Rust now, in terms of LoC?
        
         | rwmj wrote:
         | Rust: 20,887 lines
         | 
         | C: 33,351,596 lines
         | 
         | (That's just doing 'wc -l' rather than using any proper code
         | metrics tool)
        
           | amelius wrote:
           | Ok. Does that include device drivers?
        
             | izacus wrote:
             | Yes.
        
           | geertj wrote:
           | How much of those 20K lines are Rust infrastructure, versus
           | drivers written in Rust?
        
             | bonzini wrote:
             | The latter are basically a rounding error, though there is
             | a rewrite of the Android binder driver.
        
         | antoinealb wrote:
         | At least according to the Github's language breakdown for
         | https://github.com/Rust-for-Linux/linux, C is still 98.3% of
         | the repository, and Rust is in the 0.1% of "others".
        
       | loeg wrote:
       | So this is a huge tangent but couldn't most of the uses of the
       | non_null!() macro in this diff just be (safe!) pointer
       | comparisons or subtractions, without the unsafe{} logic to
       | convert a pointer value to a reference just for the purposes of
       | comparison or subtraction?
       | https://lore.kernel.org/lkml/20240217002717.57507-1-ojeda@ke...
        
         | saghm wrote:
         | Although I think I recall that the kernel doesn't use Rust's
         | standard library (which is consistent with the diff you
         | linked), it's possible that the standard library's
         | documentation on the pointer subtraction might reference a
         | concern they could share (https://doc.rust-
         | lang.org/std/primitive.pointer.html#method....):
         | 
         | > If any of the following conditions are violated, the result
         | is Undefined Behavior:
         | 
         | > * Both the starting and resulting pointer must be either in
         | bounds or one byte past the end of the same allocated object.
         | 
         | > * The computed offset cannot exceed isize::MAX bytes.
         | 
         | > * The offset being in bounds cannot rely on "wrapping around"
         | the address space. That is, the infinite-precision sum must fit
         | in a usize.
         | 
         | > Most platforms fundamentally can't even construct such an
         | allocation. For instance, no known 64-bit platform can ever
         | serve a request for 263 bytes due to page-table limitations or
         | splitting the address space. However, some 32-bit and 16-bit
         | platforms may successfully serve a request for more than
         | isize::MAX bytes with things like Physical Address Extension.
         | As such, memory acquired directly from allocators or memory
         | mapped files may be too large to handle with this function.
         | 
         | > Consider using wrapping_sub instead if these constraints are
         | difficult to satisfy. The only advantage of this method is that
         | it enables more aggressive compiler optimizations.
         | 
         | If their pointer subtraction uses similar semantics, there
         | might be issues if they want to compare pointers from different
         | allocation objects, are worried about 32-bit or 16-bit
         | platforms, or maybe even consider the performance concerns too
         | worrisome. The Rust I write tends to be a bit higher-level and
         | doesn't require unsafe, so my instinctual reaction to "using
         | unsafe for performance" generally errs on the same of abject
         | terror, but it's a fundamental part of what makes the safe side
         | of abstractions I use possible, and the kernel is probably one
         | of those places that needs to do that sometimes, so I'd
         | reluctantly have to admit I'm probably not qualified to
         | evaluate whether these cases would merit unsafety for
         | performance alone, but the first two concerns sound like
         | legitimate things that the kernel would need to handle.
        
           | loeg wrote:
           | > If their pointer subtraction uses similar semantics, there
           | might be issues if they want to compare pointers from
           | different allocation objects, are worried about 32-bit or
           | 16-bit platforms, or maybe even consider the performance
           | concerns too worrisome.
           | 
           | Any of these type of issue would equally invalidate using
           | unsafe{} to cast the pointer to a reference, which is what
           | non_null! does.
        
           | tialaramex wrote:
           | > Although I think I recall that the kernel doesn't use
           | Rust's standard library
           | 
           | Rust's standard library has three elements
           | 
           |  _core_ has stuff you get with the Rust language, like any
           | use of Rust, Rust for Linux has core. You could _technically_
           | implement Rust without core, or at least, without most of it,
           | but that 's not really the Rust language, you've instead made
           | your own weird fork.
           | 
           | [T]::sort_unstable() is a core function which sorts a slice
           | of some Ordered type T but may re-arrange elements despite
           | them comparing equal hence the word "unstable".
           | 
           |  _alloc_ depends on an allocator. You may not have an
           | allocator, e.g. you 're a tiny embedded controller, in which
           | case you likely don't want and can't use this. Rust for Linux
           | re-implements alloc, basically cloning the "official" alloc
           | and fiddling with it.
           | 
           | Vec::try_reserve() is a feature found in alloc, it tries to
           | allocate enough space to ensure your Vec has a certain amount
           | of capacity beyond its current size, and if not reports it
           | could not.
           | 
           |  _std_ further depends on an Operating System, it offers
           | exciting features like knowing what the time is, reading a
           | file, connecting to a remote service over TCP /IP, or making
           | a thread. Rust for Linux does not provide std.
           | 
           | File::create() is a std function which creates files.
           | 
           | The function you were interested in is part of core (although
           | you were looking at its re-export from std) and so yes, it
           | exists in Rust for Linux.
        
       | 1letterunixname wrote:
       | My wishlist would include gradually refactoring core in Rust and
       | formal verification a-la seL4 to prove correctness. There's no
       | point to refactor churn from one language religion to another for
       | low entropy, core code without improvements in assurance that
       | it's also provably bug-free, race-free, and secure while also
       | being as fast or possibly faster.
        
       ___________________________________________________________________
       (page generated 2024-02-18 23:01 UTC)