7 ms·
and even std::map, std::unordered_map, even std::vector (!) suck It's really hard to take your comment serious because of generalization like this. Maybe they'
by stinos 3mo ago
and even std::map, std::unordered_map, even std::vector (!) suck
It's really hard to take your comment serious because of generalization like this. Maybe they're not usable for your particular usecase but that doesn't mean they suck. Just like there's a 'million' ways that C++ sucks in your book, there's a reason there's millions of lines of code out there where these containers are valid usecases and hence work without issues whatsoever nor a need to replace them with something else.
- jstimpfle 3mo agoThey're not useable for anything serious, i.e. high throughput, low frequency, massively concurrent work. In other words, most of the things for which you shouldn't better have chosen a different language in the first place. They're also unusable by the way because of ergonomic and software architecture factors, such as bad modularity, terrible compile times, unreadable error messages, unreadable symbol names... Yes that is overgeneralizing a little bit but it's largely true. The problem is typically not the containers themselves but all the other bad decisions that they push you to make in order to work around their "small issues". The huge problem is that these containers can get you started quickly, i.e. leetcode type stuff and single threaded stuff, but at some point you'll realize your architecture ended up completely in the wrong place because of that. If you haven't been thinking deeply about memory management and concurrency, you won't be able to understand, no offense meant. I've just fixed another subsystem that was completely overwhelmed, seeing 8x bandwidth gains already on a small testsystem, but the factor is basically unbounded when moving to bigger systems, when it's about contended vs uncontended.
- delta_p_delta_x 3mo ago> anything serious, i.e. high throughput, low frequency, massively concurrent work Why is only 'high throughput, low frequency, massively concurrent work' considered 'serious'?
- jstimpfle 3mo agoYou are free to make your own definition, what are your suggestions? (Obviously I meant to say low latency, not low frequency)
- delta_p_delta_x 3mo agoThat is a cop-out. You made the assertion, you define it. What about these particular workloads (and the environments they're used in) make them 'serious' and why are other workloads 'lesser' and therefore the standard library 'suffices'? Why not use better containers for everything? Google, for instance, universally recommends Abseil.
- jstimpfle 3mo agoI stand by my statement. You are welcome to contend it, but then please actually suggest alternative workloads that could qualify as serious? Google also recommends using Golang in many cases, which was explicitly designed for not-so-experienced people. It is more geared towards creating services quickly and robustly, not towards squeezing out the last 10x of performance. I can't say anything about abseil, having never used it. "By Google" is not an immediate seal of quality, and it doesn't mean that one size fits all. I've recently seen a list of .so objects required in order link grpc (also by Google), there were like dozens of abseil .so's in the list IIRC. I don't like it! In my experience, validated countless times in my own practice, complexity => slow and hard to maintain and simplicity => fast and easy to change. Templatized C++ containers are generic recipes, they can't make use of local context and hence don't lead to the simplest solutions. They produce tons of boilerplate. They give you a decent single-threaded baseline performance in many cases, sure, but now start hammering these data structures using 16 CPUs in parallel... you might find that you should have designed your application completely differently. Like WalterBright says, I too use very simple data structures almost exclusively (arrays, linked lists, linear allocation). Most of these coded ad-hoc everywhere, very straightforward, very adaptable. Even hash maps I only use infrequently -- if I can, I just make keys such that I can index directly. I get performance from knowing exactly what happens, and minimize the work that needs to happen. I create immutable data objects (write-once) where possible. I've created my own pooled block-allocator for power of 2 sized allocations with book-keeping in shadow-memory (preventing fragmentation), massively reducing syscalls that modify virtual memory mappings and closely controlling memory used by various subsystems. I don't expect a library like abseil to solve many of my problems, it probably makes some things "easy" by taking away the very control from me that I need to solve the problem I have, resulting in unsolved problems and complexity.
- stinos 3mo agoIf you haven't been thinking deeply about memory management and concurrency, you won't be able to understand, no offense meant I do think about that, when needed. My point is that these containers can be 'good enough' in places where it doesn't really matter, not that they're always the go-to thing. E.g. I really don't see any issue using a map as part of a configuration type of object which gets read from args or json and which only gets used once at application start.
- jstimpfle 3mo agoYes. When you don't have any specific requirements, any mediocre data structure will do.
- jcranmer 3mo agostd::map and std::unordered_map are just unbelievably shitty implementations. The former is a red-black tree, which in my entire programming career I have needed to reach for like... twice? It's just not the right container for almost any problem you have, yet it's the one that gets the short, sweet name. The latter is a bucket-based hashmap, which is about the worst kind of hashmap that can be built. On top of that, their APIs are also really annoying to use compared to, say, Python or Rust's implementation. At least C++20 finally added a simple contains method, but something like setdefault is just a chore to get implemented.
- tptacek 3mo agoNot really apropos any of this but a vivid career memory for me is leaving a startup that was all in C++ and going to Arbor Networks, which was all C, and porting the STLport map to rbtree.c and making it our default container. No, I have no idea why I did that. Different times!
- WalterBright 3mo agoPretty much the only collections I use are: 1. arrays 2. linked lists 3. hash tables 4. simple binary trees