[forward_declare] Interest Inquiry toward Faster Compile Times

I have been increasingly frustrated with how long it takes to compile c++ code. After spending some time in Java and C# I can feel the pain of compile times much sharper than I use to. After seeing that Java and C# were able to achieve some level of generics without requiring 'everything in the header' and knowing that C compiles an order of magnitude faster than c++ I set about to find a way to increase my compile times. One of the common recommendations is to 'forward declare' everything and to use the PIMPL (private implementation pattern). Unfortunately, PIMPL usually implies heap allocation and if you ever want to return-by-value you are stuck including the entire header for the types you use in your header. I started inspecting some of my code and running it through the pre-processor and noticed that almost every source file was in the 50K+ lines of code post-preprocessor and that some files were north of 250K lines of code. This was ridiculously inefficient, especially because I was already using PIMPL everywhere I could and most of these lines were stl + boost. After a little bit of work I was able to abstract vector, boost::exception, iostream, string, threading, and many of the other types that I had been including that resulted in 'code-bloat'. The resultant library was able to reduce my post-preprocessor output to just one or two thousand lines of code (assuming the .cpp itself was 500+ lines). My compile times dropped to sub-second per object file from 10+ seconds (some up to 40 seconds). There are some side effects from doing this, performance in some cases was slightly slower due to one level of indirection, but with with link-time optimization this performance loss was minimized. And any loss of performance was clearly acceptable trade for the gain in development efficiency. In situations were performance really is critical I can choose to include the raw header in individual cpp files, but in most cases that level of 'optimization' is overkill. One of the things I realized doing this work was that often the only reason you need to include a header is because the compiler needs to know the SIZE of the type that you wish to forward declare and nothing else. So our development is slowed entirely due to the lack of a SINGLE NUMBER. So I created a utility that allowed me to 'forward declare' the size of the variable. This allowed me to use return by value and member variables via forward declaration WITHOUT having to resort to heap allocation. It occurred to me that a library that allowed developers to choose a little drop in runtime performance for a dramatic improvement in compile times would be generally useful to the C++ community. I have included an example of the 'technique' and general purpose utility that would allow others to quickly and easily integrate forward declaration of 'value types'. A full up boost submission would probably include pre-wrapped versions of most of the STL and Boost types.

Hi, Agreed on the general idea, quite interesting indeed, thanks for sharing. Isn't there a space cost as well ? First the way you did you require one more byte for each object (why by the way?) which means that each "fwd" in a sequence will have something like 7 bytes of padding after it when compiling for 64 bit systems. Hopefully there aren't any alignment problems when using "fwd" but I am not expert enough to be sure, have you considered it ? Regards, Julien

Julien, An extra 'byte' was just left over from me testing. It works with 8 bytes (2 ints) and it asserts on 7 bytes. I was trying to find a way to 'warn' if you reserved too much. It looks like BOOST_STATIC_WARN() has been removed. I thought about alignment issues (I am no expert here), but my understanding is that structs/classes are always 'aligned' in the same manner regardless of what is stored. Therefore, if my fwd<> class only has one data member (an array) it should be aligned appropriately for any type. Dan On Aug 1, 2012, at 9:01 PM, Julien Nitard <julien.nitard@m4tp.org> wrote:
Hi,
Agreed on the general idea, quite interesting indeed, thanks for sharing.
Isn't there a space cost as well ? First the way you did you require one more byte for each object (why by the way?) which means that each "fwd" in a sequence will have something like 7 bytes of padding after it when compiling for 64 bit systems. Hopefully there aren't any alignment problems when using "fwd" but I am not expert enough to be sure, have you considered it ?
Regards,
Julien
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 08/01/12 20:18, Daniel Larimer wrote:
Julien, An extra 'byte' was just left over from me testing. It works with 8 bytes (2 ints) and it asserts on 7 bytes. I was trying to find a way to 'warn' if you reserved too much. It looks like BOOST_STATIC_WARN() has been removed.
I thought about alignment issues (I am no expert here), but my understanding is that structs/classes are always 'aligned' in the same manner regardless of what is stored. Therefore, if my fwd<> class only has one data member (an array) it should be aligned appropriately for any type.
I'm pretty sure that you're array, char fwd<T,S>::_store[S], has an alignment of 1; thus, If T is double, it would not be aligned properly. You need to use an aligned buffer, which boost provides and is also in the standard someplace. boost::variant uses the boost aligned buffer for its storage buffer. HTH. -regards, Larry

On Wed, Aug 01, 2012 at 10:37:24PM -0500, Larry Evans wrote:
On 08/01/12 20:18, Daniel Larimer wrote:
Julien, An extra 'byte' was just left over from me testing. It works with 8 bytes (2 ints) and it asserts on 7 bytes. I was trying to find a way to 'warn' if you reserved too much. It looks like BOOST_STATIC_WARN() has been removed.
I thought about alignment issues (I am no expert here), but my understanding is that structs/classes are always 'aligned' in the same manner regardless of what is stored. Therefore, if my fwd<> class only has one data member (an array) it should be aligned appropriately for any type.
I'm pretty sure that you're array, char fwd<T,S>::_store[S], has an alignment of 1; thus, If T is double, it would not be aligned properly. You need to use an aligned buffer, which boost provides and is also in the standard someplace. boost::variant uses the boost aligned buffer for its storage buffer.
Isn't there a standard section that mentions that some flavor of sequence-of-char storage must have alignment suitable for any natural alignment on the platform? Might just be constrained to free store allocations or something, I guess. -- Lars Viklund | zao@acc.umu.se

On Thursday 02 August 2012 06:03:22 Lars Viklund wrote:
Isn't there a standard section that mentions that some flavor of sequence-of-char storage must have alignment suitable for any natural alignment on the platform?
Might just be constrained to free store allocations or something, I guess.
Yes, this is a requirement for pointers returned by malloc and ::operator new. Structure's alignment is the largest alignment of its members. Array's alignment is the alignment of the array element.

On Aug 2, 2012, at 12:34 AM, Andrey Semashev <andrey.semashev@gmail.com> wrote:
On Thursday 02 August 2012 06:03:22 Lars Viklund wrote:
Isn't there a standard section that mentions that some flavor of sequence-of-char storage must have alignment suitable for any natural alignment on the platform?
Might just be constrained to free store allocations or something, I guess.
Yes, this is a requirement for pointers returned by malloc and ::operator new. Structure's alignment is the largest alignment of its members. Array's alignment is the alignment of the array element.
this requirement does not hold for stack allocated objects. Looks like I would have to modify it to use the aligned storage, although the code appears to work with mis-aligned double (pointing at an 'odd' address). I am sure that some types will require proper alignment. Options include always allocating arrays in chunks of 8 bytes by switching to an int64 array and eating the 'overhead'. Anything require alignment greater than 8 bytes?
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Thu, Aug 02, 2012 at 12:44:40AM -0400, Daniel Larimer wrote:
On Aug 2, 2012, at 12:34 AM, Andrey Semashev <andrey.semashev@gmail.com> wrote:
On Thursday 02 August 2012 06:03:22 Lars Viklund wrote:
Isn't there a standard section that mentions that some flavor of sequence-of-char storage must have alignment suitable for any natural alignment on the platform?
Might just be constrained to free store allocations or something, I guess.
Yes, this is a requirement for pointers returned by malloc and ::operator new. Structure's alignment is the largest alignment of its members. Array's alignment is the alignment of the array element.
this requirement does not hold for stack allocated objects. Looks like I would have to modify it to use the aligned storage, although the code appears to work with mis-aligned double (pointing at an 'odd' address).
Try "any type wider than an octet on pretty much any platform not x86". You're paying a massive cost on x86 for misaligned accesses too. Floating point numbers and SSE extensions will blow up even harder on misaligned accesses.
I am sure that some types will require proper alignment. Options include always allocating arrays in chunks of 8 bytes by switching to an int64 array and eating the 'overhead'. Anything require alignment greater than 8 bytes?
-- Lars Viklund | zao@acc.umu.se

On Thu, 2 Aug 2012, Daniel Larimer wrote:
I am sure that some types will require proper alignment. Options include always allocating arrays in chunks of 8 bytes by switching to an int64 array and eating the 'overhead'. Anything require alignment greater than 8 bytes?
Note that int64 could have an alignment of 4 while double would have one of 8, or other strange combinations. Also, vector (as in SSE, not std::vector) elements may want bigger alignment (and malloc has a bug on several platforms that it returns insufficiently aligned memory for those). -- Marc Glisse

On Aug 2, 2012, at 1:09 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
On Thu, 2 Aug 2012, Daniel Larimer wrote:
I am sure that some types will require proper alignment. Options include always allocating arrays in chunks of 8 bytes by switching to an int64 array and eating the 'overhead'. Anything require alignment greater than 8 bytes?
Note that int64 could have an alignment of 4 while double would have one of 8, or other strange combinations. Also, vector (as in SSE, not std::vector) elements may want bigger alignment (and malloc has a bug on several platforms that it returns insufficiently aligned memory for those).
Suppose I did this: template<typename T, unsigned int S, typename A = double> struct fwd { ... union { A _force_align; char s[S]; } _store; }; Now users of the API could 'align to' any type they wish, defaulting to double which should be sufficient for most cases. Anyone using forward declarations like this is probably doing so for types that are at least 8 bytes in size and probably not for types leveraging SSE vectors. Ideally, users of this technique would be opting for compile performance over minimizing memory use. It is bad enough that we have to specify the size manually just to reduce compile times, but specifying the alignment is probably something most users will have no clue on and therefore, the default should assume 'worst case' and align that way. Dan
-- Marc Glisse
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Thursday 02 August 2012 01:28:12 Daniel Larimer wrote:
Suppose I did this:
template<typename T, unsigned int S, typename A = double> struct fwd { ... union { A _force_align; char s[S]; } _store; };
Now users of the API could 'align to' any type they wish, defaulting to double which should be sufficient for most cases. Anyone using forward declarations like this is probably doing so for types that are at least 8 bytes in size and probably not for types leveraging SSE vectors.
I think, specifying an integral alignment would be better for this very reason. However, you will probably have to resort to compiler-specific directives to achieve alignments greater than ones for the standard types.

On Aug 1, 2012, at 11:37 PM, Larry Evans <cppljevans@suddenlink.net> wrote:
On 08/01/12 20:18, Daniel Larimer wrote:
Julien, An extra 'byte' was just left over from me testing. It works with 8 bytes (2 ints) and it asserts on 7 bytes. I was trying to find a way to 'warn' if you reserved too much. It looks like BOOST_STATIC_WARN() has been removed.
I thought about alignment issues (I am no expert here), but my understanding is that structs/classes are always 'aligned' in the same manner regardless of what is stored. Therefore, if my fwd<> class only has one data member (an array) it should be aligned appropriately for any type.
I'm pretty sure that you're array, char fwd<T,S>::_store[S], has an alignment of 1; thus, If T is double, it would not be aligned properly. You need to use an aligned buffer, which boost provides and is also in the standard someplace. boost::variant uses the boost aligned buffer for its storage buffer.
Yes, _store[S] has an alignment requirement of 1, but what is the alignment requirement for fwd<T,S>? Can we assume that this == &_store[0] ? Could we not just do 'reinterpret_cast<test*>(this)'? template<typename T, int S> struct fwd { fwd() { static_assert( sizeof(*this) >= sizeof(T) ); new (this) T(); } char _store[S]; };
HTH.
-regards, Larry
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Thursday 02 August 2012 00:28:25 Daniel Larimer wrote:
Can we assume that this == &_store[0] ?
I don't think this is a valid assumption for non-POD types, which is fwd because it has constructors and a destructor.

02.08.2012 8:28, Daniel Larimer пишет:
Yes, _store[S] has an alignment requirement of 1, but what is the alignment requirement for fwd<T,S>? It's probably 1 because _store has an alignment of 1.
Btw, what about the following? template<typename T, size_t S, typename Alignment1=char, typename Alignment2=char, typename Alignment3=char> struct fwd { fwd() { static_assert( sizeof(*this) >= sizeof(T), "!" ); new (this) T(); } union { char _store[S]; Alignment1 _alignment1; Alignment2 _alignment2; Alignment3 _alignment3; }; }; MSVC compiler has also an __alignof operator. -- Best regards, Sergey Cheban

On Wednesday 01 August 2012 20:36:03 Daniel Larimer wrote:
One of the things I realized doing this work was that often the only reason you need to include a header is because the compiler needs to know the SIZE of the type that you wish to forward declare and nothing else. So our development is slowed entirely due to the lack of a SINGLE NUMBER. So I created a utility that allowed me to 'forward declare' the size of the variable. This allowed me to use return by value and member variables via forward declaration WITHOUT having to resort to heap allocation.
This is an interesting idea but you also have to know alignment of the forwarded type. Which basically brings us to aligned_storage. I think, a simple wrapper around aligned_storage like your fwd could be a useful tool.

On Aug 1, 2012, at 11:20 PM, Andrey Semashev <andrey.semashev@gmail.com> wrote:
On Wednesday 01 August 2012 20:36:03 Daniel Larimer wrote:
One of the things I realized doing this work was that often the only reason you need to include a header is because the compiler needs to know the SIZE of the type that you wish to forward declare and nothing else. So our development is slowed entirely due to the lack of a SINGLE NUMBER. So I created a utility that allowed me to 'forward declare' the size of the variable. This allowed me to use return by value and member variables via forward declaration WITHOUT having to resort to heap allocation.
This is an interesting idea but you also have to know alignment of the forwarded type. Which basically brings us to aligned_storage. I think, a simple wrapper around aligned_storage like your fwd could be a useful tool.
Simply including boost::aligned_storage adds 1600 lines of code to be processed, most of it totally irrelevant to the task of aligned storage. I would want to implement aligned storage with much less overhead. The primary goal is to accelerate compile times and including anything from boost::mpl (which alligned_storage does) starts to pile on the code. Dan
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Thursday 02 August 2012 00:50:26 Daniel Larimer wrote:
Simply including boost::aligned_storage adds 1600 lines of code to be processed, most of it totally irrelevant to the task of aligned storage. I would want to implement aligned storage with much less overhead.
The primary goal is to accelerate compile times and including anything from boost::mpl (which alligned_storage does) starts to pile on the code.
If you can create a slim equivalent of aligned_storage, I think we could simply replace the current implementation.

On Aug 2, 2012, at 1:43 PM, Andrey Semashev <andrey.semashev@gmail.com> wrote:
On Thursday 02 August 2012 00:50:26 Daniel Larimer wrote:
Simply including boost::aligned_storage adds 1600 lines of code to be processed, most of it totally irrelevant to the task of aligned storage. I would want to implement aligned storage with much less overhead.
The primary goal is to accelerate compile times and including anything from boost::mpl (which alligned_storage does) starts to pile on the code.
If you can create a slim equivalent of aligned_storage, I think we could simply replace the current implementation.
This really gets to the heart of the design of the boost libraries. If it is possible to create a slim version of something like aligned_storage, it should also be possible to do so for many other libraries. It is a lot of work to create a 'slim' library, particularly if you don't have a collection of 'slim' libraries to build on top of. Should it be a boost wide effort to migrate toward a two-layer API, slim vs fast? In my opinion a concerted effort needs to be made to make c++ compile faster when using standard libraries and boost. Is it there anything particularly horrid about forward declaring sizes, using reinterpret cast, or other such techniques to hide implementation details and thereby improve compile times?
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

2012/8/2 Daniel Larimer <dlarimer@gmail.com>
I have been increasingly frustrated with how long it takes to compile c++ code. After spending some time in Java and C# I can feel the pain of compile times much sharper than I use to. After seeing that Java and C# were able to achieve some level of generics without requiring 'everything in the header' and knowing that C compiles an order of magnitude faster than c++ I set about to find a way to increase my compile times.
One of the common recommendations is to 'forward declare' everything and to use the PIMPL (private implementation pattern). Unfortunately, PIMPL usually implies heap allocation and if you ever want to return-by-value you are stuck including the entire header for the types you use in your header.
I started inspecting some of my code and running it through the pre-processor and noticed that almost every source file was in the 50K+ lines of code post-preprocessor and that some files were north of 250K lines of code. This was ridiculously inefficient, especially because I was already using PIMPL everywhere I could and most of these lines were stl + boost.
After a little bit of work I was able to abstract vector, boost::exception, iostream, string, threading, and many of the other types that I had been including that resulted in 'code-bloat'. The resultant library was able to reduce my post-preprocessor output to just one or two thousand lines of code (assuming the .cpp itself was 500+ lines). My compile times dropped to sub-second per object file from 10+ seconds (some up to 40 seconds).
There are some side effects from doing this, performance in some cases was slightly slower due to one level of indirection, but with with link-time optimization this performance loss was minimized. And any loss of performance was clearly acceptable trade for the gain in development efficiency. In situations were performance really is critical I can choose to include the raw header in individual cpp files, but in most cases that level of 'optimization' is overkill.
One of the things I realized doing this work was that often the only reason you need to include a header is because the compiler needs to know the SIZE of the type that you wish to forward declare and nothing else. So our development is slowed entirely due to the lack of a SINGLE NUMBER. So I created a utility that allowed me to 'forward declare' the size of the variable. This allowed me to use return by value and member variables via forward declaration WITHOUT having to resort to heap allocation.
It occurred to me that a library that allowed developers to choose a little drop in runtime performance for a dramatic improvement in compile times would be generally useful to the C++ community.
I have included an example of the 'technique' and general purpose utility that would allow others to quickly and easily integrate forward declaration of 'value types'.
A full up boost submission would probably include pre-wrapped versions of most of the STL and Boost types.
Hi, I believe the general idea has been around for years [1]. I wonder if a utility like this gets accepted to Boost. You have my interest. I think you can save a few more lines of code in the headers by separating some of the member functions of fwd (like the constructors and the destructor) into another header file, that will only get included in .cpp files. Cheers, Kris [1] http://www.gotw.ca/gotw/028.htm

Hi,
I believe the general idea has been around for years [1]. I wonder if a utility like this gets accepted to Boost. You have my interest.
I think you can save a few more lines of code in the headers by separating some of the member functions of fwd (like the constructors and the destructor) into another header file, that will only get included in .cpp files.
There is a trade off between lines of code an 'number of files loaded'. But I think you are right it could be split out. As I think of more features to add to fwd this becomes important. In my latest test I show how operators can be transparently supported. fwd only solves the problem for some classes. Classes like std::string pose a bigger challenge because they cannot be forward declared even if all you want to use is a std::string* because it is really a template / typedef. My partial solution was to attempt a class that was 'reinterpret_castable' to std string. Simply including <string> adds 4000+ lines of code to the build. Including my string.hpp adds 61 lines and is sufficient for 95% of the usage of std::string (I would finish out the interface to mirror most of std::string) leaving only a few edge cases. where std::string would be required. In the .cpp it would use the real string to implement everything.
Cheers, Kris
[1] http://www.gotw.ca/gotw/028.htm
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Thu, Aug 2, 2012 at 2:36 AM, Daniel Larimer <dlarimer@gmail.com> wrote:
I have been increasingly frustrated with how long it takes to compile c++ code. After spending some time in Java and C# I can feel the pain of compile times much sharper than I use to. After seeing that Java and C# were able to achieve some level of generics without requiring 'everything in the header' and knowing that C compiles an order of magnitude faster than c++ I set about to find a way to increase my compile times.
Did you try PCH (precompiled headers)?
One of the common recommendations is to 'forward declare' everything and to use the PIMPL (private implementation pattern). Unfortunately, PIMPL usually implies heap allocation and if you ever want to return-by-value you are stuck including the entire header for the types you use in your header.
It'd be nice if a future version of C++ allowed pimpl without space overhead. Olaf

On Thu, Aug 2, 2012 at 4:17 PM, Olaf van der Spek <ml@vdspek.org> wrote:
On Thu, Aug 2, 2012 at 2:36 AM, Daniel Larimer <dlarimer@gmail.com> wrote:
I have been increasingly frustrated with how long it takes to compile c++ code. After spending some time in Java and C# I can feel the pain of compile times much sharper than I use to. After seeing that Java and C# were able to achieve some level of generics without requiring 'everything in the header' and knowing that C compiles an order of magnitude faster than c++ I set about to find a way to increase my compile times.
Did you try PCH (precompiled headers)?
Well ... I did, they didn't work for me. Basically PCH resulted in a huge (200 MB-ish) file to be loaded for each CPP, a good portion of which was useless. Worse, I had to generate two PCHs : one for my shared libs and one for my binaries because they were not using the same compilers options. In addition, GCC options for PCH are not that easy to use / clear. What worked was parallel make, though it uses a lot of memory. Another clumsy and unpracical option was to #include my CPPs in another a larger one and compile that (it was one solution to another unrelated problem). It avoids repeating the preprocessing many times.
One of the common recommendations is to 'forward declare' everything and to use the PIMPL (private implementation pattern). Unfortunately, PIMPL usually implies heap allocation and if you ever want to return-by-value you are stuck including the entire header for the types you use in your header.
It'd be nice if a future version of C++ allowed pimpl without space overhead.
I am not sure why you are saying this, space is not the problem Daniel wants to address (though it be nice). Is it related to your message on std-proposal M.L. ? Daniel (and I ;) cares about Dymanic memory allocation. Though it would be good to measure whether modern allocators are very expensive or not ... I.E. if one couldn't replace forward by pimpl + efficient allocator. It may be worth measuring. I have been hearing about very efficient malloc implementation for a while without being able to test them practically. Does anyone have any experience ? Regards, Julien

On Thu, Aug 2, 2012 at 9:43 AM, Julien Nitard <julien.nitard@m4tp.org> wrote:
One of the common recommendations is to 'forward declare' everything and to use the PIMPL (private implementation pattern). Unfortunately, PIMPL usually implies heap allocation and if you ever want to return-by-value you are stuck including the entire header for the types you use in your header.
It'd be nice if a future version of C++ allowed pimpl without space overhead.
I am not sure why you are saying this, space is not the problem Daniel wants to address (though it be nice). Is it related to your message on std-proposal M.L. ? Daniel (and I ;) cares about Dymanic memory allocation. Though it would be good to measure whether modern
Yes, it is. I should've said heap allocation / indirection, space indeed isn't the problem. -- Olaf

On Aug 2, 2012, at 3:43 AM, Julien Nitard <julien.nitard@m4tp.org> wrote:
On Thu, Aug 2, 2012 at 4:17 PM, Olaf van der Spek <ml@vdspek.org> wrote:
On Thu, Aug 2, 2012 at 2:36 AM, Daniel Larimer <dlarimer@gmail.com> wrote:
I have been increasingly frustrated with how long it takes to compile c++ code. After spending some time in Java and C# I can feel the pain of compile times much sharper than I use to. After seeing that Java and C# were able to achieve some level of generics without requiring 'everything in the header' and knowing that C compiles an order of magnitude faster than c++ I set about to find a way to increase my compile times.
Did you try PCH (precompiled headers)?
Well ... I did, they didn't work for me. Basically PCH resulted in a huge (200 MB-ish) file to be loaded for each CPP, a good portion of which was useless. Worse, I had to generate two PCHs : one for my shared libs and one for my binaries because they were not using the same compilers options. In addition, GCC options for PCH are not that easy to use / clear. What worked was parallel make, though it uses a lot of memory. Another clumsy and unpracical option was to #include my CPPs in another a larger one and compile that (it was one solution to another unrelated problem). It avoids repeating the preprocessing many times.
I also leverage the 'unity build' technique and have a CMAKE option to automatically build libraries I am not actively editing that way. It helps dramatically, but uses a ton of RAM and eliminates the 'partial build' forcing you to pay for a full build every time.
One of the common recommendations is to 'forward declare' everything and to use the PIMPL (private implementation pattern). Unfortunately, PIMPL usually implies heap allocation and if you ever want to return-by-value you are stuck including the entire header for the types you use in your header.
It'd be nice if a future version of C++ allowed pimpl without space overhead.
I am not sure why you are saying this, space is not the problem Daniel wants to address (though it be nice). Is it related to your message on std-proposal M.L. ? Daniel (and I ;) cares about Dymanic memory allocation. Though it would be good to measure whether modern allocators are very expensive or not ... I.E. if one couldn't replace forward by pimpl + efficient allocator. It may be worth measuring. I have been hearing about very efficient malloc implementation for a while without being able to test them practically. Does anyone have any experience ?
In multi-threaded applications, even very efficient allocators will lead to lock contention or excessive memory synchronization via the use of atomics. Besides, custom memory allocators are often a huge problem of their own.
Regards,
Julien
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Aug 2, 2012, at 3:17 AM, Olaf van der Spek <ml@vdspek.org> wrote:
On Thu, Aug 2, 2012 at 2:36 AM, Daniel Larimer <dlarimer@gmail.com> wrote:
I have been increasingly frustrated with how long it takes to compile c++ code. After spending some time in Java and C# I can feel the pain of compile times much sharper than I use to. After seeing that Java and C# were able to achieve some level of generics without requiring 'everything in the header' and knowing that C compiles an order of magnitude faster than c++ I set about to find a way to increase my compile times.
Did you try PCH (precompiled headers)?
Yes, PCH have their own problems and are ineffective for situations where you are actively editing the headers. The compiler still has to process them too.
One of the common recommendations is to 'forward declare' everything and to use the PIMPL (private implementation pattern). Unfortunately, PIMPL usually implies heap allocation and if you ever want to return-by-value you are stuck including the entire header for the types you use in your header.
It'd be nice if a future version of C++ allowed pimpl without space overhead.
Keep in mind the other use case is this: class X { public: fwd<test,24> getByValue()const; } Not shown in my initial example is that fwd<> automatically casts to test or anything test automatically casts to. In this case, even an efficient malloc will not save class X. Perhaps fwd<> could be implemented via the heap... but that is an expensive way to solve the alignment problem.
Olaf
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (9)
-
Andrey Semashev
-
Daniel Larimer
-
Julien Nitard
-
Krzysztof Czainski
-
Larry Evans
-
Lars Viklund
-
Marc Glisse
-
Olaf van der Spek
-
Sergey Cheban