HN Theater @HNTheaterMonth

The best talks and videos of Hacker News.

Hacker News Comments on
CppCon 2016: Chandler Carruth “High Performance Code 201: Hybrid Data Structures"

CppCon · Youtube · 3 HN comments
HN Theater has aggregated all Hacker News stories and comments that mention CppCon's video "CppCon 2016: Chandler Carruth “High Performance Code 201: Hybrid Data Structures"".
Youtube Summary
http://CppCon.org

Presentation Slides, PDFs, Source Code and other presenter materials are available at: https://github.com/cppcon/cppcon2016

Modern programs’ performance characteristics are often dictated by their data. Whether the cache locality of data access, the size of working set, or avoiding costly memory allocation overhead. Unfortunately, the standard C++ library data structures range from adequate to terrible at controlling these aspects, and they don’t provide any of the core mechanisms needed for extremely efficient data structure design.

This talk will present the core concepts of designing high performance data structures in C++. It is based on years of experience in the LLVM compiler as well as several other large code bases. From these principles, the talk will propose a suite of data structures that provide performance without loss of generality or functionality. As much as this talk will present specific data structure designs, its primary intent will be to give an understanding of what makes these structures have greater performance than more naive approaches.

Chandler Carruth
Google
C++ Lead
San Francisco Bay Area
Chandler Carruth leads the Clang team at Google, building better diagnostics, tools, and more. Previously, he worked on several pieces of Google’s distributed build system. He makes guest appearances helping to maintain a few core C++ libraries across Google’s codebase, and is active in the LLVM and Clang open source communities. He received his M.S. and B.S. in Computer Science from Wake Forest University, but disavows all knowledge of the contents of his Master’s thesis. He is regularly found drinking Cherry Coke Zero in the daytime and pontificating over a single malt scotch in the evening.

Videos Filmed & Edited by Bash Films: http://www.BashFilms.com
HN Theater Rankings

Hacker News Stories and Comments

All the comments and stories posted to Hacker News that reference this video.
I suggest watching this talk:

https://www.youtube.com/watch?v=vElZc6zSIXM

Or pretty much any other by Chandler to understand why the STL sucks and why you should write better datastructures for your own use cases.

pjmlp
All nice and good if one is a compiler expert, except most people end up writing datastructures that perform worse than STL.
in CppCon 2016: Chandler Carruth “High Performance Code 201: Hybrid Data Structures"[1] he says:

"but the standard deque data type is really quite bad. I wouldn't recommend anyone use it for anything. if you look at the implementation constraints, the constraints placed upon its iterators, and its invalidation constraints, it's painted into a very unpleasant corner and it has very few opportunities to be an efficient data structure."

[1] https://www.youtube.com/watch?v=vElZc6zSIXM

tom_mellior
Thanks for the reference. But this is still specific to access patterns: You can use a deque as a queue without iterating, so iterators and their invalidation constraints should not matter.
pansa2
For a language whose purpose is high-performance, the std:: containers are an embarrassment. `deque` is slow, `map` is slow - so the language added `unordered_map` which is also slow...

Are any of the containers (other than `vector`) worth using in high-performance code?

I’m sympathetic to the game developers who I’ve heard say “we use C++, but nothing from std::”.

Leherenn
Array is great as far as I know.
kllrnohj
std::array is great except it's annoying to statically initialize. Really wish make_array or to_array were non-experimental a lot sooner (to_array finally did land in C++20 at least).

But yeah it does mean you can finally stop doing that silly `sizeof(a)/sizeof(a[0]);` trick.

59nadir
STL is mostly garbage, which is a big reason it's not used in places that actually need performance, both for build times and runtime.

Yes, it's embarrassing. I think it should be noted that the performance mantra is mostly for show with C++, though. The same people who spout it will also blatantly use pessimizing language features just because, when normal, procedural code would've done the job faster and ultimately simpler.

I think the performance overhead of a few things in C++ make sense, but in general you get performance in C++ by turning things off and abstaining from most of the features. Exceptions complicate mostly everything, so the best thing to do is to turn them off and not rely on anything that uses them, for example.

Modern C++ isn't fast and most of C++ wasn't even before the modern variant was invented. The C "subset" is.

dataangel
> Exceptions complicate mostly everything, so the best thing to do is to turn them off and not rely on anything that uses them, for example.

Look forward to all your users ignoring your return codes and never calling valid() on your objects that can only signal construction failed that way.

Also the impact of exceptions on performance is overblown, even in high perf situations:

https://news.ycombinator.com/item?id=20342183

Throwing is slow, but throwing is supposed to be rare. Don't use it as flow control.

pjmlp
About 1% of developers actually need to deliver µs fast code.

The remaining 99% are happy to be able to deliver fast enough portable code without having to reinvent data structures all the time.

adev_
> STL is mostly garbage, which is a big reason it's not used in places that actually need performance, both for build times and runtime.

It is NOT garbage. It is more than sufficient for the 99% of devs that need key in hand data structure and good enough performance (Meaning faster than 99% of over programming languages already).

If what you need is sub micro-second perf, then yes, redefined your data-structure.

BTW, you will very likely have to do that in any language anyway. Because it is impossible to design fast forever-living data structure. They (almost) all become obsolete when architectures evolve. Red-Black Trees where state of art DS, teached-at-school 10 years ago, they are useless garbage nowadays if you seek for performance.

kouteiheika
> It is more than sufficient for the 99% of devs that need key in hand data structure and good enough performance (Meaning faster than 99% of over programming languages already).

I really don't get this argument. If you don't need pedal-to-the-metal performance then why are you using C++ in the first place? (Unless, of course, your answer is "legacy code".)

C++ is being touted as being high performance, but basically every standard data structure besides `std::vector` is garbage for high performance, pedal-to-the-metal code. And not only data structures - `std::regex`'s performance is bad, `std::unique_ptr` doesn't optimize as well as a plain pointers, no vendor has a best-in-class `std::hash` implementation (they're neither DoS-safe nor the fastest), etc.

> BTW, you will very likely have to do that in any language anyway. Because it is impossible to design fast forever-living data structure. They (almost) all become obsolete when architectures evolve.

Do you, though? Rust already replaced their standard hash map implementation with a completely different one which was faster, so it shows that it can be done.

adev_
> I really don't get this argument. If you don't need pedal-to-the-metal performance then why are you using C++ in the first place? (Unless, of course, your answer is "legacy code".)

There is many other things that pure compute-bound CPU performance that can drive you to a GC-less language like C++. Fine grain memory usage is one of them, latency control is an other.

> `std::regex`'s performance is bad. , `std::unique_ptr` doesn't optimize as well as a plain pointers

std::regex is not defendable, specially when there is much better implementation already available (https://github.com/hanickadot/compile-time-regular-expressio...)

However, do you have any bench / source for std::unique_ptr ? You are the first one I hear giving critics on it.

> Do you, though? Rust already replaced their standard hash map implementation with a completely different one which was faster, so it shows that it can be done.

Rust does not have 25 years of code base behind him. We can talk to that again when he gets 10 years more.

C++ can not afford to randomly break API on one of its core STL component just to hypothetically gain few bit of performance.

It can be done, but it should be done with a depreciation process and an alternative implementation, like it has been done for auto_ptr -> unique_ptr.

aw1621107
> However, do you have any bench / source for std::unique_ptr ? You are the first one I hear giving critics on it.

Chandler Carruth talks about this at CppCon 2019 [0]. From a quick review he says part of the reason std::unique_ptr isn't zero-cost right now is:

- Objects passed by value (like std::unique_ptr) are passed on the stack instead of in registers, and changing that will be an ABI break

- No destructive move means extra temporaries will be created/retained

[0]: https://youtu.be/rHIkrotSwcc?t=1046

steveklabnik
Rust didn't break the API of HashMap. The trick is that the STL decided that certain algorithmic requirements were a part of the interface. For std::map, the case here is that it must be sorted. Its API also means you can't be polymorphic over a hashing strategy. This constrains possible valid algorithms. Rust made the opposite choices.

And so they did exactly what you say, for that reason. std::unordered_map is a better comparison.

The parent was asking the goldilocks question -- was there ever a point where C++ was not too complex like modern C++, e.g. this {} issue, but had enough features (contrast with C, which doesn't have enough features for many applications). I don't think there was such a moment.

Apparently move constructors were a de-optimization in the case of std::vector. As far as I remember, it's related to iterator invalidation and move semantics making small-size optimization impossible (e.g. inlining small vectors into the object itself rather than having another pointer and heap allocation). I'm pretty sure it's in this video:

https://www.youtube.com/watch?v=vElZc6zSIXM

Although it's debatable how big a deal this is, it's a good example of the point. People like "C with classes" because they can read the source and kind of figure out what code is generated. They can reason about locality.

Although I don't consider myself an expert C++ programmer, if I can't reason about the consequences of move constructors on std::vector, which is a fundamental and relatively simple data structure, then the language is already getting into "surprising" territory. I would have never figured out that de-optimization unless I heard it in a video.

On a related note, I wish that return value optimization had better syntax -- that would make move semantics unnecessary in a lot of cases.

On the other hand, reasoning about the generated code is already a lost cause because assembly code is so complicated now. We now have to live in a world where we can never fully understand our tools.

ant6n
On top of assembler being complicated, the CPUs contain another sort of compiler and optimizations, so it gets even harder to know what exactly happens.

I thought that moving is optional in a sense, and the compiler could decide to copy instead of move (?)

placidbox
At what point is it mentioned in the video? AFAIK small optimization on std::vector was already invalid since .swap() needed to keep existing references/iterators valid, couldn't throw or call copy constructors/assignment.

RVO being transparent would be nice, though. There's a proposal somewhere to make it guaranteed in some circumstances, but it's still fairly opaque when reading code

chubot
Sorry I don't recall offhand. It was definitely Chandler Carruth who mentioned this, and he has a handful of videos on YouTube from CppCon. They are all worth watching if you care about such things :)

I don't know the details but I'm fairly sure that the issue is that move constructors in C++11 made small size optimization impossible in some cases. I think he works on the LLVM optimizer so that would be a primary source and not hearsay.

HN Theater is an independent project and is not operated by Y Combinator or any of the video hosting platforms linked to on this site.
~ yaj@
;laksdfhjdhksalkfj more things
yahnd.com ~ Privacy Policy ~
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.