Building a database is brave or stupid or both. Over the last 15 or 20 years I’ve tried lots of databases of all flavors and every time come back to Postgres.
What can’t it do.
And like Linux it’s written in C. Not that means much.
However, you didn't return to postgres:6.0 (first formal release in 1997 [1]), you returned to postgres:latest, which included the lessons learned from lots of other databases, thinking here of postgres:9.2 (in 2012) adding native JSON support making Postgres basically NoSQL with extra steps. Contrary to popular wit, reinventing the wheel is always beneficial, if it will not bring something new to the world, it will at least make you understand and appreciate wheels better.
It depends on your use case. For example, Postgres will hit limitations for large streams of time series data on the ingestion side, and the standard SQL language of Postgres may make it challenging to navigate a dataset by time: sampling the data, time intervals, time-series joins (ASOF join), and these kinds of things are not easy or possible to do on Postgres.
Why not combine Postgres for OLTP workloads alongside another database for fast analytics/time series, optimised to deal with high throughput ingestion and low latency queries?
NB: I am one of the co-founder of an open-source time series database (questdb)
Clustering it is still a pain, certainly if you want a proper autoscaling master-master setup. (Which may not be necessary for performance, but is still what you need for availability/resilience).
And it's still too easy to shoot yourself in the foot, by deadlocking, or using up all the server's resources with a query that looks very similar to one that was fine.
Seems like there are a couple of people with this mindset at every company. “Let’s write X”, “are you crazy, no one writes X! We can use Y!”, “But Y lacks Z”, “No! The thing you want Y to do is bad! You should not want Z! Do W instead - it is the correct way”
Stop larping as graybeards, and try to actually do something instead of endlessly bike shedding your cargo cult.
Betting against Postgres all the time, since the .com age I have mostly used Oracle and SQL Server, and Postgrest only in a single projec that was alive during 4 years.
There was also Informix, SYBASE and DB2, but those hardly matter nowadays.
>>Over the last 15 or 20 years I’ve tried lots of databases of all flavors and every time come back to Postgres.
Almost the same here, have tried just about everything that comes along, and sooner or later I end up swapping out the database de jour and go right back to sql server in almost all use cases (for the type of projects I do).
I feel like db's are pretty much a solved problem, and can't imagine trying to build and market a brand new one these days. Almost as hard as trying to come up with a new operating system and convincing people to switch.
I wish good luck to anyone that tries, but talk about pushing a boulder up a mountain; definitely doesn't seem like the easy path to success.
> Rust is easy to learn. For seasoned C++ programmers, Rust is easy to learn. When they first start out, Rust learners usually spend most of their time making sense of ownership and lifetime. Even if they don't explicitly express these concepts in code, experienced C++ engineers always keep these two concepts in mind when programming in C++.
Yeah, sadly it is. With e.g. Elixir I can literally get into a REPL and prototype my solution in minutes, right there on the spot, and then just copy a few lines from it and have the solution be 90% done (minus tests, of course).
With Go and Rust I have to make a dedicated function somewhere and then have it be called after starting the program. Ain't exactly rocket science but the difference in time to do it and the convenience is still very stark.
I love working with Rust for the stability and speed it gives me but the value proposition and daily coding flow are VERY different compared to a dynamic language. With Elixir I am mostly just brain-dumping and stuff happens extremely quickly and fluidly, with Rust I kind of sigh and accept that the next 10 minutes I'll just be writing and writing. Might even zone out and make a dumb mistake because I have to spend more keystrokes and more time to do something I'll do in a minute in Elixir.
Maybe it's time to look for snippets support in my editor. Or start asking ChatGPT for them.
Try using a test -- can stick anywhere and just run code there (push of a button with analyzer in vscode). Almost like embedding a repl into a module for experimentation.
See this is what I’m scared about in my current job. We have some people who want to use dynamically typed languages and some who want to use static.
I don’t think being able to brain dump code is a good thing and it leads to an unmanageable mess when you have a large codebase. Types are essential as far as I’m concerned, but I constantly have to get into arguments with the dynamic type fans because their “flow” Is being restricted.
Brain-dumping is simply a way to iterate and figure out what works and what doesn't, quickly. After I do it I take the requisite time to emulate exhaustive pattern matching, and add tests that cover the functionality well.
My problem with Rust, and I love the language a lot, is exactly this: I want to quickly find what would work. After that I'm very happy to take the proper time to go things rigorously.
Yes and then someone comes along and makes a change that breaks something seemingly unrelated and it’s less likely to be caught because there is no type system.
And please don’t say tests solve that because they don’t. They help but they don’t solve it.
You won't catch me arguing with that. I work both with dynamic and static languages and usually I'll pick the static ones.
Dynamic languages are very valuable when you can afford to iterate and gradually find out the golden path. For the better or the worse, many businesses are of that type.
That being said, I just ended an Elixir contract and absolutely want to code Go or Rust for money again.
I do appreciate that you write tests. I find it's like pulling teeth with most devs to get them to write anything but the most basic of tests.
I tend to think more than write code, so usually my first go is reasonably close to what I need. But there are always edge cases you just never think about. I'd rather have a strong debugger than a repl imo
> I find it's like pulling teeth with most devs to get them to write anything but the most basic of tests
You are unfortunately very correct (at least in my 21 years of experience as well). I too feel annoyance when I know that I made a piece of code work well but (a) every now and then I am truly wrong and (b) various pieces of the system in the code interact in sometimes unexpected ways, unveiling inputs to your code that you haven't foreseen.
So even though it often takes a heavy and annoyed sigh out of me, I still roll up my sleeves and add the tests because I've shot myself in the foot too many times, and ignoring past experience is just being a stupido.
As for debugger/REPL, they are not orthogonal; you can have both. I'd more contrast debugger with tests themselves -- both are ways to go step by step through a process that you know is faulty somewhere.
REPL to me is just a way to more quickly sketch a v1.0 of a piece of code, nothing else.
Nah, not specifically about the REPL itself, I just need a way to quickly sketch and run a piece of code is all. I know big IDEs support this but I prefer keeping everything in the terminal -- I'll have to go check if Emacs or NeoVim offer something along those lines.
Maybe take a look at evcxr, it runs in a terminal and is REPL like. When I'm dabbling in rust, I use it e.g. to quickly try out library functions and how to work with the result. But I'm just getting started.
I love the idea of Elixir, but I just can't get into it because of its weird choice of sigils. |> for pipes and <- for assignments, seriously? I seriously dislike programming languages which choose two character sigils for basic operations. I also heavily dislike |x| in Rust.
Not to get on the merits of Rust or Elixir, but while you are absolutely entitled to your preferences I should suggest that perhaps you may miss out something important by ditching languages based purely on the format of sigils.
It's like whitespace in Python, parens in Lisp, begin/ends in Ruby, or 1-based arrays in Julia. You get used to it and eventually it feels natural when using that language.
Not going to judge you. When you feel a bit more generous and adventurous, I recommend you give it another go.
Syntax is easy enough. Like all programming languages, you'll get used to it in a weekend and won't even notice it afterwards.
Elixir is absurdly productive: very terse code, very self-explanatory stdlib API, transparent concurrency / parallelism, and in-OS-process high availability and mostly-self-healing hierarchy of green threads and supervisors observing them.
People on HN and Reddit really love to roll their eyes at stuff that's getting popular, and likely will avoid the technology out of a misplaced spite, just because a lot of people are talking about it. It's a weird phenomena.
(Not saying you're doing it, I just kinda got carried away here.)
Minor clarification: Elixir uses = for assigment. There's a special construct called "with" that's basically fallible pipes, and that's probably where you saw <-
with {:ok, id} <- get_id(),
{:ok, val} <- get_val(id)
do
show_success(val)
else
{:error, e} ->
# We reach this if either get_id or get_val fails
show_error(e)
end
The Rust tendency toward “golfing” is why I don’t like it. It’s not even lifetimes, but the way traits are setup. And the lack of unified function call syntax. Sometimes it’s a function, sometimes a method — that distracts a lot from the problem at hand IMHO.
I assume they didn't mean compared to C++. If anything, saying prototyping in C++ is easier than Rust is beyond ludicrous even if you're a seasoned C++ developer.
I'd have an easier time prototyping in Rust than C++, and I've been writing C++ for 10 years and Rust for a little over a year.
However, prototype in something like Ruby (or even TypeScript, and some people mentioned Elixir) is in a different universe compared to C++ or Rust.
Like, it's not even a "fair fight" to compare it meaningfully.
What makes Rust better at rapid prototyping? Cargo?
I find that modern C++ "kitchen sink" approach to features makes it good for rapid prototyping, a bit like Perl on the dynamic side. It won't force you into a specific approach, pick the one that gets you there the fastest. Use raw pointers and malloc(), or use fancy smart pointers and RAII, your choice, you can also do both, you have exceptions, you have goto, you can write(), printf() and cout, you have classes and lambdas and (multiple) inheritance and traits. More options are better for rapid prototyping.
Also, C++ is the most popular language for competitive programming, you can't get more "rapid" than that.
If I wanted to just blast out something quick and dirty, I don't think I'd reach for `unsafe`. It's syntactically inconvenient, with lots of `(*foo).bar` and `MaybeUninit`. And I don't think I could be happy with a prototype that's blatantly full of UB, so for me it would take more effort rather than less.
Now that I say that, I guess someone could write an "unsound helper functions" library that helps you write code full of UB conveniently. It could be an interesting thought experiment. But I don't think the community would be very happy about it...
Both viewpoints make sense; whether Rust is good for prototyping depends on the domain.
If it fits the borrow checker well (like in CLI apps, stateless servers, data transformation) then the borrow checker fits beautifully and seamlessly.
In other settings (complex turn-based games, some compilers, GUI), the borrow checker can cause some artificial complexity and prototyping slowdowns compared to other paradigms.
I guess it depends on your point of view. For me, having Rust catch issues even when prototyping makes me enjoy prototyping more. I absolutely hate (even when prototyping) when I try to run something, it chugs along for a bit, and then hits a runtime error due to some stupid typo.
In fact I like Rust for prototyping precisely because I don't yet have tests, and the extra compiler diligence frees me to focus on the prototype.
> and then hits a runtime error due to some stupid typo.
I don't think that the parent comment implied prototyping in dynamic languages but rather in statically compiled ones.
FWIW in C or C++ you don't have to do as much code gymnastics to satisfy the compiler so consequently prototyping is both faster and easier when compared to Rust.
Again for me personally, I find the opposite true. With C and C++ I'll find that once in a while, quick sloppy coding gets me something that seems to work for a bit and then fails in subtle and hard to debug ways. That's a time sink that just doesn't exist when I whip something together in Rust.
I agree with the macro part. I have seen people use macros instead of functions as a way to escape the type system. But it's not a problem that comes up with C++ programmers.
I was happy to see this as well. As a 'seasoned' C++ dev myself, when I learned Rust, I was pleasantly surprised to see those implicit concepts made explicit in code.
Same. I think that I didn't go through the Rc<RefCell> phase that so many new to Rust go through because of C++ teaching me the same lessons in a much more brutal way. By the time I got to Rust I had learned to structure my code to sort of use pointers/references as capabilities, such that simply having knowledge of the bit pattern of the pointer was implicit access through that pointer since as a codebase evolves someone will keep pointers around or not go through.whatever song and dance you need to do to keep accesses through that pointer valid. That thought process translates very well to Rust.
What I love about Rust is what I love about Python… “explicit is better than implicit”
When I open something up to read it, to try and understand it, to dig in and fix something broken… having everything be exposed in the explicitly written code… is vastly more useful to me than trying to mentally interpret a language as I read it and remember the rules, the meta-programming rules… and all the implicit stuff that can affect how the program will behave.
Lot of programming languages aren’t good at this explicitness, and I’ll be honest, it’s a genuine struggle for me picking up the languages like this, only made worse when the documentation is very prose like and fails to convey how anything actually works, eschewing that in favour of, at length, demonstrating the feel of a programming language through countless demonstration example that lack mechanical “what is this doing under the hood” explanation.
A few years ago I met up with someone who just graduated and who's only experience with programming was MATLAB during his degree. To my surprise he'd been hired to use Rust and was telling me how great the recently released async was.
Hot take, I feel like people that complain Rust is hard typically write bade code in other languages. Rust is just preventing you from making common mistakes or using patterns that make your code hard to reason about and debug later.
This, this, and this again. Lots of patterns Rust enforces are sensible choices even with a garbage collector, because data races for instance are still a thing even if you have automatic memory management
As somebody who could possibly be in the category you described, once I learned about Arc+Mutex, I pretty much write code the same way I used to. That and maybe OnceCell/Lazy?
As a fellow Rust user, please stop saying this. Not everyone who codes like us is a bad programmer. It's this kind of sentiment that gives us a bad name.
Rust may influence us into patterns that are better in some (likely even most) situations, but not always. Sometimes the situation calls for other approaches, and that's okay.
The OP is crapping on people who find Rust hard to learn by broad-brushing them into the "bad programmer" bucket. It's a hallmark of Rust zealots, and one reason why the Rust community has such a bad name. Which is a shame because the language is decent and useful.
As someone with a passable level of modern C++ exp it took about a week to pick up Rust. Syntax was the time sink...
Though, people tend to gloss over that C++20 is decently comparable to Rust in terms of semantics and safety, the issue is very few C++ codebases are modern and the footguns are still lurking for the careless.
That said, Rust iterators are very nice and the async story completely mocks the C++20 coroutine nonsense.
"The STL library lacks support for some modern programming tools, for example, native co-routine support. As a result, developers must rely on many community projects, and most lack long-term support."
I couldn't agree more with this comment. As great as the community is, there's a lot of projects that are just not maintained. I wish this was different.
They aren't strictly comparable. While the heap allocation may be optimised out, there is no way to use native C++ coroutines as guaranteed zero-cost construct due to the automatic heap allocation in the API.
Rust's coroutines currently have practical optimisation issues related to instance size (because the compiler isn't smart enough yet in a few places), and the more powerful generator API very much isn't ready yet, but they give you considerably more control over the memory management.
It's easy to stack- or pool-allocate coroutines there if necessary for performance, while in C++ you wouldn't be able to use the native language feature where frequent or unmonitored heap allocations from fine-grained coroutine use would be a problem. (Apparently this makes them unsuitable for AAA game development, for example.)
Library-provided coroutines may be more versatile.
Rust coroutines evaluate to opaque value types instead of handles, for comparison, so the caller gets to decide what to do with them.
Currently they're a bit unwieldy though, until naming (aliasing) their types becomes possible. The unstable documentation for that is here: https://rust-lang.github.io/impl-trait-initiative/explainer/...
(Edit: Sorry, I'd grabbed the wrong second link. Fixed.)
Co-routines are available in C++20. And in dozens of other libraries, if for some reason OP is limited to < C++20 which I doubt considering that the product is not yet launched.
Coroutines in Rust are a native language feature and their API is part of `std`, but the executors indeed come from community libraries.
Tokio is one option, but as long as you don't contextually fork (for parallelism) you can in theory run the same coroutines on any other executor, like the ones from async-std.
Spawning a sibling task (as opposed to mixed child task polling, which can be macroed inline) unfortunately isn't available through the common API so far, which is where the bulk of the mentioned incompatibilities stems from.
Sorry if I'm missing something important as I have experience with C++ but not rust, but is async/await the right abstraction in Rust vs. the underlying generators which I assume is lower level and closer to C++20 Co-routines in terms of performance ? [1]
In other words, it seems Rust co-routines at the level of Tokio are not as performant as C++ native Co-routines [2] and further down the thread, it's mentioned that once generators are stabilized, it might help build lower cost and performant stackless coroutines in Rust.[3]
Hmm… I'd say for IO-bound tasks/loading in a DBMS yes, async/await coroutines are the correct abstraction, since you're waiting to reschedule on external notice and normally don't want to spin-wait (or you could block on the optimistic case and then `.await` the fallback).
If you'd like to do modular data processing instead then the current best Rust approach is using `Iterator`s[1] and possibly the `rayon`[2] crate for safe parallelisation.
There currently is no coroutine feature that maps nicely onto `Iterator`s, or rather that's indeed expected to be the unstable generators feature, as it should cover that use case without overhead. (Async-coroutines map onto `Future`[3] instead.)
You can think of Rust's `async` and generator use cases vaguely like the ones of JS's async and generator functions. The latter will function without any runtime or trampoline if you advance it in a loop, as far as I can tell, but they're unwieldy if what you want to yield on are only waits on external events. (`Waker`s[4] have similar consumer semantics to JS's or C#'s continuation passing, even if they are only indirect memory management handles.)
It also often makes sense to use both of these at the same time to produce something like an `AsyncIterator`[5], but I expect that feature to be quite some ways away in Rust, at least in a seamlessly mixing fashion.[6]
- - -
I'm actually pretty curious which will turn out faster in practice between C++'s coroutines and Rust's generators, since their memory management is so different.
The Rust coroutines (that is: including `Future`s) are generally stackless already, but also by default heapless, as their entire memory is abstracted as opaque instance with anonymous type that is returned to the caller by value. Boxing them is an explicit operation, and it's equally possible to pin them on the current stack/in the current instance instead. (That's how `.await` works; the child is embedded into the outer `Future` directly.)
There are some pitfalls related to this, since that instance's size is determined by the largest `.await`/yield site, but the tooling should (eventually) be able to warn on unexpectedly large `.await`/yield locations like it currently warns on unexpectedly large enum variants.[7]
> But as more and more engineers joined us, some shortcomings
> of C++ came to bite us: unreadable coding style, memory leak,
> segmentation fault, and more.
* unreadable coding style: This is not a C++ problem.
* memory leak: Memory leak is an old C++ problem, since C++11 there is no reason for not using smart pointers.
The only point that could be attributed to C++ is the segfaults perhaps, due to its lack of safety. But your other two points made me skeptical about Rust bringing you much benefit. I am specially concerned about throwing away months worth of code. Rewriting everything from scratch is what newbies love to do and will most likely get you in the same mess you were in. Try to learn with the error of others [1]. And btw, the problem is usually who writes the code and not which language is used.
> since C++11 there is no reason for not using smart pointers
There are many reasons for not using smart pointers, first amongst them for me being performance.
Smart pointers do allow you to remove a large class of memory bugs from your code (albeit not memory leaks) in the same way that Rust's safe references do. However C++ smart pointers impose a run time performance penalty on your code, whereas in Rust the checks happen at compile time leading to better runtime performance.
What's the overhead of an unique_ptr vs the equivalent rust pointer (yes yes, I know that the Itanium ABI has non optimal calling convention for unique ptrs, but I would be surprised if you can measure it)?
Aside from you being completely uninformed because free(nullptr) or, for that matter, delete nullptr does absolutely nothing and is well defined operation so you don't need to check for that condition in the first place.
But even if you had to, what implications would it have, if you care to explain?
Extra branch which is going to be taken 99.99999% of the time is not going to present any runtime overhead. CPU BP unit handles it for us.
That said, if this really had been an overhead, virtually every language out there would suffer from it, including Rust. Every language out there at some point needs to call into the libc.
Yes, you can write your own runtime ... which will have to rely on the OS internals to do any meaningful work, and in case of memory allocation or deallocation it will have to rely on brk/mmap and then you will be back to square one.
Overhead is almost purely theoretical and it cannot be avoided and is not anything common or specific to unique_ptr's.
Not miri. I mean the actual ASAN, UBSAN, TSAN, MSAN and LSAN sanitizers that are also commonly used in C and C++ codebases. Descendant is the same: LLVM [1]
> Can you point me to any significant primarily rust codebase that runs sanitizers? I've never heard of that
Not sure what do you mean by that, surely there are. At least the ones who are serious about the development. Sanitizers are part of official documentation in Rust [2].
The compiler is happy to compile without sanitizers enabled. Why should it require to implement a null check when deallocating when it doesn't when dereferencing?
While I agree with your point overall, it's important to note that libc is definitely not a must on some platforms. On Linux in particular, the Kernel user-space ABI is stable, so you can write your own system calls in whatever language you want.
Also, even if you chose to use some libc for system calls, there is no reason to use malloc()/free(). You only need mmap() or similar, and then your own language runtime can write their own user-space memory manager.
As a side-note, on Windows, libc isn't even a system library. The official way to execute system calls is using win32, and things like malloc()/free() are simply wrappers around HeapAlloc() and HeapFree().
> However C++ smart pointers impose a run time performance penalty on your code.
i'm not sure if this is the case. unique_ptr doesn't really do much other than use the type system to ensure that only one instance of the pointed-to value exists at once. as far as i understand, it doesn't strictly do anything at runtime.
> unqie_ptr have overhead. It need to run its dtor etc
Technically it is correct, it causes an extremly light overhead due to the inability of the compiler to optimise a part of it.
In practice, even in HPC, I never notice it to have an impact ever.
And as an advise for any new C++ programmers: Please JUST use unique_ptr, everywhere, all the time...
Trying to manage the lifetime manually with new/delete in modern C++ is not worth the cost in 99.99% of the case.
If the impact of unique_ptr is noticeable in your program, you are very likely in a realm where you should not even doing memory allocation anyway.
You're misinformed. Overhead is not about the running the dtor, unless you're willing to leak the memory in your code regardless of the smart ptr usage or not.
What the "overhead" of unique_ptr is usually attached to is the inability for a compiler to pass the unique_ptr as a value through a register but will instead have to use the stack (memory). And that even doesn't apply in the general case but _only_ for unique_ptrs holding an object with non-trivial copy-constructors or non-trivial destructors. This is due to the platform ABI and not the C++ compiler limitation.
Anyway, calling that an overhead is a far stretch and almost purely theoretical unless someone is able to measure the negative effect of such code transformation in the real-world codebase. And I say this as not particularly heavy user of smart pointers.
Also, many other codegen transformations will not fit into a very limited amount of ABI registers so should we argue about not using those as well?
In my opinion, this was only a "campaign" of Google trying to use a unique_ptr as a leverage to persuade the committee to accept their break-the-world ABI suggestion. We know how it all went.
For unique_ptr, in a release build, no: but in a debug build there's overhead, and more to the point, stepping into the deference in gdb/lldb at least in my experience requires stepping through the internals, to the point some of the code we use with them is #ifdeffed hackily to use raw ptrs in some cases to avoid this annoyance.
For shared_ptr, the atomic ref counting can cause surprising overhead due to contention in multi-threaded scenarios, even if just accessing the pointer, depending on how the shared_ptr is passed through functions...
There are settings you can place in .gdbinit to avoid stepping in to internals of anything you don’t want to step into, be it std library classes/functions or your own code.
> There are settings you can place in .gdbinit to avoid stepping in to internals of anything you don’t want to step into, be it std library classes/functions or your own code.
This is exactly what I need. For both, C++ and Rust smart pointers.
Can you share any more info on how to set this up?
Yes. You can provide a stubbed out deleter or a stack based allocator. But you're then responsible for making sure the unique_ptr doesn't outlive that stack memory. Though that's true for any reference to stack memory.
> I am specially concerned about throwing away months worth of code. Rewriting everything from scratch is what newbies love to do and will most likely get you in the same mess you were in.
This was my first thought, but then I realised newbies would have started with Rust. :)
In the first few months of a big build a huge amount of time and effort goes into the foundation: design, POCs, setting up environments, CI, testing infrastructure…
My guess is that they weren’t very deep in production code, and the fact that they didn’t fall for the sunk cost fallacy speaks highly for them.
Tooling, existing ecosystem, built during 40 years of production deployment.
Rust is naturally safer than C++, however there are still many domains where a bit of yak shaving is required before actually coding what one cares about.
So it boils down to where to spend resources, and as note, I am definitly not a fan of Orthodox C++ ideas, rather having C++ improve its safety story as much as possible.
I'm quite nooby in both Rust and C++, but for the little interactions I had, I felt like Rust had a much clearer path forward than C++ when I was in doubt, and "how to write in good style" was more obvious. This leads me to the assumption that building a Rust culture is probably easier than building a C++ culture, because it is easier to get junior developers and those coming from other languages up to speed.
Same here. Clippy and rust compiler made me switch to Rust from c++. Now after experiencing cargo, I find python to be insufferable (tooling, not the language).
Yep. The one big beginner “mistake” I see people make in rust is overusing Box / String / Vec. Rust code that allocates everywhere can be even slower than javascript. The reason? Malloc is slower than you think. Slower than short allocations in V8 or Go. If you want performance, make friends with &str, &[], <I: Iterator<…>>, bumpalo, SmartString and SmallVec. (Or similar crates). Removing allocations from the hot path can improve performance by 10-100x.
That said, most code isn’t a hot path. Performance doesn’t matter in most programs. And if you’re a veteran C++ programmer, none of this will come as a surprise.
I slightly disagree. Using heap allocated types is perfectly fine. The biggest thing I have to keep reminding myself coming from higher level languages is to re-use data structures, and to architect things in a way that this is possible.
Allocating a new String/Vec every single time you do something is killer for performance, but if you do it once up front then clear the data structure for the next use it should be performant enough.
That's funny. I've been going mostly the other direction. I'm avoiding mutable structures whenever possible. I have a much easier time reasoning about stuff when I know that things aren't going to change mid-life.
That is certainly true, but if you are talking about things that are too big to stack allocate, the cognitive overhead of reusing heap allocated items is the price for getting back the throughput overhead of memory allocation.
Does anyone know of any guide/tutorials/books about how to avoid common Rust performance issues. Like real world examples, "instead of doing X, do Y". I am maybe beginner to intermediate in Rust, but I think I'm still very susceptible to those things.
I've observed some level premature optimization in the Rust community, surely coming from being performance oriented.
I received a review comment some time ago about changing a line of code in order to spare one allocation, for a call that was executed _once_ in the whole lifetime of a program. That was not the only time I've observed this attitude.
I think starting with being handy with profiling and only after measurement, thinking about solutions, rather than starting with the idea that certain patterns are harmful per se.
The argument for Rust is rarely that C++ cannot do the same task, it's that Rust provides better guardrails.
Unreadable code is not a C++ specific problem, but does Rust make it easier to write readable code? Probably. Same for memory leaks and other similar problems.
Non-trivial Rust code can be just as unreadable as code one would write in any other language. In fact, some of Rust's features (e.g. lifetime identifiers, functional-ish constructs that people use to create huge call chains with closures everywhere) arguably make it easier to write unreadable code than one might find in other languages.
Some features do both: make it easier to write elegant code, while also making it easier to write unreadable code. Introducing such features is a trade-off and I think they generally choose wisely.
It’s good from a technical perspective but not a business perspective. Startups only get a limited amount of time/money investment in order to prove their profitability. “Writing a better version” can come later, when the startup isn’t trying to come up with a version in the first place.
> * unreadable coding style: This is not a C++ problem.
I would argue that it is, after a few years of Rust. My style in C++ was formed by my exposure to other people's code. I guess this is true for most people.
Certainly, in C++, as well as in any language, Rust included, there are a myriad of ways to express yourself when solving a problem. Is my C++ coding style unreadable? I don't think so. But I used that language for 30+ years. Let's say I only used it for five years -- what then? I would have much less exposure to other people's code and hence to well written/readable code.
Rust has rustfmt (a code formatter) and clippy (a very opinionated linter). And they get used lots. Most Rust CI now includes `cargo fmt --check` and `cargo clippy` runs than need to come out clean.
This goes a long way in making code canonical. Clippy's amazing suggestions also made me a much better Rust developer in a much shorter time.
Are rustfmt & clippy part of "Rust the language"? No. But in a way they are since there is nothing else they compete with for opinion on how Rust code should be formatted and written.
When you onboard new people and they have adapted the pov that this makes lots of sense, it goes a long way in avoiding code being produced that is difficult to read for others.
And because of this, I do indeed think that it is a problem of a programming language, in 2023, if the default tooling does not include such utilities. And a strong incentive through the community, pretty much all the available learning materials and repos in the wild, encouraging their use.
Came to say this exactly. C++ encountered coding styles are often a hodgepodge of "personal preferences" and urban legends. Rust coding style is partly enforced by rustfmt and clippy. The former makes you not worry about mixing styles into a project (after 30 years doing C/C++ I love this), the latter has really good suggestions which makes you reflect on your code.
Using a code formatter in C++ (e.g. via githook or the like) seems still the exception in most commercial C++ codebases I got to look at, when consulting in recent years.
I.e. often there is a mix of styles, indentation/line wrap preferences and even the occasional tab in a codebase that otherwise uses spaces. Etc. etc.
And that's just the formatting part.
Linters seem to be mostly used manually by experienced developers but rarely are part of the commit pipeline or even if they are, their suggestions enforced.
Your mileage may vary. I mostly look at code from a very specific industry. But I can't help but notice these things now, because of my exposure to Rust.
> since C++11 there is no reason for not using smart pointers.
Smart pointers lure you into a dark alley where each tiny object lives in its own tiny heap allocation, and before you know it you have so much memory management sprinkled decentralized all over your code base that the memory management overhead becomes a performance problem, but at the same time it's too late to do anything about it because it would mean rewriting everything (this is then usually when the desperate search for a silver bullet like a "high performance memory allocator" starts).
(not that Rust is necessarily better in that regard when people start to work around borrow checker restrictions with Box and Rc...)
Yes, but people need to be aware that "auto obj = make_unique..." or "auto obj = make_shared..." should be a very rare thing and not the norm (and I've seen plenty code bases like that). There needs to be a proper memory management strategy with the goal of minimizing heap allocation in random places in the code. E.g. automatic memory management doesn't resolve you from thinking just as much about memory management than doing it manually in the first place.
The idea that ref-counting is automatically "better" than a garbage collector is still pretty popular unfortunately (and that's just the tip of the iceberg).
A bump allocator + state of the art compacting GC is MUCH faster on a naïve basis which is why it is important to minimize number of allocations in non-GC langs and use stack based RAII when possible. When building things like trees in a non-GC language, arena allocation should be considered for max performance. This is just another low level vs high level trade off IMO.
> A bump allocator + state of the art compacting GC is MUCH faster
I can see it repeated very often, but can you point me to any evidence for such claim, based on modern low-pause GCs and real data (not simulation)?
I find low pause GCs have pretty substantial overhead and have way lower allocation throughput than old stop-the-world GCs. And the difference between manual memory allocation wasn't that big either (still within 2x).
It's not about what you use to point to the thing. It's about how you allocate the thing in the first place. Smart pointers are like a free pass to do things without consideration: they allow you to make progress without caring how your things are allocated, because they ease the pain that results from just allocating stuff on the global heap, lacking a systematic approach.
Note that while smart pointers ease pain in the short term, there are subtle complications that arise from the constraints that they introduce. One is performance, in some cases the cost of generalized memory management can be too much. Memory fragmentation can be an issue too. RAII the mechanism is not free but requires compatible code and containers. I'm sure there are lots of projects that have broken under the added constraints introduce by such smart classes.
And while smart pointers are orthogonal to systematic memory management, if you get the management right the use of smart pointers can easily become a net negative.
I'm sure it is the same for C++, but in my Rust code things that are put in a Box/Arc etc. are carefully considered and typically my top level business objects. I even wrote my own inline String struct a while back (flexstr) to ensure I don't do allocations for strings smaller than 22 bytes. I don't use allocations "all over the place" without thought and like any language feature, design and placement is important.
That's much more thought put into memory management than what I was used to in the C++ world from 5..15 years ago where many people seemed to have the impression that allocating and freeing memory or the overhead for refcounting is free.
If this is starting to change then it's a good thing.
Decent test coverage and ASAN should be all you need to never have a memory leak in C++. ASAN will even tell you what backtrace allocated the thing in the first place.
I've a feeling it's easier to write decent Rust than decent C++.
The post contains comments about how difficult they found it to keep coding style consistent and language feature use consistent. This suggests to me an inexperienced team without the skills to manage a project of the size and complexity they need.
Now whether with the right team they could produce a better solution in C++ or Rust, i've no idea, but if this is the team they have, then it sounds like Rust might be the right choice for them.
In Rust you can allocate small structs on the stack while being confident that the plain pointer passed down the stack will be valid throughout the function execution.
In C++, you need to use a plain pointer or a unique pointer. The former makes the function leak when passed a pointer to heap.
The latter requires a heap allocation and free for the struct contents.
You probably want to revisit your understanding because what you said doesn't make much sense. Allocating variables on stack and passing them over to other functions is perfectly fine. If you want them to live on a heap that's perfectly fine too.
I used to code primarily in C++ around 12 years ago, then moved over to Python. I've now started with Rust and I really love it. I find myself constantly fighting with the compiler, it telling me what it won't allow me to do.
In C++, threading was my only way to execute parallel tasks, Python 3 showed me a about coroutines, which I've really started to love.
So in Rust I'm experimenting a lot with Tokio right now, and I'm trying to duplicate what I've made in Python. I often think about how good this compiler is that it won't let me do things which I clearly would have done in C++ either to cut corners or, more importantly, out of lack of understanding the consequences.
I was creating this WebSocket server which would serve as a bridge to a MQTT broker, all in async code, all in one big file. I was constantly fighting with the compiler about reusing variables or handing them over to tasks.
When I then attempted to refactor the code by splitting it into several files, the core of the server in main.rs, some WebSocket-related stuff in websocket.rs, all WebSocket-stuff related to the communication with the clients into websocket_handler.rs and all MQTT stuff in mqtt.rs, all my fighting against the compiler fell together. In my inner eye I could see how the variables were handed over to which file during execution, and that this was the reason why I was no longer allowed to use them in the previous file. So much logic, so clear, and the compiler forced me to do it that way.
Then there's the ease of integrating external libraries, which, at least in Windows back then used to be non-trivial in C++.
Cloudflare Workers (serverless) + WebSockets is the lingua franca of the internet now. Using languages with built-in concurrent stream processing features is I feel key to moving at internet speeds ;)
Those are both mostly niche technologies, they're really nowhere near "the lingua franca of the Internet". In fact, "serverless" may well be past its peak, with many having tried it in AWS or Azure a few years ago, and then moving on to Kubernetes to avoid the extreme vendor lock-in. And while there are "serverless" frameworks for K8S, they are not as popular as more traditional deployments.
The point of safer languages is that it can protect you from the person writing the code. Sometimes that person is someone else. Sometimes that person is you. But no matter who the person is they will eventually have a bad day and some of those bad days will not be caught by a C++ compiler and linter. So your last point is I think probably not correct. The truth is that you need both a competent coder and also a language that catches when you are a little off your game. Rust is one of the compilers that help to catch when you are off that game.
Your point that a rewrite is very risky is well made regardless though.
> Memory leak is an old C++ problem, since C++11 there is no reason for not using smart pointers.
C++11 did not invent smart pointers, pretty much every C++ project had already been using them long before they were added to the standard. They help with leaks to some extent, but are not a panacea, I can do a memory leak with shared_ptr in just a few lines of code. I've seen this line of reasoning many times before and it needs to stop.
Indeed, but to be fair, Rust's smart pointers can be used to create memory leaks just as easily as C++'s. (Overall I think Rust is a much better language than C++, though).
There was no way to implement a smart pointer in even a halfway usable and reliable way without move semantics, so C++11 is absolutely essential to use them well. Also I fully agree with the general sentiment. I have not produced a memory leak in many, many years in dozens of hobby projects or in a handful of professional C++ use. It's truly is a giant game changer. You can produce a leak with shared_ptr, but only if you do shit that looks dangerous and stinks to high heavens (a bit similar to the unsafe keyword).
As a long time c++ developer there's a big difference between when something shouldn't happen and when it can't happen. Rust makes certain classes of issues fundamentally impossible (ironically, leaks are possible in Rust), while in C++ it depends on how well you can enforce certain code guidelines on yourself and anyone that works on your same codebase. Also, you get like zero assurances that other people code has been written with the same quality standards as yours, as long as something is very easy to mess up, it will probably be inadvertantly messed up by someone.
> C/C++ is undoubtedly one of the most popular programming languages for building database systems. Most well-known database systems, including MySQL, PostgreSQL, Oracle, and IBM Db2, are created in C/C++.
Considering C and C++ to be the same language is quite a stretch. They are fundamentally different.
It is not a stretch it is just plain wrong. C++ has good C interoperability (most C is even valid C++) and most compilers that support compiling one also support the other, but I can't take seriously anyone that refers to "C/C++" as one language.
Relationship is at best one-way only. C++ can mix and use C code. A C++ compiler will do fine with C. A C++ programmer will do more or less reasonable C code.
C code will not accept C++. A C compiler will not support C++ (unless it's explicitly designed as a C++ compiler too). A C-only programmer will be as lost on a C++ codebase as on a Rust, Go or Java codebase.
Author quoted C/C++, I immediately knew what conclusions I’d find. If on the other hand they had seasoned C++ devs (instead of C/C++), they might have had a different outcome.
That is the current issue with most C++ codebases nowadays, I only see modern C++ on conference slides, when I look into codebases even from ISO C++ members, it is always C++ full of C idioms no matter what.
I bet most candidates to C++ job offers end up discovering the hardly reality of existing code.
That's a fundamental C++ problem. That and all the other idioms it supports. C++ is really like 10 languages and you always have find a mentor to show you the specific one you're working with in a codebase.
While I agree, note that it isn't exclusive of C++, most languages of similar age present similar issues.
How many styles do we now have on C#11, Java 20, Python 3.11, PHP 8.2,....?
This is why static analysis and linters are so relevant for keeping teams into a specific way of doing things, it is not like we can always justify start from scratch into simpler languages.
What is with the modern C++ community treating "C/C++" as a shibboleth to gatekeep over? I'm a seasoned C++ dev (using it before C++98 was available, kept up with trends) and I've never seen this before until the last year or so. I've never had a problem with it as I see my C++ skills being tranferrable to C.
The popular databases we use today such as Postgres and Mysql are pretty terrible. Backups are extremely complicated to set up, and restoring from backups is hard. Multimaster setups almost work, but not completely. You want a geo-distributed high availability database? Forget about it. The popular databases today just don't do the things every web startup wants from a database.
So I totally get why people want to make better database software, but at the same time, I don't understand how startups think the "move fast break things" approach will work here.
The value of a buggy, incomplete, poorly documented database is 0, and the value of a database system that actually works is infinite. It's totally discrete.
How this is not going to end up like every other database startup? Funding gets cut eventually because they can't demonstrate traction, but they can't demonstrate traction until the database product is actually way way better than the old dogs. Which will take 10 years if not 20.
MongoDB is the only new database that managed to break through, and it was a single-threaded document store without proper ACID properties. For a database, it was simple, but it would still regularly eat your data. Today, something like MongoDB would never get traction.
I wish these rising wave guys luck, but I don't see any indication they understand the obstacles they're facing.
> MongoDB is the only new database that managed to break through
Snowflake, Cassandra, DuckDB, Clickhouse, Redis, InfluxDB, DynamoDB, BigQuery etc.
There are many databases that have broken through they just are far more niche focused.
> but it would still regularly eat your data
No it didn't which is why it became so popular. The whole fsync saga was always overblown because (a) every client that shipped set it a safe default anyway and (b) it was fixed almost immediately.
I would love to hear more about "fsync saga" if you have any references.
I know that PostgreSQL had "problems" with fsync(), but they never ended. They just accepted defeat, but so would everyone else who relies on filesystems to store their data. It's even more ingrained than that. The way hardware works, and, especially, the communication protocols around it (eg. SCSI or NVMe) are structured, fsync() is always going to be a problem.
The mongodb organization repeatedly poo-pooed the issues with data loss, and only after repeated public exposure of the issues did they do anything about it. I don't know why people aggressively deny this when anybody can just google it and judge for themselves.
Thanks! This was very interesting. But, did they actually fix this? The three posts are about the problems, but they go up to 3.X version of MongoDB, and the most recent seems to be at 6.X.
Every time I read of memory leaks in C++ codebase, I get no idea why RAII didn't work in those cases. Even if the codebase was huge and complex. Circular references? Some special cases why one can't use RAII?
Forget unique pointer or smart pointers. People had been coding in C++ far before that without fearing memory leaks by following RAII principals.
Unless you are very deep in system / embedded, most of the code that constitutes your program is not your code -- it's various libraries, frameworks, code generated by utilities etc. Often times this is the source of both unsafe interfaces and misunderstanding of the functionality on the part of the developer writing the code.
Second to it is, probably, concurrency. RAII isn't going to save you here either.
Then there's also input processing where you may run into a situation that causes resources not being de-allocated because you never anticipated a particular shape of the input.
RAII works for very local and very well-defined things, it's not a good answer to dynamic situations or resources with complicated ownership.
RAII isn't a perfect safeguard against memory leaks. Rust doesn't provide 100% protection against them, either, especially when `unsafe` gets involved. It's better than C++, though, in this regard. There is no fool-proof way to avoid them, other than by never dynamically allocating memory.
>But as more and more engineers joined us, some shortcomings of C++ came to bite us: unreadable coding style, memory leak, segmentation fault, and more.
- Seasoned devs but they never heard of clang tidy/format
- Memory leaks on a new db codebase where each component should have clear ownership of data or pass to the next pipeline/stage - you dont even need smart poirters here, just a half decent design.
- I am not even going to mention sanitizers, probably rocket science for them
In my experience, segfaults are often a result of using C libraries in C++. In the project I work on, OpenSSL integration supplies a constant trickle of segfaults (it's not my general area, I'm just witnessing those and report to whoever works on it).
This is especially true if you are trying to use those libraries in multi-threaded environment.
Segfaults happen, you run valgrind/asan/tsan etc.
As long as the codebase is not horrendous its easy to fix.
Third party packages complicate things, have to choose/use wisely/appropriately
In Rust they are really rare. Like vanishingly small numbers of them. C++ definitely. SegFaults happen. Sometimes they are even in prod. Rust not so much.
So far there isn't that much stuff written in Rust, so, any non-trivial Rust program will link with a bunch of non-Rust code. On the project I worked on, we had to link with SPDK for example (a rather big iSCSI server implementation).
C++ has been around for... what?.. 40 odd years? And any non-trivial project still links with C libraries.
I don't see this problem somehow going away in Rust w/o some revolutionary changes in operating systems, which is the major supplier of decrepit but unavoidable libraries you have to link with in order to get anything done.
From what I understood, clangd was not enough to make new developers write good enough code.
The problem was not the seasoned core of developers, but the fresh hires.
Now, this would be an interesting problem. Just as Python has PEP8 and some other programmable coding guidelines, we should have different sets of modern programmable C++ coding guidelines, which can be checked by clangd.
And I mean modern, logical, Rust challenging, C++20 coding guidelines. Something this particular team would follow. Nonsense like Orthodox C++ doesn't cut it.
I really like Rust. I like C, and C++ too. I find a lot of C++ and C detractors are nit-picking and over-promising the-new-shiny-thing, or are probably not great engineers to begin with and are blaming the tool. In this instance, I'm leaning towards the latter.
Although Rust is an improvement in many ways, I actually think it is becoming more C++ like with every release. I think it has a good chance of over-taking C++'s complexity, even if it has a much better user story around build & package/module/library management.
As a guy who is writing Rust and found it a true value-add in his career, I agree with this and it's my #1 worry. Rust can already be very arcane to decipher sometimes, especially when you start getting errors from async libraries.
My entirely egotistical opinion is that the maintainers of the language have to take a very good and critical look of the current status quo and start systematically killing off any complexity they can.
Personally I don't want C++ 2.0. Tire people enough and they'll just move to another language again. I know I have, several times in my career, and will do so again if I have to.
> Rust can already be very arcane to decipher sometimes, especially when you start getting errors from async libraries.
For what it's worth, the community, library authors, and most importantly the language design teams are all very aware of this. And there's efforts being made to make all these pain points things more ergonomics and approachable.
I think it just a slower process than we'd like. I think in part it's so slow might be due to how the decision making and work is structured; it's very open, but also slow.
Stuff like GATs took ages to design and implement, and yeet and parts of async are similar. These are done very carefully and they also let decisions marinate for a while before further action.
It's not a critique, since I think it's good and wouldn't know a recommendation to speed it up.
I think GATs in Rust are really cool. Just like template meta programming in C++ is really cool (despite the countless articles on why it shouldn't be used by mere mortals in production code--it's too powerful and unwieldy!). I worry that Rust will become just as arcane as C++ but will look better at a surface level because it has modern and sane defaults and not 40 years of baggage.
Perhaps I'm worried I'm just not smart enough to be a Rust programmer.
Off topic: I also find the Rust community unwelcoming and very clique-ish, I get the very strong "you're not apart of the cool gang" vibes and I'm too old to care to navigate this.
I do understand what you mean abou complexity creep, and hope it doesn't happen, but also fear that it might in due time.
The thing about GAT is that it was never meant to be a feature. It just removes a non-obvious limitation from the language. I remember when learning Rust, I expected "GAT syntax" to just work, and was surprised when it didn't.
So, for me it makes the language less arcane.
> Perhaps I'm worried I'm just not smart enough to be a Rust programmer.
I think everyone can learn anything. It's just a matter of finding the right angle to understand a concept. If something hasn't click, force yourself to use those parts until they do.
> Off topic: I also find the Rust community unwelcoming and very clique-ish, I get the very strong "you're not apart of the cool gang" vibes and I'm too old to care to navigate this.
Ah maybe. I've not experienced this personally, but I've seen others make similar claims. It's generally aways very welcoming from what I've seen. There's the occasional smartass on their Discord, but that's just... Discord Things(TM). People ignore them, and if they're obnoxious they get called out and asked to chill out a bit.
Out of curiosity, what are your main interaction channels/places with the community? Maybe you just accidentally navigated into ones that don't suit you personally
50 / 50. I find the Rust Users discourse forum to be generally welcoming, though sometimes it seems people find your question too obvious and nobody ever responds. I found that showing that I made an effort and pointing at my source of confusion increases engagement. But it might be sensitive to timezones or such as well, no idea.
Rust's Discord however is AMAZINGLY friendly. I've been contacted in DMs by maintainers of very prominent and popular libraries by outlining a problem that I had, in detail.
And finally, r/rust I witnessed first-hand being extremely toxic at times.
Ah, I don't mean to generalise, but most of my experiences on Reddit have been a mixed bag, often more negative. Regardless of the community. I think it's because there's "no barrier to entry" (ie no special sign up, it's just a button). And the design in general feels like it's more suited for short form quippy comments than chatting or discussions.
And I 100% agree that their Discord is great. Also recommend it.
I've seen lots of activity on beginner and intermediate questions though.
As well as just chatting to people, or helping someone with an interesting problem.
I've had a really difficult problem ignored on Discord, but I also think the threading UI on there isn't great for lots of concurrent and unrelated discussions. I just found it frustrating to use. So, maybe some questions fall through the cracks?
Managed to resolve it in the end though. However, having typed all this, I realise a wiser thing would've been to ask on StackOverflow instead lol.
I arrived at the same conclusion. I have faith in Rust's maintainers and I know things can't happen as quickly as I'd like them to. I am still human and can rage when something doesn't go my way -- and it looks easy to me as a side observer -- but I don't judge and I applaud the team's dedication and rigor.
For what it's worth, the C++ maintainers are aware of how arcane and indecipherable their language of choice is, too. The process is even slower because there is a lot of C++ code out there that can't take the same level of change whiplash that Rust changes give you.
I also really like Rust, and I see it as a good replacement of C++, except for one reason: the monoculture around it.
You are expected to use one specific compiler. And there's very little (apparent) interest in actually writing a spec, so that other people can actually try to implement their own compilers with a working borrow checker, compilers capable of compiling rustc without sacrificing soundness (so far the compilers I've seen are lacking borrow checker, for example).
My only remaining hope rests on the Ferrocene people.
So I can see why Rust is being used for user applications, but until that monoculture issue is fixed, I don't really see it replacing C, C++, much less SPARK, as a language for critical systems.
It is my sincere hope that having Rust in the Linux kernel, and in GCC, results in Rust getting an actual spec, so that we can finally know what is expected compiler behavior and what is a bug in rustc, other than "what the rustc from this specific repository does".
Like, for example, Rust 2018 edition is frozen (AFAIK), so that would be a good target for a baseline spec. Could be a more recent edition, even; it doesn't really matter as long as it's something.
> ...it has a much better user story around build & package/module/library management
Cargo sure does, but support for rust outside of cargo is much, much worse than equivalent support for C and C++. It doesn't matter for self-contained projects like simple Makefile ones, but at large scales, moving everything to cargo doesn't seem reasonable right now. Maybe eventually?
Sorry, I was using `pip` as an example of an easy build system to use to get stuff working. Is it as simple as `conan install boost` within a projects dir?
I strongly agree with this. Everyone complains about C and C++ build systems, but they were designed to be easy to begin with. Then projects grew in size and there wasn't a "standard" way to do things so people came up with their own systems. We now seem to be standardizing around CMake for better or worse.
On the flip side, Rust makes the usual cause very easy, with the ability to to pull in code with a single line in a config file (I would argue this is probably a double edged sword - I've some some Rust projects that look like they're a javascript project with a thousand dependencies). I think the "simple" case of compiling Rust without cargo is more complicated and has a higher friction.
Perhaps this isn't fair, complaining about Rust's build system when you're off the beaten path because it's difficult with loose footing. C++ doesn't really have a beaten path (Well since C++17 it's slowly become CMake), that's why all the routes are so well trodden...
It's relevant because many people using Rust are using it for building web backends where high-performance systems language is not needed, yet the safe concurrency is required.
Fascinating how defensive C++ lifers can be. Rust builds on the knowledge of decades of C++ programming. It’s basically a compiler enforced set of C++ best practices. It’s strange how hostile some in the C++ community are to Rust.
I could be wrong, but I think there's few big camps of people.
The camp that thinks Rust is just unnecessary fuss because "you can do it all" in C++ already. They pride themselves with knowing C++ esoterica, and don't like that Rust lowers the entry barrier to writing similar software. They want an exclusive club. They also see ownership as a nuisance. They know you can be equally reckless in Rust too, but they don't like that Rust is so "in your face" about it, too.
The camp that is afraid Rust will marginalise C++ and hence push them towards undesirable (even if high paying) jobs.
There's the camp that's jaded by seeing too many fads come and go, and probably just burnt out at some point. So, they just want to work with what's there and be left alone. They don't want to learn something that they know (incorrectly or not isn't for me to judge here) will be dead in the water soon. And they'll have wasted their energy on it for naught. Or in short, they see it as an unwelcome distraction. This camp also includes "but it has no ISO specification for aviation/etc" too.
I think all these are wrong.
I don't think C++ will be marginalised, it just won't be the default choice for certain domains.
I don't think the extra tooling is a nuisance, if anything in my experience it unburdens the mind from non-domain concerns.
And I also don't think it's a fad, given how productive the language makes people feel, and the fact the Rust Foundation is very serious about the longevity of the project, and that it has many big-player backers.
There's also obviously others too; people come in about 8 billion flavours.
I don't fall into any of the camps you mentioned specifically. I have been using C++ as my main programming language for a good 15 years and am a big fan of modern C++. I tried Rust for a month (every day) and I just feel like it gets in my way too much and it's just not worth the extra friction. A friend of mine (using Python as a physicist) wanted to try system programming recently and I told them to just try Rust and not trouble themselves with C++. I think Rust is the easier language to learn and probably just as powerful, but C++ just gets in your way less. It's not as hard to use correctly as people pretend it is (though I admit that years of experience and studying are required) and if you can use it relatively well you can write safe code without much trouble and you can also have a very high (higher than Rust) level of control seamlessly at the same time.
I don't know many people with similar preferences, but most of them do game development, if that helps to contextualize a bit. There safety is not as important and development speed is much more important than for other applications.
> It's not as hard to use correctly as people pretend it is (though I admit that years of experience and studying are required)
The original statement and the one in parens are directly at odds with each other. If every C++ dev requires years of experience and studying to use correctly, it follows that they have left years worth of code that is not done correctly in their wake. Also, no other (non-esoteric) language requires this high a barrier to write correctly.
> if you can use it relatively well you can write safe code without much trouble
And yet there isn't a single large C++ project that doesn't suffer from violations of memory safety - the one class of bugs that we know how to eliminate completely, if using a proper runtime system.
Ultimately, I'll use what I have to use. I, personally, don't like Rust's syntax and will miss the static inheritance of templates. There's a lot I won't miss, on the other hand
My biggest issue with most Rust posts is that they set up strawman C++ arguments (that are usually just C code targeting a C++ compiler). I'm sold on all the idea behind Rust and making sure that programmers can't just easily drop down to insecure parts of a language - I just don't think we should be shaming good C++ codebases because we want Rust to "win."
You have to remember that we die. So what you learn til 30, say, you capitalise on till 70, and then you retire & die.
There isn't another live to live until 30 "again", and then be within the Rust culture.
Rust has, by analogy, stapled it's "Ninety-five Theses to the door" of C++ and those C++atholics are afraid their way of life is ending before they do.
Taking that analogy further, Catholicism didn't die out. Protestantism definitely grew, then there were hostilities and outright fighting for hundreds of years in some cases.
Well it will suck out a lot of potential jobs from the C++ market, at least in the longer time horizon. And many people invested almost their whole lives into doing C++.
> It’s basically a compiler enforced set of C++ best practices. It’s strange how hostile some in the C++ community are to Rust.
Well, the syntax is alien and new, it doesn't do OO the way 9 out of 10 working developers expect it to, almost all C++ popular design patterns have to be rejected, many of the claims("fearless concurrency") are exaggerated and the Rust evangelists are really really toxic when referring to C++ or C, often simply claiming that fewer bugs is worth the tradeoff from switching to Rust.
I literally saw a comment on HN this past week complaining that OSes are not switching to Rust, almost completely ignoring the fact that any rewrite of a 3 decades old codebase is going to introduce more bugs than it is going to prevent, even if you have perfect memory safety (which you won't, in an OS).
In all honesty, Rust would have been adopted orders of magnitudes faster had Rust evangelists been welcoming, and not accused of being defensive or hostile.
I mean, look through this very page full of comments, and be honest, how many of the comments talking about C++ developers are welcoming to C++ developers?
I've seen an order of magnitude more people complaining about Rust evangelists as I've actually seen Rust evangelists, and they've been significantly more hostile and toxic.
The majority of Rust programmers I know were C++ programmers in the past. Many, including myself, use both professionally.
> I've seen an order of magnitude more people complaining about Rust evangelists as I've actually seen Rust evangelists, and they've been significantly more hostile and toxic.
Does this, to you, look like a response that is welcoming to C++ devs? I gave careful and impassive reasons, and you strike back with literal ad hominem attacks.
This sort of reply is what makes Rust, as a community, look shallow-minded and toxic.
You said Rust evangelists are toxic and exaggerating. I said that I've seen the more of the same in the other direction, and I'm the one striking back with literal ad hominem, and "shallow-minded and toxic"? My response isn't all that difference in tone and content to your own comment, but you've come back way harder at me personally than I was being in general.
I'm not saying it doesn't exist. I'm just saying I've seen way more griping about Rust evangelists than I've seen actual Rust evangelists. For every crazy Rust post like that, I've seen at least 5 of people complaining about crazy rust posts like that. I've seen plenty of articles with comments crapping on Rust evangelists when they weren't even in the comments at all.
There is no "best practice". It depends on context. OOP is good for some things and not that much for others. Same goes for your list of "best" practices. Dismissing a paradigm in totality because some Joe Shmoe of today has declared it non cosher looks rather more like a religious statement than a practical choice.
the fact we might have got sick of your evangelism and lies hasn't crossed your mind I guess
>It’s basically a compiler enforced set of C++ best practices
Its not, its a whole different programming paradigm where the compiler dictates how you write your software. You dont let your creative facilities to drive you or whats best for your domain - you just obey the language rules...
What's often neglected is the excellent tooling around Rust, that alone is reason enough to switch from C++, where you have a really fragmented tooling ecosystem and you're often required to deal with complex Makefiles or build config as well as download dependencies manually. Most of that just disappears with Rust, unless you're developing code that interfaces with existing C/C++ libraries.
C++ could improve its tooling but systems programming is inherently a bit of a fragmented ecosystem. I'm not sure we can shoehorn cargo into all the situations where C, C++, and Fortran have adapted to already.
This, also. C and C++'s build model is a train wreck, especially in C++ code gets rebuilt dozens of times due to headers being simply plopped into whatever translation unit you are building. Rust efficiently solves this by defining building abstractions in the language itself, instead of relying on hacks such as #include, PCH, ...
Has support for these gotten any better? Last time I was reading about it compiler support was under baked at best.
If they get it fully working and stable I agree modules should go a long way to getting rid of it (entirely if you are willing to wrap old header files in modules yourself).
The expression "no brainer" means that some decision is so obvious as to not require any thought. I think this article is saying that using C++ with a team of seasoned C++ developers was such an obvious thing to do that they didn't give it much thought.
Seven months, 10+ team but let’s average that over time to 10. Let‘s take 20 days/month and we arrive at roughly 200LOC per day. C++, database server code. Interesting…
> But as more and more engineers joined us, some shortcomings of C++ came to bite us: unreadable coding style, memory leak, segmentation fault, and more.
One advantage of Rust of C/C++ that is underreported is the that Rust makes it easier to operate a team with diverse levels of experience/expertise. One or two senior engineers set up the tone, design and coding standards. Junior folks try to follow but if they screw up Rust offers more checks and guard rails limiting the blast radius. Many bugs simply do not make past the borrow checker and type system. This also helps when churn and attrition happens in the team. I witnessed quite a few horror stories when aspiring but not-yet competent C++ coders wrecked havoc in C++ code-base when seniors were busy with something else.
As a hobby software engineer who mostly writes ETL jobs in Python the biggest selling point of Rust is Cargo. I usually use a lot of .clone() in my code and most of my fields are Strings which would make a seasoned Rust/C++ laugh at the code. However, the performance of novice Rust beats 10+ years of experience Python by a factor of 10 (favouring Rust).
With Cargo I can build code that just runs. With Python it is always a gamble. Different arch? You need to install different packages to compile the C/C++/Fortran code if the library author did not care about WHL. Starting up an application always a gamble, do we have all the deps? Did we miss some?
And so on. With Rust + Cargo I have confidence that the executable runs. Yes, the compilation is an extra step, but I would have that trade every single time for extra safety and reliability.
> As a hobby software engineer who mostly writes ETL jobs in Python the biggest selling point of Rust is Cargo. I usually use a lot of .clone() in my code and most of my fields are Strings which would make a seasoned Rust/C++ laugh at the code. [...] Yes, the compilation is an extra step, but I would have that trade every single time for extra safety and reliability.
It sounds like you'd be better off with higher-level Haskell for these tasks.
Absolutely not. The last time I have tried Haskell it was failing some pretty basic tasks. The JSON library required to be re-compiled for some reason and it used 20+G of RAM when the build crashed. The community is flat out hostile towards Mac users and a basic request was closed with a comment that Mac is a broken platform and it should not be used. I do not have time for these, Rust offers a much better experience and the community is very helpful even if you are asking silly questions.
> The community is flat out hostile towards Mac users and a basic request was closed with a comment that Mac is a broken platform and it should not be used.
It was years ago, I try to dig up the link on Github but can't even remember which project I was trying to compile. It was about static linking on Mac.
Please do yourself a favor and don’t waste 5m of your life reading this article like I did.
It’s about a team of allegedly experienced C++ developers at a start-up that spent seven months building a project only to spend another two months rewriting it in Rust and then a few more months moving from async to Tokio. But those lost months have not been in vain, because they have 1600 stars on Github. They actually bragged about their Github stars.
It seems the Rust euphoria has reached such levels that people have stopped thinking critically both about the inexplicably bad business decisions and the near-zero technical content described in the article.
You can't revert this trend - C++ is a legacy language being depreciated by more and more projects.
C++ and Rust are simply not competing on the same level. You don't need a complicated "enterprise" building farm/cluster to build your project, dependencies are managed by the guys who also write your compiler, there is a growing community that actually listen to your feedback and you don't need to wait 40 years to get networking support into the standard library. What C++ can offer? Languages like Rust, Golang and Zig all want their users to focus on their applications, while C++ just wants you to focus on C++. OO was a cool concept back in the 90s, but that was 30 years ago when you have 8MBytes of RAM if you are lucky - who wants to model every program using OO in 2023?
It has never been a better time to depreciate the C++ language and codebases written in C++. Museum is a much better place for C++.
I’ve noticed that the tone is becoming rougher with each new Rust story. I’d be curious to know what kind of professional would choose to express themselves in this way, it’s pretty embarrassing.
First of all, that blog post - as many Rust-themed blogs from start-ups - is a submarine article attempting to increase the notoriety of their product. Not enough to disqualify it, but a hint that it won’t necessarily be technically solid.
And indeed, on a technical level it’s superficial and doesn’t give any code examples to substantiate its claims. Code is critically important, because as another recent blog showed, some people don’t know why it’s a bad idea to pass non-zero-terminated char buffers to C string functions and then turn this into a big story about the dangers of C++.
The story also has some red flags, such as not being able to enforce coding standards. Code review is a near-mandatory quality control and teaching method that easily handles this. Clang-format and clang-tidy take care of the low-hanging fruit.
Having segfaults is a really bad sign. So is not mentioning the words address sanitizer, valgrind or similar.
Having memory leaks in 2021 is incomprehensible. This is an amateur mistake of the worst kind in modern C++. It means they’re writing C.
I don’t have time to dig more in depth, but there’s a disturbing lack of critical thinking and skepticism in these comments.
> I’d be curious to know what kind of professional would choose to express themselves in this way, it’s pretty embarrassing.
Embarrassing for pointing out that OO is dead and it is not acceptable to ask users to wait almost 40 years to get networking support into the standard library? No, C++ standard committee members should be embarrassed, not those disappointed users.
> that blog post - as many Rust-themed blogs from start-ups - is a submarine article attempting to increase the notoriety of their product.
As any article published by an commercial entity, it is always about increasing its economic benefits. Personally, I don't know anyone from the company but their blog is just one more success story of depreciating C++ and I applaud for that.
> Having memory leaks in 2021 is incomprehensible. This is an amateur mistake of the worst kind in modern C++.
Sorry but I stopped reading after this. I've been writing software for the past 20 years, worked for the biggest names in industrial, had my PhD in CS about 15 years ago, I write code on almost daily basis (Linux kernel modules, database kernel, infrastructure kind of code). I make the above mentioned amateur mistakes pretty often.
Not saying I am highly skilled, just saying if I can make such mistakes after working 20 years in the field, it wouldn't be rare for other people especially those young developers.
btw, I recently had a nasty memory leak bug in golang that took me a couple days to reproduce and debug, yes, in a GC based language.
Rust asyncio is still in its minimum-viable-product stage. My impression is that it will no long be considered MVP when it has structured concurrency. It would be great if authors posted honest insights about the limitations and work-arounds, if such exist.
I would like to know what the core authors of Materialize or InfluxDB-IOX have to say about using Rust for building a database. They've found the dead bodies, if there are any.
306 comments
[ 1.6 ms ] story [ 291 ms ] threadWhat can’t it do.
And like Linux it’s written in C. Not that means much.
“Never bet against Postgres”.
[1] https://en.wikipedia.org/wiki/PostgreSQL#Release_history
Why not combine Postgres for OLTP workloads alongside another database for fast analytics/time series, optimised to deal with high throughput ingestion and low latency queries?
NB: I am one of the co-founder of an open-source time series database (questdb)
And it's still too easy to shoot yourself in the foot, by deadlocking, or using up all the server's resources with a query that looks very similar to one that was fine.
Stop larping as graybeards, and try to actually do something instead of endlessly bike shedding your cargo cult.
There was also Informix, SYBASE and DB2, but those hardly matter nowadays.
Async I/O.
Almost the same here, have tried just about everything that comes along, and sooner or later I end up swapping out the database de jour and go right back to sql server in almost all use cases (for the type of projects I do).
I feel like db's are pretty much a solved problem, and can't imagine trying to build and market a brand new one these days. Almost as hard as trying to come up with a new operating system and convincing people to switch.
I wish good luck to anyone that tries, but talk about pushing a boulder up a mountain; definitely doesn't seem like the easy path to success.
Fail over without downtime or operator intervention.
Finally somebody understands this.
Rust is not difficult because of lifetimes, it just gets in the way of freely prototyping what you want.
This situation is slowly improving with the compiler getting better and better.
Then there is some annoying macro usage. Some Rust code looks truly alien.
I'm not a rust programmer, but I guess that's an issue if you come from a dynamic language, not from c++.
With Go and Rust I have to make a dedicated function somewhere and then have it be called after starting the program. Ain't exactly rocket science but the difference in time to do it and the convenience is still very stark.
I love working with Rust for the stability and speed it gives me but the value proposition and daily coding flow are VERY different compared to a dynamic language. With Elixir I am mostly just brain-dumping and stuff happens extremely quickly and fluidly, with Rust I kind of sigh and accept that the next 10 minutes I'll just be writing and writing. Might even zone out and make a dumb mistake because I have to spend more keystrokes and more time to do something I'll do in a minute in Elixir.
Maybe it's time to look for snippets support in my editor. Or start asking ChatGPT for them.
I don’t think being able to brain dump code is a good thing and it leads to an unmanageable mess when you have a large codebase. Types are essential as far as I’m concerned, but I constantly have to get into arguments with the dynamic type fans because their “flow” Is being restricted.
Brain-dumping is simply a way to iterate and figure out what works and what doesn't, quickly. After I do it I take the requisite time to emulate exhaustive pattern matching, and add tests that cover the functionality well.
My problem with Rust, and I love the language a lot, is exactly this: I want to quickly find what would work. After that I'm very happy to take the proper time to go things rigorously.
And please don’t say tests solve that because they don’t. They help but they don’t solve it.
Dynamic languages are very valuable when you can afford to iterate and gradually find out the golden path. For the better or the worse, many businesses are of that type.
That being said, I just ended an Elixir contract and absolutely want to code Go or Rust for money again.
I tend to think more than write code, so usually my first go is reasonably close to what I need. But there are always edge cases you just never think about. I'd rather have a strong debugger than a repl imo
You are unfortunately very correct (at least in my 21 years of experience as well). I too feel annoyance when I know that I made a piece of code work well but (a) every now and then I am truly wrong and (b) various pieces of the system in the code interact in sometimes unexpected ways, unveiling inputs to your code that you haven't foreseen.
So even though it often takes a heavy and annoyed sigh out of me, I still roll up my sleeves and add the tests because I've shot myself in the foot too many times, and ignoring past experience is just being a stupido.
As for debugger/REPL, they are not orthogonal; you can have both. I'd more contrast debugger with tests themselves -- both are ways to go step by step through a process that you know is faulty somewhere.
REPL to me is just a way to more quickly sketch a v1.0 of a piece of code, nothing else.
I'll have to check how does NeoVim fare with these things.
Syntax is easy enough. Like all programming languages, you'll get used to it in a weekend and won't even notice it afterwards.
Elixir is absurdly productive: very terse code, very self-explanatory stdlib API, transparent concurrency / parallelism, and in-OS-process high availability and mostly-self-healing hierarchy of green threads and supervisors observing them.
People on HN and Reddit really love to roll their eyes at stuff that's getting popular, and likely will avoid the technology out of a misplaced spite, just because a lot of people are talking about it. It's a weird phenomena.
(Not saying you're doing it, I just kinda got carried away here.)
https://depth-first.com/articles/2020/09/21/interactive-rust...
https://github.com/google/evcxr
The other option is to use the playground, https://play.rust-lang.org/?version=stable&mode=debug&editio...
Is it meaningfully harder than c++ in this regard?
I'd have an easier time prototyping in Rust than C++, and I've been writing C++ for 10 years and Rust for a little over a year.
However, prototype in something like Ruby (or even TypeScript, and some people mentioned Elixir) is in a different universe compared to C++ or Rust.
Like, it's not even a "fair fight" to compare it meaningfully.
I find that modern C++ "kitchen sink" approach to features makes it good for rapid prototyping, a bit like Perl on the dynamic side. It won't force you into a specific approach, pick the one that gets you there the fastest. Use raw pointers and malloc(), or use fancy smart pointers and RAII, your choice, you can also do both, you have exceptions, you have goto, you can write(), printf() and cout, you have classes and lambdas and (multiple) inheritance and traits. More options are better for rapid prototyping.
Also, C++ is the most popular language for competitive programming, you can't get more "rapid" than that.
Now that I say that, I guess someone could write an "unsound helper functions" library that helps you write code full of UB conveniently. It could be an interesting thought experiment. But I don't think the community would be very happy about it...
If it fits the borrow checker well (like in CLI apps, stateless servers, data transformation) then the borrow checker fits beautifully and seamlessly.
In other settings (complex turn-based games, some compilers, GUI), the borrow checker can cause some artificial complexity and prototyping slowdowns compared to other paradigms.
In fact I like Rust for prototyping precisely because I don't yet have tests, and the extra compiler diligence frees me to focus on the prototype.
I don't think that the parent comment implied prototyping in dynamic languages but rather in statically compiled ones.
FWIW in C or C++ you don't have to do as much code gymnastics to satisfy the compiler so consequently prototyping is both faster and easier when compared to Rust.
I've seen way too many half baked attempts at making prototypes fast that do end up in complete rewrites.
Go tell that to a C++ programmer!
;)
When I open something up to read it, to try and understand it, to dig in and fix something broken… having everything be exposed in the explicitly written code… is vastly more useful to me than trying to mentally interpret a language as I read it and remember the rules, the meta-programming rules… and all the implicit stuff that can affect how the program will behave.
Lot of programming languages aren’t good at this explicitness, and I’ll be honest, it’s a genuine struggle for me picking up the languages like this, only made worse when the documentation is very prose like and fails to convey how anything actually works, eschewing that in favour of, at length, demonstrating the feel of a programming language through countless demonstration example that lack mechanical “what is this doing under the hood” explanation.
Rust may influence us into patterns that are better in some (likely even most) situations, but not always. Sometimes the situation calls for other approaches, and that's okay.
Though, people tend to gloss over that C++20 is decently comparable to Rust in terms of semantics and safety, the issue is very few C++ codebases are modern and the footguns are still lurking for the careless.
That said, Rust iterators are very nice and the async story completely mocks the C++20 coroutine nonsense.
I couldn't agree more with this comment. As great as the community is, there's a lot of projects that are just not maintained. I wish this was different.
Also seastar comes with coroutine supports[1], and incidentally it was written for a very high performance C++ database implementation.
[1] https://docs.seastar.io/master/split/5.html
Rust's coroutines currently have practical optimisation issues related to instance size (because the compiler isn't smart enough yet in a few places), and the more powerful generator API very much isn't ready yet, but they give you considerably more control over the memory management. It's easy to stack- or pool-allocate coroutines there if necessary for performance, while in C++ you wouldn't be able to use the native language feature where frequent or unmonitored heap allocations from fine-grained coroutine use would be a problem. (Apparently this makes them unsuitable for AAA game development, for example.)
Library-provided coroutines may be more versatile.
Rust coroutines evaluate to opaque value types instead of handles, for comparison, so the caller gets to decide what to do with them. Currently they're a bit unwieldy though, until naming (aliasing) their types becomes possible. The unstable documentation for that is here: https://rust-lang.github.io/impl-trait-initiative/explainer/...
(Edit: Sorry, I'd grabbed the wrong second link. Fixed.)
At first I even thought it was an argument against Rust, not in favor...
Coroutines in Rust are a native language feature and their API is part of `std`, but the executors indeed come from community libraries.
Tokio is one option, but as long as you don't contextually fork (for parallelism) you can in theory run the same coroutines on any other executor, like the ones from async-std. Spawning a sibling task (as opposed to mixed child task polling, which can be macroed inline) unfortunately isn't available through the common API so far, which is where the bulk of the mentioned incompatibilities stems from.
In other words, it seems Rust co-routines at the level of Tokio are not as performant as C++ native Co-routines [2] and further down the thread, it's mentioned that once generators are stabilized, it might help build lower cost and performant stackless coroutines in Rust.[3]
[1] https://github.com/rust-lang/rust/issues/43122#issuecomment-...
[2] https://github.com/rust-lang/rust/issues/43122#issuecomment-...
[3] https://github.com/rust-lang/rust/issues/43122#issuecomment-...
If you'd like to do modular data processing instead then the current best Rust approach is using `Iterator`s[1] and possibly the `rayon`[2] crate for safe parallelisation.
There currently is no coroutine feature that maps nicely onto `Iterator`s, or rather that's indeed expected to be the unstable generators feature, as it should cover that use case without overhead. (Async-coroutines map onto `Future`[3] instead.)
You can think of Rust's `async` and generator use cases vaguely like the ones of JS's async and generator functions. The latter will function without any runtime or trampoline if you advance it in a loop, as far as I can tell, but they're unwieldy if what you want to yield on are only waits on external events. (`Waker`s[4] have similar consumer semantics to JS's or C#'s continuation passing, even if they are only indirect memory management handles.)
It also often makes sense to use both of these at the same time to produce something like an `AsyncIterator`[5], but I expect that feature to be quite some ways away in Rust, at least in a seamlessly mixing fashion.[6]
- - -
I'm actually pretty curious which will turn out faster in practice between C++'s coroutines and Rust's generators, since their memory management is so different.
The Rust coroutines (that is: including `Future`s) are generally stackless already, but also by default heapless, as their entire memory is abstracted as opaque instance with anonymous type that is returned to the caller by value. Boxing them is an explicit operation, and it's equally possible to pin them on the current stack/in the current instance instead. (That's how `.await` works; the child is embedded into the outer `Future` directly.)
There are some pitfalls related to this, since that instance's size is determined by the largest `.await`/yield site, but the tooling should (eventually) be able to warn on unexpectedly large `.await`/yield locations like it currently warns on unexpectedly large enum variants.[7]
(I'll borrow your footnote style.)
[1] https://doc.rust-lang.org/stable/core/iter/trait.Iterator.ht...
[2] https://crates.io/crates/rayon
[3] https://doc.rust-lang.org/stable/core/future/trait.Future.ht...
[4] https://doc.rust-lang.org/stable/core/task/struct.Waker.html
[5] https://doc.rust-lang.org/stable/core/async_iter/trait.Async...
[6] then comparable to JS, I'd assume, where `yield` and `await` aren't necessarily paired: <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...>
[7] https://rust-lang.github.io/rust-clippy/stable/index.html#...
* unreadable coding style: This is not a C++ problem. * memory leak: Memory leak is an old C++ problem, since C++11 there is no reason for not using smart pointers.
The only point that could be attributed to C++ is the segfaults perhaps, due to its lack of safety. But your other two points made me skeptical about Rust bringing you much benefit. I am specially concerned about throwing away months worth of code. Rewriting everything from scratch is what newbies love to do and will most likely get you in the same mess you were in. Try to learn with the error of others [1]. And btw, the problem is usually who writes the code and not which language is used.
[1] https://www.joelonsoftware.com/2000/04/06/things-you-should-...
- Their product is still relatively new (7 months of coding isn't that much) and not even released,
- they picked a technology specifically designed for the problems they've identified on their existing codebase.
- they completed the rewrite (and weren't stuck having to maintain the old codebase), and are happy with the result.
The risk is losing the current user base.
For this particular software: No users, no market penetration, no risk at all doing a rewrite.
There are many reasons for not using smart pointers, first amongst them for me being performance.
Smart pointers do allow you to remove a large class of memory bugs from your code (albeit not memory leaks) in the same way that Rust's safe references do. However C++ smart pointers impose a run time performance penalty on your code, whereas in Rust the checks happen at compile time leading to better runtime performance.
But even if you had to, what implications would it have, if you care to explain?
Stack overflow says "delete" would check for null before deallocation: https://stackoverflow.com/questions/4190703/is-it-safe-to-de...
Happy to be educated
That said, if this really had been an overhead, virtually every language out there would suffer from it, including Rust. Every language out there at some point needs to call into the libc.
PS: small overhead is technically still overhead; yet, I am not saying you should worry about it
Overhead is almost purely theoretical and it cannot be avoided and is not anything common or specific to unique_ptr's.
> Can you point me to any significant primarily rust codebase that runs sanitizers? I've never heard of that
Not sure what do you mean by that, surely there are. At least the ones who are serious about the development. Sanitizers are part of official documentation in Rust [2].
[1] https://github.com/rust-lang/rust/issues/39699
[2] https://doc.rust-lang.org/unstable-book/compiler-flags/sanit...
The compiler is happy to compile without sanitizers enabled. Why should it require to implement a null check when deallocating when it doesn't when dereferencing?
Also, even if you chose to use some libc for system calls, there is no reason to use malloc()/free(). You only need mmap() or similar, and then your own language runtime can write their own user-space memory manager.
As a side-note, on Windows, libc isn't even a system library. The official way to execute system calls is using win32, and things like malloc()/free() are simply wrappers around HeapAlloc() and HeapFree().
i'm not sure if this is the case. unique_ptr doesn't really do much other than use the type system to ensure that only one instance of the pointed-to value exists at once. as far as i understand, it doesn't strictly do anything at runtime.
https://www.youtube.com/watch?v=rHIkrotSwcc
At 18 min.
Technically it is correct, it causes an extremly light overhead due to the inability of the compiler to optimise a part of it.
In practice, even in HPC, I never notice it to have an impact ever.
And as an advise for any new C++ programmers: Please JUST use unique_ptr, everywhere, all the time...
Trying to manage the lifetime manually with new/delete in modern C++ is not worth the cost in 99.99% of the case. If the impact of unique_ptr is noticeable in your program, you are very likely in a realm where you should not even doing memory allocation anyway.
What the "overhead" of unique_ptr is usually attached to is the inability for a compiler to pass the unique_ptr as a value through a register but will instead have to use the stack (memory). And that even doesn't apply in the general case but _only_ for unique_ptrs holding an object with non-trivial copy-constructors or non-trivial destructors. This is due to the platform ABI and not the C++ compiler limitation.
Anyway, calling that an overhead is a far stretch and almost purely theoretical unless someone is able to measure the negative effect of such code transformation in the real-world codebase. And I say this as not particularly heavy user of smart pointers.
Also, many other codegen transformations will not fit into a very limited amount of ABI registers so should we argue about not using those as well?
In my opinion, this was only a "campaign" of Google trying to use a unique_ptr as a leverage to persuade the committee to accept their break-the-world ABI suggestion. We know how it all went.
Ye well I knew the overhead was really small.
For shared_ptr, the atomic ref counting can cause surprising overhead due to contention in multi-threaded scenarios, even if just accessing the pointer, depending on how the shared_ptr is passed through functions...
Much nicer than hacky ifdefs.
This is exactly what I need. For both, C++ and Rust smart pointers.
Can you share any more info on how to set this up?
https://sourceware.org/gdb/onlinedocs/gdb/Skipping-Over-Func...
This was my first thought, but then I realised newbies would have started with Rust. :)
In the first few months of a big build a huge amount of time and effort goes into the foundation: design, POCs, setting up environments, CI, testing infrastructure…
My guess is that they weren’t very deep in production code, and the fact that they didn’t fall for the sunk cost fallacy speaks highly for them.
Sadly there is, lack of security culture and plenty of devs won't allow them on a PR.
Wow. Genuinely surprised.
Rust is naturally safer than C++, however there are still many domains where a bit of yak shaving is required before actually coding what one cares about.
So it boils down to where to spend resources, and as note, I am definitly not a fan of Orthodox C++ ideas, rather having C++ improve its safety story as much as possible.
Orthodox C++ can be safely ignored by any sane developer.
And, again, people talk about it as if it was a real thing and they knew how to measure it...
Also, C++ and Rust are very similar in appearance. So, I struggle to see how jumping ship here would be a big win.
That said, most code isn’t a hot path. Performance doesn’t matter in most programs. And if you’re a veteran C++ programmer, none of this will come as a surprise.
Allocating a new String/Vec every single time you do something is killer for performance, but if you do it once up front then clear the data structure for the next use it should be performant enough.
That's funny. I've been going mostly the other direction. I'm avoiding mutable structures whenever possible. I have a much easier time reasoning about stuff when I know that things aren't going to change mid-life.
Also, that is exactly what Rust's borrow-checker is there for. It doesn't allow you to mutably borrow the same data structure multiple times.
I received a review comment some time ago about changing a line of code in order to spare one allocation, for a call that was executed _once_ in the whole lifetime of a program. That was not the only time I've observed this attitude.
I think starting with being handy with profiling and only after measurement, thinking about solutions, rather than starting with the idea that certain patterns are harmful per se.
Slower than V8, definitely possible. Slower than Go, very unlikely, since it doesn't have a generational or compacting gc.
Unreadable code is not a C++ specific problem, but does Rust make it easier to write readable code? Probably. Same for memory leaks and other similar problems.
The C++ programmers that love over-complicated, read-only code would be right at home in Rust. In fact they’re probably working on it right now :-)
As the system grows, you realize all that was wrong with your previous version, and can write a new better one.
That doesn't mean you need to switch to another language to do it though.
In particular for a product like this which is itself targeting developers.
I would argue that it is, after a few years of Rust. My style in C++ was formed by my exposure to other people's code. I guess this is true for most people.
Certainly, in C++, as well as in any language, Rust included, there are a myriad of ways to express yourself when solving a problem. Is my C++ coding style unreadable? I don't think so. But I used that language for 30+ years. Let's say I only used it for five years -- what then? I would have much less exposure to other people's code and hence to well written/readable code.
Rust has rustfmt (a code formatter) and clippy (a very opinionated linter). And they get used lots. Most Rust CI now includes `cargo fmt --check` and `cargo clippy` runs than need to come out clean.
This goes a long way in making code canonical. Clippy's amazing suggestions also made me a much better Rust developer in a much shorter time.
Are rustfmt & clippy part of "Rust the language"? No. But in a way they are since there is nothing else they compete with for opinion on how Rust code should be formatted and written.
When you onboard new people and they have adapted the pov that this makes lots of sense, it goes a long way in avoiding code being produced that is difficult to read for others.
And because of this, I do indeed think that it is a problem of a programming language, in 2023, if the default tooling does not include such utilities. And a strong incentive through the community, pretty much all the available learning materials and repos in the wild, encouraging their use.
I.e. often there is a mix of styles, indentation/line wrap preferences and even the occasional tab in a codebase that otherwise uses spaces. Etc. etc. And that's just the formatting part. Linters seem to be mostly used manually by experienced developers but rarely are part of the commit pipeline or even if they are, their suggestions enforced.
Your mileage may vary. I mostly look at code from a very specific industry. But I can't help but notice these things now, because of my exposure to Rust.
Smart pointers lure you into a dark alley where each tiny object lives in its own tiny heap allocation, and before you know it you have so much memory management sprinkled decentralized all over your code base that the memory management overhead becomes a performance problem, but at the same time it's too late to do anything about it because it would mean rewriting everything (this is then usually when the desperate search for a silver bullet like a "high performance memory allocator" starts).
(not that Rust is necessarily better in that regard when people start to work around borrow checker restrictions with Box and Rc...)
I can see it repeated very often, but can you point me to any evidence for such claim, based on modern low-pause GCs and real data (not simulation)?
I find low pause GCs have pretty substantial overhead and have way lower allocation throughput than old stop-the-world GCs. And the difference between manual memory allocation wasn't that big either (still within 2x).
Note that while smart pointers ease pain in the short term, there are subtle complications that arise from the constraints that they introduce. One is performance, in some cases the cost of generalized memory management can be too much. Memory fragmentation can be an issue too. RAII the mechanism is not free but requires compatible code and containers. I'm sure there are lots of projects that have broken under the added constraints introduce by such smart classes.
And while smart pointers are orthogonal to systematic memory management, if you get the management right the use of smart pointers can easily become a net negative.
"It is complicated so let's see if there is a simpler approach".
If this is starting to change then it's a good thing.
I've a feeling it's easier to write decent Rust than decent C++.
The post contains comments about how difficult they found it to keep coding style consistent and language feature use consistent. This suggests to me an inexperienced team without the skills to manage a project of the size and complexity they need.
Now whether with the right team they could produce a better solution in C++ or Rust, i've no idea, but if this is the team they have, then it sounds like Rust might be the right choice for them.
In C++, you need to use a plain pointer or a unique pointer. The former makes the function leak when passed a pointer to heap.
The latter requires a heap allocation and free for the struct contents.
In C++, threading was my only way to execute parallel tasks, Python 3 showed me a about coroutines, which I've really started to love.
So in Rust I'm experimenting a lot with Tokio right now, and I'm trying to duplicate what I've made in Python. I often think about how good this compiler is that it won't let me do things which I clearly would have done in C++ either to cut corners or, more importantly, out of lack of understanding the consequences.
I was creating this WebSocket server which would serve as a bridge to a MQTT broker, all in async code, all in one big file. I was constantly fighting with the compiler about reusing variables or handing them over to tasks.
When I then attempted to refactor the code by splitting it into several files, the core of the server in main.rs, some WebSocket-related stuff in websocket.rs, all WebSocket-stuff related to the communication with the clients into websocket_handler.rs and all MQTT stuff in mqtt.rs, all my fighting against the compiler fell together. In my inner eye I could see how the variables were handed over to which file during execution, and that this was the reason why I was no longer allowed to use them in the previous file. So much logic, so clear, and the compiler forced me to do it that way.
Then there's the ease of integrating external libraries, which, at least in Windows back then used to be non-trivial in C++.
Your point that a rewrite is very risky is well made regardless though.
What both of those had in common was a single strong tech lead that would veto code with no argument if it didn’t meet standards.
I’ve yet to work on Rust but I’ve seen horrific and buggy code in C++, C, Java, Kotlin, C# and of course JavaScript and Python.
C++11 did not invent smart pointers, pretty much every C++ project had already been using them long before they were added to the standard. They help with leaks to some extent, but are not a panacea, I can do a memory leak with shared_ptr in just a few lines of code. I've seen this line of reasoning many times before and it needs to stop.
They certainly pay better, upfront, than a startup does.
> C/C++ is undoubtedly one of the most popular programming languages for building database systems. Most well-known database systems, including MySQL, PostgreSQL, Oracle, and IBM Db2, are created in C/C++.
Considering C and C++ to be the same language is quite a stretch. They are fundamentally different.
C code will not accept C++. A C compiler will not support C++ (unless it's explicitly designed as a C++ compiler too). A C-only programmer will be as lost on a C++ codebase as on a Rust, Go or Java codebase.
I bet most candidates to C++ job offers end up discovering the hardly reality of existing code.
How many styles do we now have on C#11, Java 20, Python 3.11, PHP 8.2,....?
This is why static analysis and linters are so relevant for keeping teams into a specific way of doing things, it is not like we can always justify start from scratch into simpler languages.
So I totally get why people want to make better database software, but at the same time, I don't understand how startups think the "move fast break things" approach will work here.
The value of a buggy, incomplete, poorly documented database is 0, and the value of a database system that actually works is infinite. It's totally discrete.
How this is not going to end up like every other database startup? Funding gets cut eventually because they can't demonstrate traction, but they can't demonstrate traction until the database product is actually way way better than the old dogs. Which will take 10 years if not 20.
MongoDB is the only new database that managed to break through, and it was a single-threaded document store without proper ACID properties. For a database, it was simple, but it would still regularly eat your data. Today, something like MongoDB would never get traction.
I wish these rising wave guys luck, but I don't see any indication they understand the obstacles they're facing.
Snowflake, Cassandra, DuckDB, Clickhouse, Redis, InfluxDB, DynamoDB, BigQuery etc.
There are many databases that have broken through they just are far more niche focused.
> but it would still regularly eat your data
No it didn't which is why it became so popular. The whole fsync saga was always overblown because (a) every client that shipped set it a safe default anyway and (b) it was fixed almost immediately.
I know that PostgreSQL had "problems" with fsync(), but they never ended. They just accepted defeat, but so would everyone else who relies on filesystems to store their data. It's even more ingrained than that. The way hardware works, and, especially, the communication protocols around it (eg. SCSI or NVMe) are structured, fsync() is always going to be a problem.
The mongodb organization repeatedly poo-pooed the issues with data loss, and only after repeated public exposure of the issues did they do anything about it. I don't know why people aggressively deny this when anybody can just google it and judge for themselves.
All of the clients set safe defaults and the documentation was very clear about default fsync behaviour.
Forget unique pointer or smart pointers. People had been coding in C++ far before that without fearing memory leaks by following RAII principals.
Second to it is, probably, concurrency. RAII isn't going to save you here either.
Then there's also input processing where you may run into a situation that causes resources not being de-allocated because you never anticipated a particular shape of the input.
RAII works for very local and very well-defined things, it's not a good answer to dynamic situations or resources with complicated ownership.
- Seasoned devs but they never heard of clang tidy/format - Memory leaks on a new db codebase where each component should have clear ownership of data or pass to the next pipeline/stage - you dont even need smart poirters here, just a half decent design. - I am not even going to mention sanitizers, probably rocket science for them
This is especially true if you are trying to use those libraries in multi-threaded environment.
C++ has been around for... what?.. 40 odd years? And any non-trivial project still links with C libraries.
I don't see this problem somehow going away in Rust w/o some revolutionary changes in operating systems, which is the major supplier of decrepit but unavoidable libraries you have to link with in order to get anything done.
The problem was not the seasoned core of developers, but the fresh hires.
Now, this would be an interesting problem. Just as Python has PEP8 and some other programmable coding guidelines, we should have different sets of modern programmable C++ coding guidelines, which can be checked by clangd.
And I mean modern, logical, Rust challenging, C++20 coding guidelines. Something this particular team would follow. Nonsense like Orthodox C++ doesn't cut it.
Although Rust is an improvement in many ways, I actually think it is becoming more C++ like with every release. I think it has a good chance of over-taking C++'s complexity, even if it has a much better user story around build & package/module/library management.
My entirely egotistical opinion is that the maintainers of the language have to take a very good and critical look of the current status quo and start systematically killing off any complexity they can.
Personally I don't want C++ 2.0. Tire people enough and they'll just move to another language again. I know I have, several times in my career, and will do so again if I have to.
For what it's worth, the community, library authors, and most importantly the language design teams are all very aware of this. And there's efforts being made to make all these pain points things more ergonomics and approachable.
I think it just a slower process than we'd like. I think in part it's so slow might be due to how the decision making and work is structured; it's very open, but also slow.
Stuff like GATs took ages to design and implement, and yeet and parts of async are similar. These are done very carefully and they also let decisions marinate for a while before further action.
It's not a critique, since I think it's good and wouldn't know a recommendation to speed it up.
So, it's getting better, but slowly
Perhaps I'm worried I'm just not smart enough to be a Rust programmer.
Off topic: I also find the Rust community unwelcoming and very clique-ish, I get the very strong "you're not apart of the cool gang" vibes and I'm too old to care to navigate this.
The thing about GAT is that it was never meant to be a feature. It just removes a non-obvious limitation from the language. I remember when learning Rust, I expected "GAT syntax" to just work, and was surprised when it didn't.
So, for me it makes the language less arcane.
> Perhaps I'm worried I'm just not smart enough to be a Rust programmer.
I think everyone can learn anything. It's just a matter of finding the right angle to understand a concept. If something hasn't click, force yourself to use those parts until they do.
> Off topic: I also find the Rust community unwelcoming and very clique-ish, I get the very strong "you're not apart of the cool gang" vibes and I'm too old to care to navigate this.
Ah maybe. I've not experienced this personally, but I've seen others make similar claims. It's generally aways very welcoming from what I've seen. There's the occasional smartass on their Discord, but that's just... Discord Things(TM). People ignore them, and if they're obnoxious they get called out and asked to chill out a bit.
Out of curiosity, what are your main interaction channels/places with the community? Maybe you just accidentally navigated into ones that don't suit you personally
Rust's Discord however is AMAZINGLY friendly. I've been contacted in DMs by maintainers of very prominent and popular libraries by outlining a problem that I had, in detail.
And finally, r/rust I witnessed first-hand being extremely toxic at times.
It really depends where you're looking.
And I 100% agree that their Discord is great. Also recommend it.
I've seen lots of activity on beginner and intermediate questions though.
As well as just chatting to people, or helping someone with an interesting problem.
I've had a really difficult problem ignored on Discord, but I also think the threading UI on there isn't great for lots of concurrent and unrelated discussions. I just found it frustrating to use. So, maybe some questions fall through the cracks?
Managed to resolve it in the end though. However, having typed all this, I realise a wiser thing would've been to ask on StackOverflow instead lol.
I arrived at the same conclusion. I have faith in Rust's maintainers and I know things can't happen as quickly as I'd like them to. I am still human and can rage when something doesn't go my way -- and it looks easy to me as a side observer -- but I don't judge and I applaud the team's dedication and rigor.
You are expected to use one specific compiler. And there's very little (apparent) interest in actually writing a spec, so that other people can actually try to implement their own compilers with a working borrow checker, compilers capable of compiling rustc without sacrificing soundness (so far the compilers I've seen are lacking borrow checker, for example).
My only remaining hope rests on the Ferrocene people.
So I can see why Rust is being used for user applications, but until that monoculture issue is fixed, I don't really see it replacing C, C++, much less SPARK, as a language for critical systems.
It is my sincere hope that having Rust in the Linux kernel, and in GCC, results in Rust getting an actual spec, so that we can finally know what is expected compiler behavior and what is a bug in rustc, other than "what the rustc from this specific repository does".
Like, for example, Rust 2018 edition is frozen (AFAIK), so that would be a good target for a baseline spec. Could be a more recent edition, even; it doesn't really matter as long as it's something.
Cargo sure does, but support for rust outside of cargo is much, much worse than equivalent support for C and C++. It doesn't matter for self-contained projects like simple Makefile ones, but at large scales, moving everything to cargo doesn't seem reasonable right now. Maybe eventually?
A lot of folks use Conan or vcpkg for pure C++ dev.
On the flip side, Rust makes the usual cause very easy, with the ability to to pull in code with a single line in a config file (I would argue this is probably a double edged sword - I've some some Rust projects that look like they're a javascript project with a thousand dependencies). I think the "simple" case of compiling Rust without cargo is more complicated and has a higher friction.
Perhaps this isn't fair, complaining about Rust's build system when you're off the beaten path because it's difficult with loose footing. C++ doesn't really have a beaten path (Well since C++17 it's slowly become CMake), that's why all the routes are so well trodden...
C++ is also becoming better with every release, and C++20 is a huge improvement.
In all honesty, code written in C++20 feels just like code I have written in Python and/or JavaScript. And 20–40 times faster.
The camp that thinks Rust is just unnecessary fuss because "you can do it all" in C++ already. They pride themselves with knowing C++ esoterica, and don't like that Rust lowers the entry barrier to writing similar software. They want an exclusive club. They also see ownership as a nuisance. They know you can be equally reckless in Rust too, but they don't like that Rust is so "in your face" about it, too.
The camp that is afraid Rust will marginalise C++ and hence push them towards undesirable (even if high paying) jobs.
There's the camp that's jaded by seeing too many fads come and go, and probably just burnt out at some point. So, they just want to work with what's there and be left alone. They don't want to learn something that they know (incorrectly or not isn't for me to judge here) will be dead in the water soon. And they'll have wasted their energy on it for naught. Or in short, they see it as an unwelcome distraction. This camp also includes "but it has no ISO specification for aviation/etc" too.
I think all these are wrong.
I don't think C++ will be marginalised, it just won't be the default choice for certain domains.
I don't think the extra tooling is a nuisance, if anything in my experience it unburdens the mind from non-domain concerns.
And I also don't think it's a fad, given how productive the language makes people feel, and the fact the Rust Foundation is very serious about the longevity of the project, and that it has many big-player backers.
There's also obviously others too; people come in about 8 billion flavours.
The original statement and the one in parens are directly at odds with each other. If every C++ dev requires years of experience and studying to use correctly, it follows that they have left years worth of code that is not done correctly in their wake. Also, no other (non-esoteric) language requires this high a barrier to write correctly.
> if you can use it relatively well you can write safe code without much trouble
And yet there isn't a single large C++ project that doesn't suffer from violations of memory safety - the one class of bugs that we know how to eliminate completely, if using a proper runtime system.
Do we? Why exactly do we need sanitizers in Rust then?
My biggest issue with most Rust posts is that they set up strawman C++ arguments (that are usually just C code targeting a C++ compiler). I'm sold on all the idea behind Rust and making sure that programmers can't just easily drop down to insecure parts of a language - I just don't think we should be shaming good C++ codebases because we want Rust to "win."
There isn't another live to live until 30 "again", and then be within the Rust culture.
Rust has, by analogy, stapled it's "Ninety-five Theses to the door" of C++ and those C++atholics are afraid their way of life is ending before they do.
False BS
>"those C++atholics are afraid their way of life is ending before they do"
We are into insults area now.
Well, the syntax is alien and new, it doesn't do OO the way 9 out of 10 working developers expect it to, almost all C++ popular design patterns have to be rejected, many of the claims("fearless concurrency") are exaggerated and the Rust evangelists are really really toxic when referring to C++ or C, often simply claiming that fewer bugs is worth the tradeoff from switching to Rust.
I literally saw a comment on HN this past week complaining that OSes are not switching to Rust, almost completely ignoring the fact that any rewrite of a 3 decades old codebase is going to introduce more bugs than it is going to prevent, even if you have perfect memory safety (which you won't, in an OS).
In all honesty, Rust would have been adopted orders of magnitudes faster had Rust evangelists been welcoming, and not accused of being defensive or hostile.
I mean, look through this very page full of comments, and be honest, how many of the comments talking about C++ developers are welcoming to C++ developers?
The majority of Rust programmers I know were C++ programmers in the past. Many, including myself, use both professionally.
Does this, to you, look like a response that is welcoming to C++ devs? I gave careful and impassive reasons, and you strike back with literal ad hominem attacks.
This sort of reply is what makes Rust, as a community, look shallow-minded and toxic.
That jumble of ideas is a good example of the arrogance directed not only at C++ programmers, but also Golang and C.
- Smart pointers
- auto and const references all over the place
- RAII
- Pure data structs
- Free functions
- A little bit of templating but not too crazy
Modern C++ reads a bit like JavaScript strangely!
I yield to your comment.
I didn't say it was.
I didn't say anything about best practice, only about familiarity.
I like the language. I really don't want to deal with their community.
>It’s basically a compiler enforced set of C++ best practices
Its not, its a whole different programming paradigm where the compiler dictates how you write your software. You dont let your creative facilities to drive you or whats best for your domain - you just obey the language rules...
If they get it fully working and stable I agree modules should go a long way to getting rid of it (entirely if you are willing to wrap old header files in modules yourself).
All my hobby coding in C++ uses modules nowadays.
There is plenty of C++ tooling for GPGPU, game engines, IDE, GUI programming, HPC,... that Rust still lacks.
In what concerns cargo, vcpkg and Conan are good enough, and support binary libraries, no need to compile everything from scratch.
Oooff.
Seven months, 10+ team but let’s average that over time to 10. Let‘s take 20 days/month and we arrive at roughly 200LOC per day. C++, database server code. Interesting…
Yes
> But as more and more engineers joined us, some shortcomings of C++ came to bite us: unreadable coding style, memory leak, segmentation fault, and more.
One advantage of Rust of C/C++ that is underreported is the that Rust makes it easier to operate a team with diverse levels of experience/expertise. One or two senior engineers set up the tone, design and coding standards. Junior folks try to follow but if they screw up Rust offers more checks and guard rails limiting the blast radius. Many bugs simply do not make past the borrow checker and type system. This also helps when churn and attrition happens in the team. I witnessed quite a few horror stories when aspiring but not-yet competent C++ coders wrecked havoc in C++ code-base when seniors were busy with something else.
With Cargo I can build code that just runs. With Python it is always a gamble. Different arch? You need to install different packages to compile the C/C++/Fortran code if the library author did not care about WHL. Starting up an application always a gamble, do we have all the deps? Did we miss some?
And so on. With Rust + Cargo I have confidence that the executable runs. Yes, the compilation is an extra step, but I would have that trade every single time for extra safety and reliability.
It sounds like you'd be better off with higher-level Haskell for these tasks.
Have you got a link to that request?
It’s about a team of allegedly experienced C++ developers at a start-up that spent seven months building a project only to spend another two months rewriting it in Rust and then a few more months moving from async to Tokio. But those lost months have not been in vain, because they have 1600 stars on Github. They actually bragged about their Github stars.
It seems the Rust euphoria has reached such levels that people have stopped thinking critically both about the inexplicably bad business decisions and the near-zero technical content described in the article.
C++ and Rust are simply not competing on the same level. You don't need a complicated "enterprise" building farm/cluster to build your project, dependencies are managed by the guys who also write your compiler, there is a growing community that actually listen to your feedback and you don't need to wait 40 years to get networking support into the standard library. What C++ can offer? Languages like Rust, Golang and Zig all want their users to focus on their applications, while C++ just wants you to focus on C++. OO was a cool concept back in the 90s, but that was 30 years ago when you have 8MBytes of RAM if you are lucky - who wants to model every program using OO in 2023?
It has never been a better time to depreciate the C++ language and codebases written in C++. Museum is a much better place for C++.
First of all, that blog post - as many Rust-themed blogs from start-ups - is a submarine article attempting to increase the notoriety of their product. Not enough to disqualify it, but a hint that it won’t necessarily be technically solid.
And indeed, on a technical level it’s superficial and doesn’t give any code examples to substantiate its claims. Code is critically important, because as another recent blog showed, some people don’t know why it’s a bad idea to pass non-zero-terminated char buffers to C string functions and then turn this into a big story about the dangers of C++.
The story also has some red flags, such as not being able to enforce coding standards. Code review is a near-mandatory quality control and teaching method that easily handles this. Clang-format and clang-tidy take care of the low-hanging fruit.
Having segfaults is a really bad sign. So is not mentioning the words address sanitizer, valgrind or similar.
Having memory leaks in 2021 is incomprehensible. This is an amateur mistake of the worst kind in modern C++. It means they’re writing C.
I don’t have time to dig more in depth, but there’s a disturbing lack of critical thinking and skepticism in these comments.
Embarrassing for pointing out that OO is dead and it is not acceptable to ask users to wait almost 40 years to get networking support into the standard library? No, C++ standard committee members should be embarrassed, not those disappointed users.
> that blog post - as many Rust-themed blogs from start-ups - is a submarine article attempting to increase the notoriety of their product.
As any article published by an commercial entity, it is always about increasing its economic benefits. Personally, I don't know anyone from the company but their blog is just one more success story of depreciating C++ and I applaud for that.
> Having memory leaks in 2021 is incomprehensible. This is an amateur mistake of the worst kind in modern C++.
Sorry but I stopped reading after this. I've been writing software for the past 20 years, worked for the biggest names in industrial, had my PhD in CS about 15 years ago, I write code on almost daily basis (Linux kernel modules, database kernel, infrastructure kind of code). I make the above mentioned amateur mistakes pretty often.
Not saying I am highly skilled, just saying if I can make such mistakes after working 20 years in the field, it wouldn't be rare for other people especially those young developers.
btw, I recently had a nasty memory leak bug in golang that took me a couple days to reproduce and debug, yes, in a GC based language.
This one hurts, but so true =)
I would like to know what the core authors of Materialize or InfluxDB-IOX have to say about using Rust for building a database. They've found the dead bodies, if there are any.
I would love to hear how you explained this to your investors.