Live data from Hacker News

Being fair about memory safety and performance

thecodedmessage.com

21–30 of 75 posts

Re: Being fair about memory safety and performance

#21
> To review, where do Rust and C++, these programming languages with their vastly different philosophies, Rust for the cautious, C++ for the fast and bold, stand? In the exact same place.

The author spent 1 page before this statement, and the whole article after it, explaining that this is not true, so the article is a big contradiction.

Rust and C++ are not "in the exact same place".

With Rust, you get bound checking by default. If, after profiling, you find that it is a performance problem somewhere, it allows you to elide it safely. In the programs I work on, 99% of the execution time of my program is spent in 1% of the code, and Rust optimizes for this situation. Instead of debugging segmentation faults due to performance optimizations that buy you nothing in 99% of the code, you can spend your time optimizing the 1% that actually makes a difference.

This is why Rust libraries are program are "so fast". Its not because of multi threading, or because rust programmers are geniuses, but rather because Rust buys these programmer time to actually optimize the code that matters, and in particular, do so without introducing new bugs.

Re: Being fair about memory safety and performance

#22
post #6

There's a presumption here that checked access would cost some nr of nanoseconds per access, but this often isn't the case since predicted, not-taken branches tend to have 0 cycle latency in recent CPUs.

> predicted, not-taken branches tend to have 0 cycle latency in recent CPUs. This is not the case. Due to instruction level parallelism, the throughput could be unaffected, but you will always have latency penalty. The CPU still needs to run the check (access the length and compare it to the index) and this adds latency. On top of that, it also increases code size, which can impact the instruction cache and binary si…

Speculative execution enables continuing along the predicted branch without stopping. You do need to have the ~2 instructions to get the length test input on hand but that usually can be eaten by insn level parallelism without hurting the latency of the array operation.

Re: Being fair about memory safety and performance

#23

> I learned that the issue was in framework code – code written by my boss’s boss. The code was untested, and written extremely poorly, and had rotted, so that it didn’t work at all. One unaddressed issue in Rust is that this could easily happen with a crate, and how hard diagnosing it could be, especially due to implicit behavior via procedural and attribute macros. Also, just because your code is safe, there could…

the are 2 answers here. the first is that the crate is less likely than a c++ library to have this bug since stuff is safe by default. the second is that having a smaller set of unsafe stuff in your code base makes it easier to rule out your code as the problem.

Re: Being fair about memory safety and performance

#24
post #12

I'm not quite sure who this article is aimed at, and who those "C++ apologists" are, but as someone who programs in C++ all day, doesn't like it at all, and yet won't advocate to switch to Rust, these kinds of arguments are unconvincing. I'm not advocating to switch to Rust not because I don't think it's better than C++. I am absolutely, 100% convinced that Rust is technically better than C++ in most possible ways —…

It is the first time, I have heard of zig and I have to say, it indeed does sound nice. (But I haven't done low level programming in quite some time ..)

Can you maybe summarize a bit more, why you prefer it over rust?

The concept of rust, of beeing safe by default and only optimize critical parts sounds solid to me, but after a quick skimming, I have not seen such a feature for zig, too, possibly by design?

" No hidden control flow. No hidden memory allocations. No preprocessor, no macros."

Re: Being fair about memory safety and performance

#25
I don't know what people mean when they talk about "safe" or "unsafe" code. Doing something like `int a[5]; a[2] = 100;` in C is perfectly safe because there is no bug in that code. The only thing that might be unsafe about that is if you change the code because then you might create a bug. Changing code is always unsafe because you can always create bugs in any language, even Rust.

I don't think "safe" or "unsafe" can be a property of code; it can only be a property of something you do, like changing code. I think that something being "unsafe" means that there is a risk with doing it. Programming is always a risk, even if you write Rust code without using the "unsafe" keyword. You can even have arbitrary code execution bugs in Rust programs without using the "unsafe" keyword; think about bugs like SQL-injections.

All of this doesn't mean than I don't think the checks that the Rust compiler does help. They probably help many people to write less buggy code. I just think it makes no sense to call code "safe" or "unsafe".

Re: Being fair about memory safety and performance

#26
post #20

This article has a core point which is good: “in Rust the default is safe, and you have to opt-in to unsafety, but in C++ the default is unsafe, and you have to opt-in to safety”. I think it’s easy to argue for Rust using this construction, because, well, that’s the entire point why Rust was created. But, it really doesn’t take a very long post to talk about this. The remainder goes off the rails, talking about “C++…

> This article has a core point which is good: “in Rust the default is safe, and you have to opt-in to unsafety, but in C++ the default is unsafe, and you have to opt-in to safety”. On the subject of safe defaults, just to correct that Rust does not in fact have as much default memory safety with regards to buffer bleeds (e.g. variants of OpenSSL's Heartbleed) as it could [1], because it has unchecked arithmetic (int…

I’m generally in the favor of checked arithmetic by default, yes. But I will give Rust credit in that it makes this easy to enable and also provides access to the various other kinds of arithmetic readily.

Re: Being fair about memory safety and performance

#27
I’m my view, Rust is a very uninspired kind of safe language. But a point on which I agree with Rust is that array accesses should be checked by default.

I think this article ignores some arguments for array bounds checks and it ignores the importance of what the default is:

- It doesn’t matter how fast or slow bounds checking is in theory. It only matters how fast it is in practice. In practice, the results are quite surprising. For example, years ago WebKit switched its Vector to checking bounds by default with no perf regression, though this did mean having to opt out a handful of the thousands of Vector instantiations. Maybe this isn’t true for everyone’s code, but the point is, you should try out bounds checking and see if it really costs you anything rather than worrying about hypothetical nanoseconds.

- If you spend X hours optimizing a program, it will on average get Y% faster. If you don’t have bounds checks in your program and your program has any kind of security story, then you will spend Z hours per year fixing security critical OOBs. I believe that if you switch to checking bounds then you will instead get Z hours/year of your life back. If you then spend those hours optimizing, then for most code, it’ll take less then a year to gain back whatever perf you lost to bounds checks by doing other kinds of optimizations. Hence, bounds checking is a kind of meta performance optimization because it lets you shift some resources away from security to optimization. Since the time you gain for optimization is a recurring win and the bounds checks are a one time cost, the bounds checks become perf-profitable over time.

- It really matters what the language does by default. C++ doesn’t check bounds by default. The most fundamental way of indexing arrays in C++ is via pointers and those don’t do any checks today. The most canonical way of accessing arrays in Rust is with a bounds check. So, I think Rust does encourage programmers to use bounds checking in a way that C++ doesn’t, and that was the right choice.

As a C++ apologist my main beef is: if bounds checks are so great then please give them to me in the language that a crapton of code is already written in rather than giving me a goofy new language with a different syntax and other shit I don’t want (like ownership and an anemic concurrency story).

Re: Being fair about memory safety and performance

#28
post #25

I don't know what people mean when they talk about "safe" or "unsafe" code. Doing something like `int a[5]; a[2] = 100;` in C is perfectly safe because there is no bug in that code. The only thing that might be unsafe about that is if you change the code because then you might create a bug. Changing code is always unsafe because you can always create bugs in any language, even Rust. I don't think "safe" or "unsafe" c…

This is only true if you never pass arrays to functions. Once you have a function that takes in an array and does indexing, it is possible to ask if it ever can access memory it wasn't supposed to without changing that function.

Re: Being fair about memory safety and performance

#29
post #12

I'm not quite sure who this article is aimed at, and who those "C++ apologists" are, but as someone who programs in C++ all day, doesn't like it at all, and yet won't advocate to switch to Rust, these kinds of arguments are unconvincing. I'm not advocating to switch to Rust not because I don't think it's better than C++. I am absolutely, 100% convinced that Rust is technically better than C++ in most possible ways —…

Expecting a language be better "enough" is an unrealistic one, you will be waiting forever.

Of course no language will be perfect to a specific domain, there is no objective metric every individual has their own needs and no universal language can cater all them at once, there will be trade offs.

Rust is already better enough( and possibly will take decades before another language "suceeds" it), choose it or be on the perpetual expectation for a "perfect" language

Re: Being fair about memory safety and performance

#30
post #25

I don't know what people mean when they talk about "safe" or "unsafe" code. Doing something like `int a[5]; a[2] = 100;` in C is perfectly safe because there is no bug in that code. The only thing that might be unsafe about that is if you change the code because then you might create a bug. Changing code is always unsafe because you can always create bugs in any language, even Rust. I don't think "safe" or "unsafe" c…

In my opinion it's pretty clear. Rust promises memory safety to me, so all code that is safe IS memory safe. I need to mark a block "unsafe" and have an understanding with the compiler that it can't ensure memory safety here and I am on my own. Makes perfect sense to me :)
Post reply on HN