5 ms·
This talk is just clickbaity, the complains are valid, but to then go and use it to claim that you can never have zero cost abstractions is just .... For exam
by AshamedCaptain 3y ago
This talk is just clickbaity, the complains are valid, but to then go and use it to claim that you can never have zero cost abstractions is just ....
For example, the ABI used by Linux already passes many structs in registers. Fixing it to also include unique_ptr will indeed "break every aspect of the C++ ABI", but that is not really an unsurmountable problem: Windows breaks C++ ABI on almost every other release (and so does almost any language other than C), Linux user-space has done so in the past, and Linux the kernel just doesn't care.
There is no overhead with exceptions when there are no exceptions (e.g., in the kernel). Also think about what it means for the compiler to need to generate exception code: if you were not using unique_ptr, wouldn't you have to make a conditional and free the pointer by hand in such scenario? If the answer is 'yes', then it is not really 'overhead'.
> It's only really zero overhead when you can't transfer ownership (`unique_ptr<T> const &`)
I think you have this backwards. Pass-by-value can be zero overhead (as in, you can probably think of an ABI which makes it zero overhead and is compliant). It is precisely pass-by-const-reference that cannot be zero overhead, because according to the language rules you are passing a reference to a unique_ptr (i.e. a pointer to a pointer). I'd hardly call that a hidden landmine, as that's what the & means, and I think the average C++ developer is familiar with the concept.
Then again, why would you try to pass a unique_ptr by reference is over me. There is really no ownership transfer whatsoever, you are just contaminating your API with unique_ptr unnecessarily.
In fact, most of the overheads mentioned just go away if you don't use unique_ptr in function signatures, which is hardly unmanageable mental complexity. In fact, in the proposal here by the Linux kernel, you also cannot pass unique_ptrs through functions; they are type erased.
- menaerus 3y ago> For example, the ABI used by Linux already passes structs in registers It's a bit more nuanced I think - what I understood from that talk is that the "overhead" of a unique_ptr is attached to the inability for a compiler to pass the unique_ptr as a value through a register but will instead have to use the stack (memory). That said, this nuance of using stack instead of registers doesn't apply in the general case but _only_ for the unique_ptrs holding an object with non-trivial copy-constructors or non-trivial destructors - so, non-PODs. If we accept this nuance as a measurable cost in actual workloads where it really matters, this is again only the artifact of Itanium ABI and something C++ can only adhere to but cannot change. Any language that speaks to the system (OS) must do the same. That said, among many other and much more complex code transformations that we do I can hardly see using push/pop instructions as a bottleneck - our CPUs indeed implement push/pop (micro)instructions through a dedicated HW circuitry meaning that they're always on the fastpath and we don't pay the price for them as we do for "regular" instructions. This is why I call this talk a BS and I see it only as a way how Google wanted to prove that "break the world" is worthy under the disguise of zero-cost abstractions that are only "sometimes" zero because of "C++/ABI".
- AshamedCaptain 3y ago> It's a bit more nuanced I think Yes, I have edited it a bit; I did not want to claim that unique_ptr is universally passed through the stack, just that it is not an insurmontable problem to do so. > this is again only the artifact of Itanium ABI and something C++ can only adhere to but cannot change. Any language that speaks to the system (OS) must do the same. This is not true, though. 1) you can change and evolve this ABI (it has happened in the past), 2) you can also have an ABI for the system libraries and an ABI for the rest (see Windows, or see how any language other than C works), and 3) since the problem would only be about non-PODs, which are pretty much C++ specific, the system ABI would not be affected at all.
- menaerus 3y agoI see, thanks for clarifying, especially on number (2) which I wasn't aware of. I always had an impression that the compiler ABI is somewhat tightly coupled with the system ABI and which is why I used them almost interchangeably. So, Google premise is that they can provide alternative unique_ptr implementation in a way so that it breaks the C++ ABI without touching the Itanium ABI but with the benefit of unique_ptr fitting into the registers always rather than almost always? If so, I am not aware that they have shown any such implementation and its impact to their codebase?
- AshamedCaptain 3y agoYou won't be compatible with the SysV/Itanium ABI (it does include C++ bits), but you can definitely do it. It just happens that you will probably not have any problem to call a C library from such a new ABI (incl. libc and the kernel) since you only changed non-POD behavior, and those C libraries won't use anything but PODs. The fact that you can have some structs with non-trivial methods that are still classified as PODs means the ABI is already solving the hard problem (i.e. these methods won't really have a 'this' pointer), so the limitation for types like unique_ptr sounds like easy to remove in an experiment.
- menaerus 3y ago