Hacker News new | ask | show | jobs
by kccqzy 2723 days ago
Using the pimpl pattern doesn't mean an indirect function call. The function to be called is always known. It's just an extra indirection in the data member. It's cheap. Think of it as Java style memory layout: everything that's not primitive stored in an object is a reference and therefore behind one level of indirection. The performance of Java is acceptance in the vast majority of use cases. Using pimpl will be the same.
3 comments

”It's just an extra indirection in the data member. It's cheap”

That extra indirection often means a cache miss. That isn’t cheap. Accessing each item traversed through a pointer can easily halve program speed.

Java tries hard to prevent the indirections (local objects may live in the stack, their memory layout need not follow what the source code say, objects may even only exist in cpu registers)

Hmm... if you were a horrible person you could declare a `char[n]` member instead of a pointer. Then you could placement-new the impl in the constructor, and static-assert that `sizeof(impl)>=n`... No more cache misses :-).

:-(

This doesn't take into account the alignment of the type though (you'd want to use std::aligned_storage<sizeof(T), alignof(T)>), but that requires knowing enough about T to be able to use sizeof() and alignof(), which means no incomplete types, bringing us back to where we started.
When you need this, use aligned storage: https://en.cppreference.com/w/cpp/types/aligned_storage
That’s not that gross. There are types in Abseil that do it.
That's basically how modules would work, at least if you ignore LTCG.
Java JIT-compiler inlines short method calls whenever possible. Though C++ compiler should be able to do the same.
And they do, when given PGO data, or when doing LTO.
Given this is a topic of slow c++ builds, mentioning LTCG should come with the caveat that it will absolutely destroy your compile times.

It's also not infallible and you might find it difficult to track a regression if introduced by someone silently breaking a heurestic in the optimiser.

Sure, I was only mentioning that it is possible.

However with VC++ it doesn't seem to be that bad, when incremental compilation and linking are enabled.

According to MS[0], LTCG doesn't work with /INCREMENTAL (note /LTCG:INCREMENTAL is different). For my use cases, LTCG is unusable for anything other than our overnight builds.

[0] https://docs.microsoft.com/en-us/cpp/build/reference/ltcg-li...

Thanks for the correction.

That's what happens when I spend most the time on JVM/.NET worlds. :)

The only advantage of c++ is max perf. If we could skip a beat we couldn't justify using c++.
It is still wins in "portability + expressiveness + safer than C" areas.

There are still more platforms with a C++ compiler available than Ada, Java or C# ones, let alone Go, D, Rust, Swift.

So if the goal is to make the code available to all platforms, without having to deal with C's lack of safety, then C++ it is.