A twist on PImpl
PImpl is a well known pattern for reducing dependencies in a C++ project. The classic implementation is:
It has two drawbacks:
- inhibits function inlining
- has an extra heap allocation and pointer chase
The extra heap allocation leads to whole new set of drawbacks – creating an instance is more expensive, fragments the heap memory and the address space, has an extra pointer chase and reduces cache-locality.
This allocation can be avoided by a simple trade-off with the PImpl idiom. Why allocating theHTTPServerImpl instance, instead of storing it in the facade object? This is because C++ requires to see the declaration of HTTPServerImpl to allow it to be stored by value. But we can store a C++ object in every memory chunk large enough to hold the its data and respects its alignment requirements. So instead of storing HTTPServerImpl pointer in the facade, we can store a memory chunk that is interpreted as an instance of HTTPServerImpl .This concept can be easily generalized in an reusable template:
And the HTTPServer becomes:
This is definitely not a new technique and it is declared “deplorable” in GotW #28. It has its drawbacks, but I consider some of them acceptable trade-offs. What is more:
- The alignment problems are mitigated by C++11 support for alignment.
- Writing operator= is not harder than writing it in general
- The extra memory consumption is acceptable for small number of instances, given the better cache coherency.
So, does this technique really eliminates the extra pointer chase?
The classical implementation looks like:
And the “twisted” one:
Seems like it does.
Of course, this technique breaks the PImpl idiom and might be considered a hack. Every time the HTTPServerImpl grows beyond the hard-coded size or its alignment requirements change, we have to change the definition of the facade and recompile all the source files depending on the HTTPServer.h, but given the advantages, this is an acceptable trade-off for many situations.
Literature:
- John Lakos; Large-Scale C++ Software Design; Addison-Wesley Longman, 1996
- Herb Sutter; Exceptional C++: 47 Engineering Puzzles, Programming Problems, and Solutions; Addison-Wesley Longman, 2000
Follow Dimitar on Twitter: @DimitarNT