A nice (and very ridiculous) fantasy, but no.
As a person who hires developers to write performant code, I'd love it if there were these magical junior Rust developers who can write performant code.
But as the market exists right now, Rust developers are twice as expensive and the product they deliver is twice as bad.
The only way I can justify Rust to higher management is selling it as a vanity PR project.
It's interesting how we have different experiences regarding this. In my experience, it's usually the opposite. And I believe it's mostly because Rust lets you focus more on the problem you're solving, rather than thinking about dos and don'ts of the language.
For example, most Rust projects (or products) seem to have much more polish than equivalent C++ projects (even for ones with years head start). By polish I mean both user experience and the developer experience when one works on the project.
Also, adding user-facing (i.e. UX) polish to Rust projects requires less ahead-of-time planning in my experience.
One reason is that when introducing new Rust code, there's less performance gotchas, and Rust code seems to compose more ergonomically than C++ code... Most of the time at least; there were times that Rust was frustrating. But I think less often probably, _and_ the frustration is compile-time, rather than runtime. Also Rust has a shorter feedback loop due to Rust's incremental compilation really helps mitigate the frustration, so you can iterate faster.
And another is because I've always felt like refactoring Rust code (even with C++ experience than Rust) tends to be easier, and faster to refactor, and I feel bolder while doing it, if that makes sense? Simply because the compiler thinks about various categories of problem domains instead of me, and it tells me about them.
Of course, it's never black and white with any of the above things I mentioned; the situation is grey in both ecosystems. But I think it's a much lighter shade of grey in the Rust space than in the C++ space. And as always, there's always exceptions on either side, too.
EDIT: I quoted OP's full sentence, but then only addressed the last bit. I hopefully clarified in comments below that I wasn't talking about the first part. Sorry about that!
Obviously your experience doesn't involve budgeting or hiring developers.
Your subjective feelings about how nice or fast it is to write Rust code isn't what we're talking about here.
The original poster claimed that Rust can save money by letting managers hire junior devs to replace senior C++ developers.
This isn't true. Rust developers are much more expensive than C++ developers, and have vastly lower productivity. (No doubt because of their vastly inflated expectations; any Go/Python/PHP developer who upgrades to Rust suddenly thinks they are elite 10x programmers because they have a clue about performance now.)
Ah, that is very true! :) I forgot to make clear in my comment that I wasn't referring to that bit at all.
I only participated in the hiring/interview process, but that's as far as my hiring experience goes.
> The original poster claimed that Rust can save money by letting managers hire junior devs to replace senior C++ developers.
Ah, I didn't interpret it that way. I thought the point they wanted to get across was that it's easier to get the same for less—not in terms of monetary cost, but in terms of less mental effort with regards to context/knowledge about the language itself.
But, the hiring point you're addressing can be inferred from their comment, too.
I think I agree with you on that... It probably is "easier" to hire C++ developers, since there's an older and bigger market for them.
I think Rust developers are in an interesting position right now that they're not as abundant as other developers, since Rust is probably still in "early adoption" stage. So they can use that as leverage in salary negotiations, maybe? But it also comes at a cost of a much smaller job market for them, too.
No, you are viewing that from a technological perspective - what you assume only holds if "Rust" was a requirement.
If staffing a project is much harder (and maybe more expensive) when using Rust as language, then Rust will not be chosen if C++ is an option.
This is not at all what I said, nor meant. I never said anything about the hiring market, but merely stated a personal observation why I think Senior C++ devs often dislike Rust.
Senior C++ developers are not impressed with Rust because it doesn't solve any problem they have. Switching to Rust would make them markedly less productive, with no corresponding benefit. The drain comes from slow compilation and from excess design overhead, the need to distort a simpler architecture to satisfy the borrow checker.
Put simply, the extra work to satisfy the borrow checker prevents errors they do not make.
This contradicts Rust propaganda, where a few CVE numbers are cited over and over, echo-chamber style. What these citations never mention is that they are for bugs in mostly very old code. We just don't need to write code that way anymore. It is not just error-prone, it is more work, so there is simply no temptation to write it that way.
I do hear of programmers who have elected to stop learning, and (proudly!) admit continuing to write C++98 or even "C-like C++". We used to say "you can write FORTRAN in any language"; there is no eliminating bad programmers, but plenty of reasons to avoid their product. What conclusions can we make about Rust from its worst adherents?
It is unavoidably true that grave security holes get found only in existing code and not hypothetical future code written with a later language revision and whatever new features will definitely avoid those "errors they do not make". That's time's arrow for you.
Can you name a few of these "Senior C++ developers" and point us to, say, a few years of their work?
Is there a specific vintage of C++ where you feel like, at last, unlike C++ 98 you "don't need to write code that way" and so Senior C++ developers won't make these errors? C++ 11 maybe?
you mean a problem blithely ignored until the software becomes important enough to attack, at which point, it's too late to rewrite the "very old" code? https://googleprojectzero.blogspot.com/2022/01/zooming-in-on...
> errors they do not make.
bullshit. a quick look at oss-fuzz on c++ projects, many of them in modern c++, will show that they are teeming with memory unsafety.
> there is no eliminating bad programmers, but plenty of reasons to avoid their product.
on an unrelated note, what product are you responsible for, so i can avoid it?
> This contradicts Rust propaganda, where a few CVE numbers are cited over and over, echo-chamber style. What these citations never mention is that they are for bugs in mostly very old code.
Empirically this is not true. https://twitter.com/LazyFishBarrel/ is not citing "a few CVE numbers over and over"; for example, in browsers, new code is disproportionately responsible for vulnerabilities. I know most of the people at the big tech companies doing the research into where the security problems in major C++ software come from; they're not making the results up.
What? Why? I've been developing C++ for 10 years and seen firsthand the problems it causes and that are addressed by Rust. If I start writing Rust I'm going to be more productive (from build system to maintenance), write more performant and reliable code faster, so I don't see how the delivered product would be worse, as I'd have more time to iterate.
About the rate, maybe that would be more expensive, but I'd say it's still worth it. Anyway, it's not like getting competent C++ developers is cheap either.
As for GP's message, I agree it looks unrealistic that "kid fresh out of college" would magically write performant code because they're writing rust. There is more to performance than the language, and it is particularly easy to write bad performance code in rust (and in C++ I must add). That being said, I'd still be less anxious to have a junior in a rust codebase than near a C++ one.
Maybe it's true for you, but I can hire a competent C++ programmer to deliver code faster for less than what you'd ask.
Also, if a programmer is spending time "iterating" on a performance problem, he's already underperforming. That's okay for less experienced developers as part of the learning process, but expecting it to be the norm? No.
> About the rate, maybe that would be more expensive, but I'd say it's still worth it.
Real-world metrics do not agree.
I don't think the OP meant iterating on performance problems specifically, just generally iterating on code as one does when they write it.
Also, every programmer at some point iterates about performance problems, not matter their experience, or language (or implementation), or runtime that's being used.
I think the original "uni grad can write better Rust code than experience C++ dev can write C++" is a hyperbole. I don't think they meant better, but the Rust developer will need less context to implement the same feature.
The spirit of that sentence was probably "it's simpler to write performant and safe code in Rust than C++". But again, without really agreeing what "performance" means here, it's a bit silly to discuss.
Performance is such a complex that can mean so many things depending on the problem. So, I we're all nit-picking about something without even agreeing what they're specifically nit-picking about.
The default IO mode in C/C++ is buffered. Rust requires you to wrap it in `BufWriter`. For most network (or general IO, really) workloads you want buffered IO.
So sure: We could say that writing performant IO code in Rust is more difficult, if we hyper-focus on this one specific detail.
FWIW (and people who're unfamiliar with this): I think switching to buffered IO in Rust is absolutely trivial, and very well documented (in multiple places where it's relevant). In fact more so than it is to switch to unbuffered IO in C++, because you have to call `setbuf` with "special" values to disable buffering.
We can then argue that experience/wisdom diminishes most of these arguments about performance, but it diminishes them on both sides.
Exactly, on both accounts, thanks.
It strikes me as odd that GP would describe "iterating on performance" as "underperforming", unless GP is in a very specific domain where the performance requirements are always known in advance and where they never change. Getting the last drop of performance from code is a trade-off. It impacts the readability and maintainability of code. To get the last drop, it can depend on the shape of your expected input data, and it requires looking at the produced assembly and performance profiling results to find bottlenecks and act on them. This alone implies iteration. If you're telling me that your engineers know their compiler so well that they can tell in advance what assembly code will be generated when changing seemingly unrelated parts of the code, eg they know the inlining limits of their compiler, I call BS.
Iterating on performance takes time to develop and maintain, which is why it should be done just enough to meet the requirements, in particular in the hot loop and to reduce bottlenecks. If your developers are optimizing all the code they write to the ASM instruction, they are probably underperforming (unless specific domain where so little code is written or the target is so small that the benefit is worth the cost). Understanding that trade-off is part of seniority (aka juniors will often both "prematurely pessimize" by writing inefficient code without increasing maintenability or in the hot loop and "prematurely optimize" by avoiding allocation at all costs in CLI argument parsing).
You could be right... I hope you are right, but I'm afraid you're not...
> I'm not sure about that. I've spent 18 years programming in C++, for much of that time in a senior professional capacity and am excited to learn Rust for whatever my next project will be. Most of my colleagues and peers feel the same. [...] I like C++ but don't love all of the baggage and am delighted that things are moving forward.
I don't know what the "split" is regarding mentality, and I've definitely seen a lot of experienced C++ devs in Rust communities, but then there's also a lot of people in "Rust bad"[1] circles (you see them on Reddit and HN). I think it might be an even split (as with most polarised opinions), but I don't think that either sort is rate.
[1]: I don't blame these people, btw. If you're in a senior or leadership position and you choose C++ for a new project, because C++ is your strong suit. Then you read online "C++ bad" comments that glorify Rust. It's hard to not take these things personally, when it might be affecting your livelihood. Especially if semi-technical management "drinks the Rust Kool-Aid" (for a lack of better expression) and grills you over your decision. It's not a very disheartening situation to be in, and that frustration can fester into contempt, and so on.
That's a good point. In the domain specific communities, I've not not really seen language flamingo.
I'm optimistic about Rust but realistic (I think) about how much inertia the common project (C++) really has. I'm also decidedly skeptical about Rust's cure-all possibilities - while I've seen a dozen or so real lifetime bugs in a decade, about half of them were caused by a developer misusing an API, deliberately calling a method that is for transferring lifetimes, and then not assigning the reference to a new object.
In my experience, most bugs are just badly written code, not the sort of problem your compiler can fix.
I think this "make a list" idea performs best where you know exactly how many things will be in the "list" but have little idea how long the concatenated String might be, so you can keep the "list" as a local array (no allocation) and do a single String::with_capacity (one allocation) and then push all the references onto it.
Otherwise, obviously we're not going to go around assembling a LinkedList since this is the 21st century and we're not crazy, so let's assume if we don't know how long that "list" is we're accumulating references in a Vec<&str>. We don't know how big to make the Vec either, and so that will grow as we push items onto it.
Rust's Strings are - under the hood - basically a Vec<u8> that promises to be valid UTF-8. So we're playing with the exact same allocation algorithm and same amortized costs in String and Vec<&str>.
If we're appending very few Strings in the typical case, the "list" approach costs extra because we're doing a bunch more allocations + copies to make the Vec<&str> that we're throwing away shortly afterwards. Likewise if the strings are very short.
And after all that it's more complicated, which counts against it unless performance was critical.
If I saw a junior reflexively doing this (with a Vec or some other "list" structure) in code I was reviewing, I'd ask them why. If their answer is "performance" I'd remind them: If we aren't measuring it then it isn't performance it's just wanking. So, where's the measurement?
But I see your point - I inadvertently gave an example that is performance basics in some languages and fine tuning in others.
The lock example is perhaps more relevant.
Another good example is appropriate caching. Often services want to parse something (e.g. an ini file) and cache it in memory. Caching the right (fully parsed) format will lead to a highly performant configuration system - taking less than 1% of CPU time - but let some juniors do parsing on top of the caching layer rather than underneath your caching layer - and suddenly your config system is 5-10% or your service CPU and is a target for optimization. Most of my daily work in growing juniors is patterns like this, nothing a language would help with.
The nice C++ frameworks from the 90's all used bounds checking enabled by default, what does ISO C++? Bounds checking disabled by default and it is up to the compiler vendors to do as they please, hence FORTIFY and _ITERATOR_DEBUG_LEVEL.
If you read how magnificent C++ is on the HILO tutorial or C++/WinRT ones, it is quite clear how WinDev sees these nasty folks doing stuff in .NET at DevDiv.
Joe Duffy on his Midori talk at RustConf mentions that even with Midori being available to WinDev they were asserting it wasn't possible.
C++ seems perfect for these people because there are so many little traps and arbitrary rules to remember. “Ha ha, you wrote for (const auto x: y) instead of for (const auto& x: y)? Stupid fool!”
(Or is it auto&& now? decltype(auto)? I honestly don’t remember and don’t really care.)
I’m not remotely suggesting all or even most C++ experts are like this, but anecdotally, their share is higher than among, say, Python programmers.
It’s not like Rust is particularly easy to learn. On a conceptual level, it’s probably harder than C++ (traits, generics, lifetimes). It’s just so much less arcane.
The defaults are wrong. Const should have been the default. Whereupon "East Const" doesn't matter, all the variables which are mutated get labelled. Similarly "explicit" should be the default (nobody wants your random single parameter constructor to be implicitly called, stop that) and "override" shouldn't be (If I name my method foo why is it my responsibility to first check whether some other bozo named a method foo so that I don't "override" it ? The compiler can and should tell me this won't end well†)
† Rust brought me around to the idea that some other bozo's quack() method has no business sharing a namespace with mine just because we're both Ducks, if I wanted to override the shared method I'd have re-implemented Duck::quack() not added my own quack() method. But in the C++ world I'll stick to just saying override shouldn't silently be the default.
yeah no.
struct foo {
int x;
};
would not be compatible with C because the int would be const, that would have made the language particularly useless.I'm not talking about those. I think they plain shouldn't exist, but it's a separate discussion from the discussion about the defaults.
But yes, this means you can't cut-and-paste C code. I appreciate that this is disappointing for the "Actually we already have lots of C++, it's just that it's mostly .c files and doesn't realise it's C++ yet" people. Set your sights higher.
† Yes, this insanity is also available in volatile flavour.
Why would CV members be insane ? Having const members has been very useful for me when refactoring codebases, to make sure that I knew every place modifying such a member. It has never been a hindrance, just plain positive, and not having it would mean one more rule to remember (and having to explain students why you can write "const int foo;" here and not there)
They actually can't (well, shouldn't) write "const int foo;" as a local variable because the compiler needs to know its value. And that gives the game away.
These are already different cases, yes both the structure member and the local variable are names with types, but they already need to be explained separately.