6 ms·
Alternative title: Poor Interface Design Makes Most Rust Programs Much Slower That programmers need to consider this stuff on each new project is a failure of
by dmw_ng 5y ago
Alternative title: Poor Interface Design Makes Most Rust Programs Much Slower
That programmers need to consider this stuff on each new project is a failure of the standard library design, it's a problem not even C++ suffers from
- mamcx 5y agoNo. But is very surprising when you see Rust how high-level is as language yet it target system programming. One major philosophy aspect of Rust is that (almost)everything is explicit and you build abstraction from the bottom.
- deleted 5y ago[deleted]
- trasz 5y agoNot even C has this problem - stdio handles this just fine, by deciding whether to buffer or not depending on where the data is going to (tty vs a file).
- smolder 5y agoNo, it's a design choice, not a 'failure'. Hidden behavior has its own pitfalls, and you can argue this all day, but there are already 100 languages which go the other way and cleverly optimize things behind the scenes every chance they get. I wouldn't mind much if they made IO buffered by default, but I don't mind it's not, either, because it's consistent with the design ethos.
- spoiler 5y agoIn my experience, the most ergonomic implementation is rarely the most performant one in C++, you usually end up having to use some SFINAE monstrosity or sprinkle constexpr if all over the place. std::optional comes specifically to mind as one of the big offenders here. You've also gotta be careful with unexpected and implicit assignment/copy/move constructors. More than half of all the C++ wisdom one needs in their career is when to avoid stdlib and which part of boost to use. Due to C++s religious devition to 80s compatibility, it becomes a minefield of a Don'ts, with a narrow path of Dos. The fact boost is a billion libraries in one speaks in of itself about the abysmal dependency situation in C++. There's also a buncha dep managers that are at each others throats. Also, C++ people like to poke fun about js devs and npm/leftpad, but forget that they use boost for even more rudimentary string operations. Or they implement the same thing over and over again. Or my favourite: copy+paste the same code in multiple projects, and then have divergent implementations of the same thing with different bugs and/or API surface; bonus points if the thing is part of an RPC implementation. As much as the edgy-dev crowd loves to belittle the very concept of dependency management, at least JS/Ruby/Python ecosystems give a shit about DX and made sure the package managers can be used with the same repositories/sources. But hey, at least C++’s IO is buffered by default. Amazing. I got distracted by my rant above: I actually PREFER the default is unbuffered, because it doesn't violate the principle of least surprise (if we remember that Rust is a systems programming language). The fact you expect the default to be buffered is probably due to exposure to C/++.
- PaulDavisThe1st 5y ago> The fact boost is a billion libraries in one speaks in of itself about the abysmal dependency situation in C++. There's also a buncha dep managers that are at each others throats. There are no dep managers for C++ that have any kind of universality to them. To reiterate for the umpteenth time: many C and C++ libraries come with compile-time flags that totally change the nature of the resulting library. It is not possible to refer to a "canonical" version of the library the way you could with something for Java, Python, JS etc. When I say "this code relies on libfoo", it is necessary to know if there are build/compile flags for libfoo that could change the nature of libfoo.{a,so}. If there are not (common, but not universal), great. If there is just one, probably manageable. If there is more than one, game over. Also, only C++ iostreams are buffered by default. Just like in C, where you are free do IO with syscalls if that floats your boat. There's nothing more or less obvious about this than in C, where stdio vs. syscalls is an essentially identical choice.
- duped 5y ago> To reiterate for the umpteenth time: many C and C++ libraries come with compile-time flags that totally change the nature of the resulting library. It is not possible to refer to a "canonical" version of the library the way you could with something for Java, Python, JS etc. That just iterates GP's point: C/C++ dependency management is abysmal, but it's "hard" because the languages themselves do not have the capability to express the required metadata in any standard way. As an example, the first time I tried to compile Ardour took me several hours finding and installing the right dependencies for my distro. PL designers have learned from these mistakes, it's not worth defending them or accepting that it is the way the world should be...
- PaulDavisThe1st 5y ago> but it's "hard" because the languages themselves do not have the capability to express the required metadata in any standard way. Of course the languages don't. It's not a part of the language. If I build libfoo with -Dexclude_feature_bar which just drops 2 source modules from the library build, how can the language express that? On Debian, you get the Ardour dependencies like this: apt-get build-dep ardour6 If your distro makes it hard than that, that's a distro problem. Of course, the libraries Debian or any other distro will install when you do that are not the ones we use to build Ardour, because we have patches for several libraries that will never be accepted upstream but are necessary/useful/important for Ardour. You can't express that with the language either.
- eska 5y agoIn C/++ land the implicit buffering causes all kinds of confusion among beginners and veterans alike. From “why does this not print” to “why is the performance so bad in multithreaded programs”. In practice people avoid C and C++ I/O and use platform-specific functions to have more control over the buffering. Good job! There are also other reasons for designing it this way such as composability. In general it’s bad idea to try to undo an abstraction, and instead one should build on top of primitives instead.