Live data from Hacker News

Clang Format Tanks Performance

travisdowns.github.io

121–130 of 156 posts

Re: Clang Format Tanks Performance

#121

Earlier quoted context omitted.

Insightful. I will be treading a very similar path soon. So, isn't there a way to emulate FP's `map` mechanics for example, in Rust, without losing performance? EDIT: To reflect your edits, this is why I want to learn Rust. I am as happy as one can be with Elixir due to Erlang's transparent super-robust and predictable parallel performance; this thing simply does not lag! However, I'd like to be prepared and be able…

The major problem with functional programming is that many idioms requires a garbage collector. For example having pure operations on binary trees by just replacing dirty nodes leaving all old references intact wouldn't be possible in rust.

It isn't entirely impossible. Erlang's processes (actors, not actual OS processes; they are like mini-green threads / fibers) very often just throw away all their data after they are done with their work, and that data is often entirely stored entirely in the stack, without any GC needed -- even if the language is GC-ed. Also, all GC is per actor so there's no stop-the-world GC pauses.

But the scenario you outline, yep, it does seem impossible with a borrow checker.

And don't get me wrong. I am gradually learning Rust and I love it. But I can see myself being a little grumpy with the procedural style and often quirky syntax. Oh well, can't have it all, right?

Re: Clang Format Tanks Performance

#123

Earlier quoted context omitted.

Achieving “not far away from C++ levels of performance” with anything but a procedural-style language is very difficult, rare, and usually comes with severe trade-offs, unfortunately. For example: Haskell has been trying to bring the performance of C to a functional language for almost 30 years now. While Haskell is a great language with impressive performance for its category, I don’t think anyone believes it render…

Insightful. I will be treading a very similar path soon. So, isn't there a way to emulate FP's `map` mechanics for example, in Rust, without losing performance? EDIT: To reflect your edits, this is why I want to learn Rust. I am as happy as one can be with Elixir due to Erlang's transparent super-robust and predictable parallel performance; this thing simply does not lag! However, I'd like to be prepared and be able…

Yes, both Rust and Zig are two of the most promising languages in this field IMO. Rust's generics is probably the best example of the 'best of both worlds' (high level abstraction, with predictably high performance), but it's also not without tradeoffs[1].

Rust is more mature, well-known, and akin to C++ in its philosophy (big language with powerful features and abstraction capabilities), while Zig[2] is less well-known but IMO a beautifully designed language akin to C in its emphasis on simplicity, while remaining modern in design (e.g. unlike Google Go, which is very simple but intentionally repeats many of C's mistakes[3]).

[1] Such powerful generics usually come with unavoidable explosions in compile time (and sometimes mental complexity for the coder). This is because while it may look like you're simply calling a library function and passing in a reference to your callback function, what it's really doing most of the time (to achieve good performance) is recompiling the entire library from scratch (or nearly so) with your function inlined. Also, the performance characteristics of any given block of code won’t be as obvious and predictable at-a-glance as it would be in a simpler language.

[2] https://ziglang.org/

[3] https://www.lucidchart.com/techblog/2015/08/31/the-worst-mis...

Re: Clang Format Tanks Performance

#124

Earlier quoted context omitted.

The major problem with functional programming is that many idioms requires a garbage collector. For example having pure operations on binary trees by just replacing dirty nodes leaving all old references intact wouldn't be possible in rust.

It isn't entirely impossible. Erlang's processes (actors, not actual OS processes; they are like mini-green threads / fibers) very often just throw away all their data after they are done with their work, and that data is often entirely stored entirely in the stack, without any GC needed -- even if the language is GC-ed. Also, all GC is per actor so there's no stop-the-world GC pauses. But the scenario you outline, y…

[deleted]

Re: Clang Format Tanks Performance

#125

Earlier quoted context omitted.

Insightful. I will be treading a very similar path soon. So, isn't there a way to emulate FP's `map` mechanics for example, in Rust, without losing performance? EDIT: To reflect your edits, this is why I want to learn Rust. I am as happy as one can be with Elixir due to Erlang's transparent super-robust and predictable parallel performance; this thing simply does not lag! However, I'd like to be prepared and be able…

The major problem with functional programming is that many idioms requires a garbage collector. For example having pure operations on binary trees by just replacing dirty nodes leaving all old references intact wouldn't be possible in rust.

Regarding binary trees: You can always go back to using old-fashioned arrays and indices. A few simple contiguous arrays of nodes (e.g. a key array and value array) is often all you need, where nodes simply refer to each other via int indices into these arrays. You may be surprised that this often yields some of the best-performing data structures, sometimes better than those using raw pointers and non-contiguous heap allocations.

And, this works in Rust just as it does in C. But at this point, you lose out on the benefits of Rust's static type system and borrow-checker:

1. The compiler will no longer be able to correctness-check the validity of these 'int' style references to other memory.

2. If something does go wrong and you read the array with a bad integer index, Rust will just 'panic' and crash the application. Unlike C, there will be no risk of memory errors or related security vulnerabilities. But on the other hand, each read being bounds-checked will make such Rust code slightly slower than is possible with C/C++. (Though I think you can use 'unsafe' blocks if you want to hyper-optimize akin to C.)

But regarding GC langauges, I generally agree; they're almost always more trouble than they're worth in any performance-sensitive context. You often end up using approaches like this to optimize around the GC (e.g. int indexes into pre-allocated arrays) which ultimately means you're coding C-style in a GC language anyway, which defeats the whole point of GC's productivity-enhancing benefit -- at that point, why not just go all the way and use C or Zig or Rust etc.?

Re: Clang Format Tanks Performance

#126

I may eat downvotes but here's an honest opinion nonetheless: this article shows almost exactly why I wouldn't touch C++ with a ten-foot pole still, after running away screaming from it 11-12 years ago. Not saying it's an unique problem with C++'s tooling. I'm just saying that it has been my experience that one is much more likely to stumble upon such horrors while working with C++ as opposed to at least 7 other lang…

> Don't take this as trash-talking, though. I simply want to get things done, not fight my environment.

I think people don't understand just how badly C++ is broken in reality (vs conceptually) until their paycheck is tied to a real, years-old, multi-developer C++ project. It is not trash talking, it is pointing out truths.

It goes well beyond "any long-lived project has its issues." I think you and I (and many others) know that it is much larger than this, it is a fundamental issue with the language, the standards body surrounding it, and the mess of toolings.

This persists today because C++ is often used to bridge a performance gap between scripted languages and C among younger programmers and academics. (Admit it: we all like that sweet sweet dopamine hit when we take our Python to C++ and the syntax is almost the same.) But that slight performance boost and that "hey this looks like Python but it's really C++" feeling are soon demolished by the accretion of unresolved issues which have enumerated ad-nauseum on HN, including this article.

I've been working with C++ since 1993 (I got a big Borland C++ Compiler as an intern plus 12 VHS tapes of Bjarne himself explaining the language)... my experience with C++ continues right up to today as a contractor having to deal with Arm mbedOS (even Keil struggles to manage hypersensitivity, GNU is a trainwreck for embedded C++) and Tensorflow/OpenCV... and C++ has yet to shake off its flaws. In fact, I think it has added to them exponentially.

Re: Clang Format Tanks Performance

#127
post #116
post #86

Earlier quoted context omitted.

Tooling developers don’t get to say “it shouldn’t matter”. It does matter, so the tools should account for this.

clang-format does account for this: if you break your includes into groups with blank lines, clang-format will sort within but not across the groups. That is, clang-format offers a crude but simple API to the programmer to express which headers have order dependency, and which don't. Given that headers can have order dependency, it is sadly part of a C++ programmer's responsibility to know which do , just as it is th…

Ok, that is a fairly unobtrusive way to describe dependencies, fair.

Re: Clang Format Tanks Performance

#128
post #103

Earlier quoted context omitted.

Well given that the order of the headers matter, wouldn't it make sense to have the coding standard specify one true include order ? That's the only way to have a deterministic result.

That ties namespacing to performance, which just sounds horrible to deal with.

Of course, the bug is horrible. But given that those type of bugs exist, having a fixed ordering of include statements seem like the least painful way to go.

Re: Clang Format Tanks Performance

#129
post #112

Earlier quoted context omitted.

That's what I keep hearing but here on HN periodically do pop up some benchmarks that show Rust being stomped. But oh well, most benchmarks aren't pure or non-opinionated so there's that as well. So far I like Rust quite a lot but -- as I said in another sibling comment -- its procedural style and syntax aren't stellar, in my eyes at least.

Well, generally you can, approximately, given C/C++ code, produce Rust code that should give equivalent LLVM bitcode to the one produced by clang on the C/C++ code, so it should not be possible for Rust to routinely lose benchmarks to clang with a significant margin given enough effort in benchmark construction.

Only if you use unsafe Rust, otherwise you'd have to prove that safe Rust semantics are enough to describe the same operations used to squeeze out that performance in C/C++.

Re: Clang Format Tanks Performance

#130
post #112

Earlier quoted context omitted.

Well, generally you can, approximately, given C/C++ code, produce Rust code that should give equivalent LLVM bitcode to the one produced by clang on the C/C++ code, so it should not be possible for Rust to routinely lose benchmarks to clang with a significant margin given enough effort in benchmark construction.

Only if you use unsafe Rust, otherwise you'd have to prove that safe Rust semantics are enough to describe the same operations used to squeeze out that performance in C/C++.

It's more complicated than that. Compilers love restrictions, because that means they can optimize more aggressively. And there are features that Rust doesn't have that C++ does have that can make Rust faster; for example, because Rust doesn't have move constructors, moving is an incredibly cheap operation, whereas it can execute arbitrary code (including throwing an exception!) in C++.

There are also... I don't know how to frame this, social issues? Rust's guarantees often let you do some very aggressive things that you could write in C++, but wouldn't, because it's not maintainable. For example, if you must use reference counting, but don't need threads, Rust has a split between Rc and Arc. You can afford to not use the atomic version in Rust code because if you ever refactor later, you know the compiler will catch this for you, whereas you're just asking for latent, hard to track down bugs if you tried this in C++.

This goes both ways; there is some stuff that C++ is better at than Rust too. It's more complex than "unsafe Rust lets you do anything C++ can do directly and so if it's 100% unsafe in Rust it will be the same speed and if it's safe Rust it will be slower."

Post reply on HN