Live data from Hacker News

The case against a C alternative

c3.handmade.network

291–300 of 388 posts

Re: The case against a C alternative

#291
post #237
post #171

Earlier quoted context omitted.

> Modern C++ also discourages raw pointers and so you get references counters all over the place, essentially turning C++ into a garbage collected language. This doesn't match my experience. It's true that modern C++ discourages owning raw pointers, but the solution is usually unique_ptr, not shared_ptr. Truly shared ownership is actually pretty uncommon IME, usually you can have one entity which obviously "owns" the…

This is not my experience. Most developers are just not very good at what they do, and the go-to smart pointers for not-very-good C++ developers is std:shared_ptr .

This has been my experience as well - especially when C++11 came out. I have seen codebases where it has been "use std::shared_ptr for everything, becuase it is safer if/when we use threads". I know that doesn't make sense, but it just was the attitude back then.

Tbh, Back then, I didn't see a problem with it. Once i started chasing down weird bugs where objects aren't freed properly because no one knew which objects own what, I have been very cautious.

Re: The case against a C alternative

#292

Earlier quoted context omitted.

Rust does runtime bounds checks on array access, which the compiler can't elide in non-trivial cases (e.g. binary search), so if you want to write such algorithms as fast as in C, you need to use a lot of unsafe array indexing.

You might be referring to slices. Arrays in rust have to have a known length at compile time.

Rustc may still need to do runtime bounds check if it can’t conclude that a dynamically computed index is in-bounds.

The length is known statically, but whether the index is in-bounds may not be.

The binary search GP talks about is exactly one such case, go on Godbolt, write up a simple binary search (with a static size so you get code), and you’ll see that the compiler checks against the literal array size on every iteration.

Re: The case against a C alternative

#293

Earlier quoted context omitted.

Not to mention that both C++ and Rust can specialise algorithms and containers for specific types, whereas in C most developers resort to void* and function pointers. It's not unusual to see C programs written in a "typical" C style become dramatically faster when rewritten in a more modern language. For example, typical C programs also don't use hashtables even when this makes the most sense, causing weird performan…

> It's not unusual to see C programs written in a "typical" C style become dramatically faster when rewritten in a more modern language. On the other hand, empirically, it is not unusual to see straightforward C programs being dramatically faster than comparable C++ programs written in enterprise style, and to also build much faster. > Last but not least, you would have to be a masochist to write heavily multi-thread…

> On the other hand, empirically, it is not unusual to see straightforward C programs being dramatically faster than comparable C++ programs written in enterprise style, and to also build much faster.

Your only comparison cases are cases where the code in question was re-written in C. This most likely means that everyone already knew it was slow and so the re-write also fixed the fundamental problems. If the code had been rewritten in C++ it would also be faster - and since C++ allows some optimizations C doesn't it would be even faster. (it is known that if you switch from gcc to g++ your code often will run faster if it compiles)

There is a reason for enterprise style C++. Most of the time it is still fast enough, and it is a lot more maintainable.

Re: The case against a C alternative

#294

> First of all, pretty much all languages ever will make vacuous claims of "higher programmer productivity". The problem is that for a business this usually doesn't matter. Why? Because the actual programming is not the main time sink. In a business, what takes time is to actually figure out what the task really is. So something like a 10% or 20% "productivity boost" won't even register. A 100% increase in productivi…

I agree especially with that last point. There is something about programming that is very difficult. It gets _more_ difficult if you write complex things, but that's not the essence of it. I think it has something to do with raw concentration.

We have all of these tools that help us to write code while making few mistakes. From constrained DSLs/configuration languages, schemas, static typing to automated tests etc. But in the end we still have to exert all that energy to sit down, focus and do the coding.

Meetings, design, coordination etc. All of those things are important, and they can be exhausting in their own way. But programming is by far the most challenging, hour per hour (pound for pound). Making all of these micro decisions, think about the impact of your code, the readability, the correctness. It is _at least_ two times harder and more draining than anything else I do, even when I'm in a flow state and the actual work is fun, more fun than all of the other tasks.

And I agree: It is the most important thing. I mean all of the other stuff is basically there to support the core task that solves your problems: producing working software (except if it isn't but then you have political problems). There are seemingly infinite dimensions for improvement as well, tradeoffs such as performance, efficiency, robustness, usability, leverage, creativity...

Re: The case against a C alternative

#295
post #96

Earlier quoted context omitted.

Gonna beat a dead horse here, but >50% of PCs that are surveyed by Steam have 12 threads or more. That’s PCs that have steam installed at all. Intel’s bare minimum current-gen i3 processor has 12 threads. That’s the absolute cheapest desktop-level processor you can get. Your phone probably has 6 cores (though not 12 threads). So yes, if you’re writing code for desktop hardware, it’s safe to assume you have at least 8…

Gaming is very much not representative. There's roughly 120M active steam users, vs. ~1.4 billion windows installs. If I look around me, for instance in my whole family we're two with Steam installed but ever household has a desktop or a laptop (and generally a 7-8 years old cheap entry-level 350€ one, you'd be hard-pressed to find even a quad-core in there)

> and generally a 7-8 years old cheap entry-level 350€ one, you'd be hard-pressed to find even a quad-core in there

My $400 laptop from 2014 has a quad core processor.

Re: The case against a C alternative

#296

Earlier quoted context omitted.

> become dramatically faster when rewritten in a more modern language IME that's mostly a myth though. A C compiler will stamp out a specialized version just as well if it can see all the relevant function bodies (either via inlining or LTO). "Zero cost abstraction" isn't just a C++ thing, it happens mostly in the language agnostic optimizer passes. For instance the reason why std::sort() shows up faster in benchmark…

The only real difference between qsort and std::sort in terms of code generation, is that for std::sort the default assumption is to function clone and for qsort it is to generate the full slow function. Now the compiler will in most cases detect that qsort can be cloned or inlined, but sometimes it might decide not to and the fallback is, in most cases slower then the C++ fallback. PS.: I'm just annoyed that my gene…

You can't just ignore that qsort is implemented in a different library just because it could be implemented inline in the header.

Re: The case against a C alternative

#297

Earlier quoted context omitted.

Precisely. This is perhaps the strangest part of the original post: C++ has the same performance advantages as Rust! It has them not because it's more safe (although it is, in some regards), but because it allows programmers to express behaviors that the compiler can reason about statically.

One cannot imagine C++ failing to emulate Rust's borrow checker by the end of the decade, even if compiler support is required. Has C++ ever failed to snarf a feature?

Many on the C++ committee are interested in the borrow checking, but are not sure how to make it work in C++. The hard part is they cannot break compatibility with code that is legal with previous versions of C++. If there is even one pathological case where the borrow checker will reject code that doesn't have a memory leak then they will not accept it, and require whoever proposes this borrow checker to prove the absence of such a thing. (note if it rejects code that worked until the leaks mean you run out of memory they will accept that). I don't know if such a thing even exists, but if it does I'm confident that in Rust it is new code that you can write differently to avoid the bug, while with C++ that may be a very massive effort to figure out 25 year old code nobody understands anymore before you can rewrite it.

One obvious corner case: It is very common to allocate a buffer at startup and let the system clean it up when the program exits. (often this is embedded cases where the only way for the program to exit is power off). I don't know how you do this in rust (if you can - I'm not a rust expert)

Re: The case against a C alternative

#299
post #237
post #171

Earlier quoted context omitted.

> Modern C++ also discourages raw pointers and so you get references counters all over the place, essentially turning C++ into a garbage collected language. This doesn't match my experience. It's true that modern C++ discourages owning raw pointers, but the solution is usually unique_ptr, not shared_ptr. Truly shared ownership is actually pretty uncommon IME, usually you can have one entity which obviously "owns" the…

This is not my experience. Most developers are just not very good at what they do, and the go-to smart pointers for not-very-good C++ developers is std:shared_ptr .

We had a few developers like that here when C++11 was introduced, but a few people gave them the smack down and now we rarely see shared pointers.

Re: The case against a C alternative

#300

Earlier quoted context omitted.

> I totally agree with you, but are we really expecting "a typical PC" to have 10+ threads? I think you are mixing hyperthreading, or SMT with regular "software" threading

They're mixing parallelism and concurrency. (nb: I might be abusing these terms too) Parallelism aka CPU-bound tasks are limited by the number of cores you have. Concurrency aka IO-bound tasks are not, because they're usually not all runnable at once. It can be faster to go concurrent even on a single core because you can overlap IOs, but it'll use more memory and other resources. Also, "going faster" isn't always a…

A succinct way to distinguish both is to focus on what problem they solve:

> Concurrency is concerned about correctness, parallelism concerned about performance.

Concurrency is concerned about keeping things correct[1] when multiple things are happening at once and sharing resources. The reason why those problems arise might be for performance reasons, e.g. multiplexing IO over different threads. As such, performance is still a concern. But, your solution space still involves the thread and IO resources, and how they interleave.

Parallelism is in a different solution space: you are looking at the work space (e.g. iteration space) of the problem domain and designing your algorithm to be logically sub-dividable to get the maximum parallel speedup (T_1 / T_inf). Now, a runtime or scheduler will have to do the dirty work of mapping the logical subdivisions to hardware execution units, and that scheduler program is of course full of concurrency concerns.

[1] For the sake of pedantry: yes, parallelism is sometimes also used to deal with correctness concerns: e.g. do the calculation on three systems and see if the results agree.

Post reply on HN