News for hackers. Stuff that matters.
Re:Why does musl make my Rust code so slow? (2020) by croemer on Tuesday December 12, 2023 @04:35PM (#38618927)
This recent blog post explains what happened here: https://www.tweag.io/blog/2023-08-10-rust-static-link-with-m...

"When it comes to musl, there’s a certain performance trap: its allocator does not perform well in multi-core environments."

"A common cause of the above symptom is thread contention: multiple threads are fighting to acquire the same resource instead of doing useful work. Although it’s better than deadlock or livelock, since the application runs to completion, it’s still a significant waste of CPU."

"The real source of thread contention is in the malloc implementation of musl. A malloc implementation must be thread-safe, as multiple threads may allocate memory at once or even free memory allocated in other threads. Thus, the thread synchronization logic could become a bottleneck.

Although I have not deep-dived into the musl malloc codebase to locate the contention, replacing it with a cutting-edge malloc implementation like mimalloc is sufficient to rectify the problem and enhance performance. Mimalloc minimizes contention and enhances multi-threaded performance. In fact, this replacement can make the application run even faster than the default glibc build."

Re:Why does musl make my Rust code so slow? (2020) by kragen on Tuesday December 12, 2023 @05:28PM (#38619599)
per-thread malloc pools are probably enough to solve this problem and are probably only a few dozen lines of code? i haven't written one so i could be wrong, but it sounds like it might be an acceptable fix to musl
Re:Why does musl make my Rust code so slow? (2020) by mperham on Tuesday December 12, 2023 @05:57PM (#38619960)
> probably only a few dozen lines of code

Classic HN.

Re:Why does musl make my Rust code so slow? (2020) by kragen on Tuesday December 12, 2023 @06:33PM (#38620357)
i'm guessing you haven't done it either, so you don't have any basis for guessing whether that's an underestimate or an overestimate

'classic hn' in the negative sense is a one-line dismissal containing no reasoning or information. do better

Re:Why does musl make my Rust code so slow? (2020) by techbrovanguard on Tuesday December 12, 2023 @08:00PM (#38621238)
hi, i’m _reasonably_ familiar with libcs, specifically glibc and musl. even a cursory investigation would reveal how involved these things are. classic hn.

do better.

Re:Why does musl make my Rust code so slow? (2020) by kragen on Tuesday December 12, 2023 @08:18PM (#38621395)
you can of course make malloc arbitrarily complex, and a simple malloc will not be very efficient, but musl's entire malloc/free implementation is only 600 lines of c (`cloc musl-1.1.24/src/malloc`) and even a fair bit of that is no longer actually used (`#if 1 ... #else ... #endif`)

so i don't think a cursory investigation supports your vague innuendo, which seems to be implying that adding thread-local allocation pools to musl would require enormously more than 'a few dozen lines of code', as i said. the entire allocator is 50 dozen lines

the code isn't 'involved'; it's nice and straightforward, except for a clever algorithm or two from hacker's delight. what's involved is debugging it when you break it

Re:Why does musl make my Rust code so slow? (2020) by intelVISA on Wednesday December 13, 2023 @07:53AM (#38626624)
Most Good Things are a few dozen lines of code, don't let the Scrum Master fool you.
Re:Why does musl make my Rust code so slow? (2020) by pcwalton on Wednesday December 13, 2023 @01:05AM (#38623306)
It's not a few dozen lines of code because of, among other things, the case in which one thread allocates a lot of memory that is then sent to another thread to be freed. This actually happens more frequently than you'd think, because of producer/consumer patterns. In that case stop-the-world synchronization must happen in order to re-balance the pools in order to avoid what are essentially memory leaks. This is complex and is actually fairly similar to garbage collection.
Re:Why does musl make my Rust code so slow? (2020) by kragen on Wednesday December 13, 2023 @02:04AM (#38623649)
aha, thanks. it's true that i was thinking that just adding it to the receiver thread's pool would be sufficient
Re:Why does musl make my Rust code so slow? (2020) by returningfory2 on Tuesday December 12, 2023 @02:29PM (#38617113)
Minimizing Docker image size is my favorite premature optimization.

In most cases it's not even an optimization! Docker's layered caching means the most relevant size is the diff between the base image and the final image. This is generally independent of which base image you use.

It has a bunch of negative consequences like in this blog post.

It's something that many people new to Docker feel they should be doing, so you see it a lot.

Just an all-round great premature optimization.

Re:Why does musl make my Rust code so slow? (2020) by maxmcd on Tuesday December 12, 2023 @02:52PM (#38617467)
Maybe "picking alpine images because they are small without thinking deeply about it" is the mistake here?

Debian images can end up using a lot of apt-get tricks to install dependencies cleanly. Way easier with alpine. I think there are plenty of reasons people are quick to make this decision without the necessary depth of investigation.

Minimizing docker image size is great. Cold starts with large image downloads can cause all sorts of fun issues. Yes, if you're shipping lots of dependencies in your containers the size of the base image can quickly be irrelevant. And yes, I think it is usually reached for prematurely, but the benefits are there for the few that need them.

Re:Why does musl make my Rust code so slow? (2020) by sshine on Tuesday December 12, 2023 @02:47PM (#38617373)
I deploy Docker images on a lot of small devices with sketchy internet connections.

During development, it really does matter if my images are 4MB or 80MB.

Just like when compilation times and tests start growing in the minutes, my feedback cycle is broken.

I also compile Rust statically to musl, so I'll seriously consider building the final image on the device to avoid copying the base image during deployment. Or ditch Docker entirely.

Re:Why does musl make my Rust code so slow? (2020) by returningfory2 on Tuesday December 12, 2023 @04:16PM (#38618672)
My initial suspension is that this falls into the "In most cases it's not even an optimization" case, but do correct me if I'm wrong.

When you create a new Docker image with a recompiled Rust binary, only the last Docker layer will need to be downloaded to the device. Incremental caching means Docker won't re-download the base layer. The last layer is basically the new binary itself. So I don't see how it would be slower than copying the raw binary. But maybe I'm missing something.

Re:Why does musl make my Rust code so slow? (2020) by Xelynega on Tuesday December 12, 2023 @02:53PM (#38617493)
Isn't their point that docker brought incrementalness to this?

So just like when you change one c file you don't have to recompile the whole project, updating the last layer in the image should only require a few mb of transfer, the base layers would only be transfered once.

Re:Why does musl make my Rust code so slow? (2020) by egnehots on Tuesday December 12, 2023 @02:53PM (#38617491)
Yes, but on the other hand, people who don't care can create huge images (especially in Node.js and Java ecosystems) that slow down CI and have a large attack surface.
Re:Why does musl make my Rust code so slow? (2020) by eikenberry on Tuesday December 12, 2023 @04:49PM (#38619134)
You don't use Alpine because it is the smallest anymore, but because it has the best package repo. It beats the big 2 (and Nix), Fedora and Debian, in terms of package coverage and being kept up to date. At least in all my testing.

I don't think it is a premature optimization anymore, it has become the best practice by default. The network effect at work.

Re:Why does musl make my Rust code so slow? (2020) by amarshall on Tuesday December 12, 2023 @05:07PM (#38619352)
Newness is at best only partly true. As far as total packages go, Alpine definitely loses to all three in your cohort. No need to guess, plenty of statistics at https://repology.org/repositories/statistics
Re:Why does musl make my Rust code so slow? (2020) by eikenberry on Tuesday December 12, 2023 @06:02PM (#38620017)
2 points in relation to those numbers. First is that distro's don't package things the same way. Debian is most famous example for how they break up packages into many smaller ones compared to the other distros. Ie. comparing raw numbers doesn't work exactly. Secondly we are talking about packages that are used in Docker images, a definite subset of those for general purpose distros. I've always found Alpine to beat the other distros packages on these terms.
Re:Why does musl make my Rust code so slow? (2020) by amarshall on Tuesday December 12, 2023 @06:47PM (#38620518)
Indeed it’s not perfect. But relying on one anecdote is not better, either. Further, it’s difficult to justify the claim that Alpine has more packages than nixpkgs when the raw numbers are >7x the other way.
Re:Why does musl make my Rust code so slow? (2020) by eikenberry on Wednesday December 13, 2023 @04:01PM (#38634086)
Anecdotes are also known as experience and this wasn't part of a scientific paper, it was an expression of my personal experiences using these tools. My most recent test of this was working on a container based setup for writing software and tracking the tools I needed across fedora, debian, nix and alpine. Alpine was the only one that had full coverage and kept up with versions appropriate for the use case. Other cases (more hosting oriented) were longer ago and may not be valid these days, but had similar results at the time (though not nix, it wasn't a contender back then).
Re:Why does musl make my Rust code so slow? (2020) by whoopdedo on Tuesday December 12, 2023 @04:56PM (#38619226)
It has to do that because upstream software won't have Alpine-specific build pipelines. (Though I expect a lot more do nowadays.) Meanwhile everyone tests on Fedora, Debian, and Ubuntu so if it isn't in the distribution repository, or the version isn't up-to-date, it's as simple as having your Dockerfile fetch and build from upstream.
Re:Why does musl make my Rust code so slow? (2020) by zzyzxd on Tuesday December 12, 2023 @08:32PM (#38621510)
I still like minimizing container image sizes for the security and performance benefits. It's just not a strong enough reason to choose a different linux distro for your production environment. In other words, switching to alpine is the wrong approach to achieve smaller image sizes.

Unlike the early days of Docker, today you see popular distros provides multiple official image flavors depends on how minimal you are comfortable with. Or you can go even further with things like Google distroless, or even just scratch. I rarely see negative consequences when it's done appropriately. In fact, we see a lot of benefits by doing this. for instance, developers now understand their own app's dependencies much better ("oh your python app is having a cert error? does it come with its own cert bundle, use 3rd party package like certifi, ca-certificates from OS package manager, or a combination of some of them?" It's much easier to answer this question now than before)

Package only the stuff your app needs.

Re:Why does musl make my Rust code so slow? (2020) by zX41ZdbW on Tuesday December 12, 2023 @02:58PM (#38617550)
It is the case when you use a default malloc, default memcpy, or default string functions from libc.

In ClickHouse, we use jemalloc as a memory allocator and custom memcpy: https://github.com/ClickHouse/ClickHouse/blob/master/base/gl...

So, the Musl build does not imply performance degradations. But the usage of Musl is not related to Docker, because ClickHouse is a single self-contained binary anyway, and it is easy to use without Docker.

Re:Why does musl make my Rust code so slow? (2020) by MuffinFlavored on Tuesday December 12, 2023 @04:52PM (#38619175)
Fantasy land: it'd be cool if something like this got upstreamed into stdlib/libc repos as like "fast_memcpy" (I'm guessing it's too not-backwards-compatible enough to make it the default) so large powerful big players don't all have their own "slighty-non-standard" way of doing this?
Re:Why does musl make my Rust code so slow? (2020) by Ericson2314 on Tuesday December 12, 2023 @04:42PM (#38619022)
libc is a bad idea. Deciding the default allocator how to talk to the kernel should be provided by the same library is a bad.

Musl should be able to exist without providing any allocator.

Re:Why does musl make my Rust code so slow? (2020) by sidkshatriya on Tuesday December 12, 2023 @05:15PM (#38619438)
You can use other allocators with musl. For example in Chimera Linux, musl uses the llvm scudo allocator instead of the default allocator packaged with musl libc.
Re:Why does musl make my Rust code so slow? (2020) by Ericson2314 on Tuesday December 12, 2023 @11:54PM (#38622829)
Yes and that's good, but it should be even easier. Rather than every libc needing to invent how to make the allocator pluggable, we should have that separation of concerns stock and shared by all implementations.
Re:Why does musl make my Rust code so slow? (2020) by q66 on Wednesday December 13, 2023 @11:10AM (#38629463)
the above is incorrect, chimera does use scudo but it patches musl to achieve that

and scudo is probably one of the few allocators that would work for this purpose, it absolutely cannot be applied to any allocator; there are some concerns that get in the way of that, e.g. the handling of ELF TLS in a libc (ELF TLS may not be and in musl's case is not available within the dynamic linker, which means you cannot use __thread and the likes anywhere within libc.so; scudo is designed to be flexible so you can get around it (we shove a pointer to the thread-local state directly in the pthread structure and manually mmap the data for it) but that is not necessarily the case with many other allocators, including mimalloc, hardened_malloc, and others)

Re:Why does musl make my Rust code so slow? (2020) by flohofwoe on Wednesday December 13, 2023 @06:28AM (#38625800)
The question that popped into my mind is rather: why does Rust rely on the C stdlib at all (e.g. why even call into musl or glibc). Shouldn't the Rust stdlib implement its own allocator which directly requests memory from Linux via syscalls?
Re:Why does musl make my Rust code so slow? (2020) by Ericson2314 on Thursday December 14, 2023 @03:14PM (#38646641)
That is what Go does. BSDs hate it. https://github.com/redox-os/relibc could be repurposed for this easily enough.
Re:Why does musl make my Rust code so slow? (2020) by croemer on Tuesday December 12, 2023 @01:14PM (#38616046)
This appears to still be an issue in late 2023 when using the default allocator, as I discovered here: https://github.com/nextstrain/nextclade/issues/1338
Re:Why does musl make my Rust code so slow? (2020) by flohofwoe on Tuesday December 12, 2023 @02:28PM (#38617093)
Hmm... if the allocator affects performance so much, then maybe the code simply uses the allocator too frequently?

In C++, if someone starts frantically searching for a faster general purpose allocator then it's usually a sign of putting each C++ object into its own heap allocation behind a smart pointer, creating and destroying tiny objects all the time, and then wondering why so much time is spent in the allocator.

Re:Why does musl make my Rust code so slow? (2020) by the_mitsuhiko on Tuesday December 12, 2023 @04:26PM (#38618810)
> Hmm... if the allocator affects performance so much, then maybe the code simply uses the allocator too frequently?

I'm not familiar with musl's allocator so it's hard for me to say anything about it. However what is pretty common is that modern allocators use thread local allocators to avoid hammering global locks too much. Since Rust is very concurrent you don't need too many allocations to benefit from these optimizations.

Re:Why does musl make my Rust code so slow? (2020) by a_humean on Tuesday December 12, 2023 @02:45PM (#38617336)
Not sure its right to blame the code when changing the base image/allocator results in 30x performance improvements on the same hardware. I would be inclined to blame a poor choice of base image/allocator.
Re:Why does musl make my Rust code so slow? (2020) by croemer on Tuesday December 12, 2023 @02:49PM (#38617422)
It's not a docker thing, we're getting the same 30x performance hit without using docker, simply compiling musl vs glibc binaries with the default allocator chosen by Rust.
Re:Why does musl make my Rust code so slow? (2020) by croemer on Tuesday December 12, 2023 @02:48PM (#38617379)
Every optimization that you don't need to do is a win. With glibc, performance impact of unnecessary allocations might be minimal, but with musl allocations suddenly matter a lot.
Re:Why does musl make my Rust code so slow? (2020) by wredue on Tuesday December 12, 2023 @05:37PM (#38619704)
In a lot of ways, rust definitely encourages heavy use of allocator.

Even if you program better for it, one of the prevailing opinions on “learning about lifetimes” is to “not learn lifetimes, just make copies”.

Re:Why does musl make my Rust code so slow? (2020) by hayley-patton on Tuesday December 12, 2023 @06:22PM (#38620242)
If the allocator can't keep up with the code, then maybe the allocator simply is bad?
Re:Why does musl make my Rust code so slow? (2020) by lmm on Tuesday December 12, 2023 @11:20PM (#38622597)
> putting each C++ object into its own heap allocation behind a smart pointer, creating and destroying tiny objects all the time

Are C++ allocators so bad that they can't handle this use pattern? Yes, you can make a bunch of manual effort to use the allocator less, but you shouldn't have to.

Re:Why does musl make my Rust code so slow? (2020) by croemer on Tuesday December 12, 2023 @01:16PM (#38616073)
Re:Why does musl make my Rust code so slow? (2020) by dang on Tuesday December 12, 2023 @05:30PM (#38619617)
Thanks! Macroexpanded:

Why does musl make my Rust code so slow? - https://news.ycombinator.com/item?id=23080290 - May 2020 (72 comments)

Re:Why does musl make my Rust code so slow? (2020) by croemer on Tuesday December 12, 2023 @11:07PM (#38622531)
How did you do that macro expand? By hand?
Re:Why does musl make my Rust code so slow? (2020) by dang on Wednesday December 13, 2023 @03:49PM (#38633947)
Re:Why does musl make my Rust code so slow? (2020) by NelsonMinar on Tuesday December 12, 2023 @05:18PM (#38619473)
Is there somewhere I can read more about Debian slim? I see there's a bookworm-slim but it's not clear what's removed or how much smaller it is. I'm asking for Proxmox; been using Alpine containers because they are so small but wouldn't mind other options. Debian-12-standard is 126MB (alpine is 3.)
Re:Why does musl make my Rust code so slow? (2020) by SushiHippie on Tuesday December 12, 2023 @10:18PM (#38622226)
https://github.com/debuerreotype/debuerreotype/blob/master/s...

They mention this script in the README on docker hub.

Re:Why does musl make my Rust code so slow? (2020) by jauntywundrkind on Tuesday December 12, 2023 @11:33PM (#38622693)
As someone who thinks Alpine images are a huge pain in the rear, are abberant systems that causes huge pain (it changed Postgres's sort order on us for example), Debian-slim was my go to choice.

Frustratingly though, it feels like most apps built on Debian and debian-slim end up downloading a bunch of different layers. Often over a dozen. It just makes me so sad.

And these layers do seem to shift and churn. I keep telling Alpine lovers their small images dont matter because the base layers will almost always be resident. But the Debian images just feel like they are ever shifting.