10 ms·
Trip C++Now 2024 – think-cell
- gpderetta 2y ago> Google does not use std::ranges for many reasons, including performance, the ability to create dangling references, and a cubic stack blowup when deeply nesting some range adapters like std::views::filter I remember discussing this exact problem for boost range in the boost mailing list almost 20 years ago. My proposal was to make ranges be their own thing and generate the iterators on the fly when begin/end was requested, instead of always storing them internally. But I think it was not considered a big issue in practice. Today we have sentinel end-iterators that can be stateless, so it should be possible to avoid blowout without fundamentally rethinking ranges.
- menaerus 2y agoMy, admittedly, not so big experience with std::ranges is that they generate an abnormal binary bloat in comparison to the traditional code, so, I also tried to argue against their usage in one my ex-teams who, paradoxically, wanted to achieve tight execution on platforms with tight resources. Another paradox was that the exceptions were disabled because of reasons while at the same time std::ranges (range-v3) implementation did not support this. I wonder how Google solved this problem since AFAIK they also disallow exceptions.
- tialaramex 2y ago> cubic stack blowup when deeply nesting some range adapters like std::views::filter I have no doubt this observation is true, but I haven't been able to picture it, can somebody explain? I don't think ELI5 (let alone an explanation suitable for a Golden Retriever) will work here, but in terms that say a C programmer would grasp. What exactly gets shoved onto the stack when we're using a std::views::filter ?
- menaerus 2y agohttps://schedule.cppnow.org/wp-content/uploads/2024/02/Rappel.pdf https://schedule.cppnow.org/wp-content/uploads/2024/02/Rappe... Slide nr. 21 (nr. 26 in PDF).
- tialaramex 2y agoThanks but I saw the numbers, however to me the numbers just say "It's terrible" and leave me with the same question I had before, what's actually on the stack ? It's not going to just be empty space left there as a joke, are there... cached values? Pointers to something (what?). I suspect it's supposed to be obvious but I don't get it.
- menaerus 2y agoAccording to https://en.cppreference.com/w/cpp/ranges/filter_view https://en.cppreference.com/w/cpp/ranges/filter_view return value of views::filter is either a new ranges::view or some sort of range adaptor that seems to be equivalent to a ranges::filter_view. I can only guess that it is those return values that are temporarily put on stack so that the consequent | operations could be chained. My hypothesis, without knowing much about this stuff, is that since the compiler cannot elide them (according to the godbolt link from the presentation), stack usage, as found by Google, has cubic growth. I don't quite understand why since I guess it's expected to grow linearly, e.g. 48 bytes at a time.
- quuxplusone 2y agoMy "Eric's Famous Pythagorean Triples" blog post is 5+ years old and possibly not addressing exactly the same issue as think-cell/Google cares about, but, you might still be interested to read it: https://quuxplusone.github.io/blog/2019/03/06/pythagorean-triples/ https://quuxplusone.github.io/blog/2019/03/06/pythagorean-tr... In my case, the blowup happens mainly because the Ranges style tends to turn easily fungible code like `if x < y` into relatively non-fungible data like the capture-list of `[y]() { return x < y; }`. The former is easily subjected to optimizations like the hoisting of loop invariants; the latter is not. Another way to put this is: The compiler is happy to mess with the layout of the function stack frame up until the very last minute; and to mess with the coroutine frame almost as long; but the layout of a lambda (or std::bind) capture frame is set-in-stone very early, by the front-end. And Ranges loves lambdas.
- foonathan 2y agoHere's an explanation: https://www.reddit.com/r/cpp/comments/1coi2kq/comment/l3fblum/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button https://www.reddit.com/r/cpp/comments/1coi2kq/comment/l3fblu...
- panstromek 2y agoSince C++ ranges kinda look like Rust iterators, but I believe Rust doesn't have this problem, can somebody explain why? What's the difference? Or maybe it also has that problem?
- tialaramex 2y agoI expect (but I'm not sure) it's because Rust iterators are a deliberately thinner, less powerful idea. Suppose I give you a Rust iterator A and a C++ range B. You can ask A for the next() item and get back an Option<Item>, this literally iterates as an inherent part of getting your answer, there's no current() or previous() and there's no separate finished() if you ran out of items you got None instead of Some(item). A can be asked for a hint about how much is left, but it's allowed to say it has no useful idea: between zero and more than you can count, inclusive. B is expected to provide a richer, albeit unsafe, API. I believe somehow this means it's only reasonable for B to cache answers, as it can be asked to give the same answer again and it'd be inefficient to re-calculate it, whereas there is no way to ask A to repeat an answer so it makes no sense for it to cache (obviously there are special purpose Rust iterators which can have any feature, but the Iterator trait itself doesn't need to cache).
- panstromek 2y agohm, so I tried this on the playground and it seems like Rust iterators also scale super-linearly in debug mode (which is expected, because every adaptor creates a new local that contains the previous one plus something extra), but this seems to go away in release mode (as everything is inlined). Is the problem in C++ something different?
- jcelerier 2y agoit's exactly the same behaviour in C++. but people are used to this behaviour in Rust while in C++ they're used to writing traditional for-loops which do not have such an overhead at -O0 over -O3
- pornel 2y agoRust's iterators are single-use streams of items, and nothing more. A Rust iterator can be fully implemented by a closure that either returns the next element or signals it's done. This minimalist interface composes well, especially that it always uses single ownership, so there's always only one copy of the state accessed only from one place. They can't describe collections. They don't remember their beginning. They don't need to know their end until they reach it. They can't be sorted. They don't need to support splitting or iterating in reverse.
- thom 2y agoRappel sounds very similar to Clojure’s transducers in spirit and implementation.
- ho_schi 2y agoRegarding the addition to libxx: I’m not fond of adding an increasing number of specific compiler options which need to be turned on for memory-safety. It should be default whenever possible. What do you think? I love -faddress=sanitizer or -fsanitize. The historically growing number of warnings which should be turned on are an issue. For example the options -Wconversion, -Wsign-conversion and -Warith-conversion shall be default with C++XX. And if your code doesn’t compile, fix it, use and older revision or turn it deliberately off (saying: I’m aware, read the handbook, I take the risk). Doing such changes with language revisions allows people to take notice about it without surprise. I want some ideas of CPP2/cppfront[1] in C++XX. Finally using #unsafe when needed, like Rust. C++ does evolve over decades, more like other languages. [1] https://github.com/hsutter/cppfront https://github.com/hsutter/cppfront BTW. Use the AddressSanitizer. Please! The toolchain improved the usage and safety of the language so much. It wasn’t available twenty years ago but it is now.
- repelsteeltje 2y agoI think what you're looking for are profiles. - https://github.com/BjarneStroustrup/profiles https://github.com/BjarneStroustrup/profiles Ie. rather than a bunch of tools helping you find undefined behaviour (or left-and-right improvements of what the behaviour should be) you'd like to be able to make high level claims about your code and have the compiler validate those guarantees. C++ having a huge C++ legacy, things of course are never easy. So for the time being this is just work-in-progress.
- pjmlp 2y agoFirst of all they have to be designed and voted in. If WG21 is actually open to having them, ISO C++29 is probably when they might land, then given the compiler velocity with previous standards, expect at least 5 years to mature, on the top three, let alone everyone else. If I am not dead by then, I will certainly be retired. How long will the industry be willing to wait for profiles?
- tialaramex 2y agoI think the compilers would be allowed to just make your default warning changes as non-fatal diagnostics aren't a conformance matter. So you probably need to lobby GCC, Clang and MSVC. Herb's discussion of "unsafe" for Cpp2 is... misleading. Rust's unsafe does not turn off checking. If you take some safe Rust which compiles (even if it panics) and you just wrap that in a block with the unsafe keyword, all you get for your trouble is a new diagnostic (by default a warning) saying not to do that because it's futile to use an unsafe block here. No checks are switched off, no "performance" shortcuts are added, if it would panic before it still does now - it's just the same code with a frivolous "unsafe" sign on it.
- jokoon 2y agoThink cell is the company the creator of lexy works at
- quuxplusone 2y agoIf you mean https://github.com/foonathan/lexy https://github.com/foonathan/lexy , then yes, foonathan (Jonathan Müller) is literally the "I" in the first sentence of TFA.
- jokoon 2y agooh indeed, I had not scrolled enough!
- foonathan 2y agoYes, but sadly I have to use Boost.Spirit at work :(
- AnonSixOneTh 2y agoI'll say this because it needs to be said. Recently it seems like every developer on LinkedIn who has "C++" in their profile, and their cat, is spammed every couple of weeks by some recruiter with a "great opportunity, 130,000 euros FULLY REMOTE", turning out eventually to be recruiting for think-cell. I got it, my friends got it, my work mates got it, everyone gets spammed periodically, it has become the laughingstock of job ads. Why? Read the Glassdoor reviews. The CTO is a terrorist obsessed with complexity, they overengineered themselves into a corner by using every freaking C++ feature that ever existed, making sure that there's only 3 or 4 people in this world who can understand their code. Of course the usual pattern goes: guy learns #feature on-the-fly appearing both incredibly smart and embelishing his resume, until of course reality hits and the complexity of the crap he wrote outclasses his "genius" intellectual capacity so then he leaves, leaving the mess for future hires to deal with. Consequently there's maybe 3 people left in this world capable to understand the atrocity that's running there, not saying fix it. So good luck finding them. These people, if they exist, already work for more that $130k. Also, why do they need the absolute raging brinking edge of C++ features? What does this company do? Trillion dollar ultra low latency / high throughput high frequency trading? AAA+ games running on 4 x 4k monitors at 200+ fps? No. They do some farty charts. Again. Good luck with the recruitment! :)
- lbhdc 2y agoThat kind of sounds like a lot of code bases I have worked in. Once you get some many people on a project things can get messy. Perhaps its a sign they have some DX and tech debt they should address. As for why the latest version of c++? Personally I have found the dx improvements of some of them to be worth the upgrade. I really like constexpr and the build time errors it gives (opposed to runtime). The newer standards let you use constexpr in more places with more stl types.
- CoastalCoder 2y agoIt does make "C with classes" sound pretty appealing. Well, maybe also with some very limited template facilities. Shoot... Did I just describe Ada95 somewhat?
- pixelpoet 2y ago
- htoweasdf 2y agoI created a similar sum type during high school detention but type order didn't seem possible at the time. I'm glad someone else has eyes on it. I unfortunately don't write C++ anymore because the TC is too low. It's sad that Python and JS pay more.
- lionkor 2y agoDid their 4-9 hour(!) mandatory take home coding test. Never done such a terrible test in my life; in every way they made a test akin to basically locking a c++ dev in a room for anywhere between 4-9 hours and afterwards rolling a die. Its underspecified, but then has automated tests, that, after failing twice, automatically reject you as a candidate. Of course it doesnt give examples or example test cases or real test cases, so you're shit outta luck trying to solve it. The challenge itself would be fun and solvable in 4 hours, but around the 2 hour mark you start having questions and from there its just bad. You can google this coding test ("think-cell interval_map") and youll get a lot more info. I complained to them just in case they cared, and they did seem to care, but failing to specify an automatically tested coding challenge is the kind of psycho shit you do if you think youre the smartest guy in the room (but arent). ETA: To be clear, I stopped the second I realized it was an underspecified test. I'm not that mad, just mad I fell for spending a whole saturday morning doing it, without ever talking to anyone there in a call or anything. That and the fact that theyre just building a powerpoint plugin and seem to overcomplicate it to such a massive degree: Yeah no thanks.