Remix.run Logo
▲ Eridrus 4 hours ago

What do you think the most impactful savings from hand-written assembly are over optimized Rust today?

▲jcranmer 3 hours ago | parent | next [-]

An optimizer is trying to balance between compile time, runtime speed, and code size, and most optimizations will win you one axis at the cost of one or both of the other axes. (The rare optimizations that win on all 3 are already all implemented in the compiler.) Compiler developer time is also a scarce resource; I know of so many more optimizations I could implement, but without demonstrable code that would actually benefit, it's not a good use of my time to implement them. Compilers tune this balance by making lots of heuristic decisions, and these heuristics are tuned by large benchmarks, which often times involve a lot of flat code profiles (i.e., no code is worth spending a lot of time really nailing down the best code layout).

One of the advantages of hand-written assembly is that you get to opt out of the compiler heuristics and commit to being able to spend the time to optimize the one bit of code that you know is really important for runtime as perfectly as you want, instead of relying on the compiler to get it close enough to perfect before it exhausts its budget of caring about optimizing it.

▲Pannoniae 3 hours ago | parent | prev | next [-]

1. Better memory locality by knowing what you load and when, exactly.

2. The ability to "cheat" on calling conventions.

3. The ability for techniques like threaded code, and in general, better cache-awareness.

4. Less mov's.

5. Guaranteeing no spilling in important loops.

6. Compilers don't do well with flags registers and you can't read/write them in high level languages. You're hoping your `if (result < a) { carry = 1; }` becomes a direct flag test. Especially important in bignum, you can't really utilise adcx/adox directly from high-level code.

7. Hot/cold layout without PGO. Yes PGO is good but sometimes you know better and PGO isn't very suitable for "configurable" code.

8. Computed goto. See https://github.com/python/cpython/issues/128563 , who doesn't like 10% free performance?

9. Exploiting uninitialised memory for classic party tricks like not initialising a buffer fully (let's say you have a library function with a return buffer. You don't want dynamic allocations for some reason. You can simulate this with a pointer return into a let's say a static 4KB buffer and a count return, you only initialise it until the count. Caller has the responsibility not to overread.)

▲steveklabnik 3 hours ago | parent | prev | next [-]

usually with Rust impactful savings come from writing the Rust differently, not from doing hand-written assembly instead.

See stuff like https://davidlattimore.github.io/posts/2025/09/02/rustforge-...

This doesn't mean Rust is near perfect, it's just that your first move should be "how do I make the Rust better" and not "I need to drop into asm."

▲Pannoniae 3 hours ago | parent [-]

"We’d like to initialise our Vec in parallel, otherwise we’d have to wait for the main thread to fill the entire Vec with a placeholder value only to then have our threads overwrite those placeholder values."

Talk about overengineering :P Multithreaded vector initialisation instead of just...skipping it?

▲steveklabnik 2 hours ago | parent [-]

That sentence is specifically talking about not initializing with a placeholder value, and instead letting it write over uninitialized values.

▲newpavlov 3 hours ago | parent | prev | next [-]

As one example, LLVM still routinely does dumb stuff like this: https://github.com/llvm/llvm-project/issues/53348

Regarding ABI, calee-saved registers also often result in useless data shuffling and prevent the compiler from using them for argument/result passing.

▲compiler-guy 4 hours ago | parent | prev | next [-]

Entirely situation and application specific. Just like with every other language.

▲Eridrus 4 hours ago | parent [-]

So there's no patterns at all?

▲compiler-guy 3 hours ago | parent [-]

I'm so far downstream from the source language that I know of none specific to Rust. And note someone else's specific answer to your question above that has nothing Rust specific either.

▲BiscuitBadger 3 hours ago | parent | prev [-]

Any “Multimedia Extensions” or streaming or whatever beyond what’s available past a 486.

Rust has autovectorization, but a developer knows their algorithms best.

Also AES-NI vs software is no contest.

When people talk about out coding ‘to the metal’ you have to consider what ‘the metal’ provides