Changes between Version 24 and Version 25 of BestPracticeHandbook


Ignore:
Timestamp:
May 15, 2015, 9:43:53 PM (7 years ago)
Author:
Niall Douglas
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • BestPracticeHandbook

    v24 v25  
    953953The approaches for improving build times for your library users are generally as follows, and in order of effect:
    954954
    955  1. Offer a non-header only build configuration:: Here is how many Boost libraries offer both header only and non-header only build configurations by using something like this in their config.hpp:
     955'''1. Offer a non-header only build configuration'''
     956
     957 Non-header build configurations can offer build time improvements of x4 or more, so these are always the best bang for your buck. Here is how many Boost libraries offer both header only and non-header only build configurations by using something like this in their config.hpp:
    956958
    957959 {{{#!c++
     
    10071009 This looks a bit complicated, but isn't really. Generally you will mark up those classes and structs you implement in a .ipp file (this being the file implementing the APIs declared in the header) with `BOOST_AFIO_DECL`, functions with `BOOST_AFIO_HEADERS_ONLY_FUNC_SPEC`, all out-of-class member functions (i.e. those not implemented inside the class or struct declaration) with `BOOST_AFIO_HEADERS_ONLY_MEMFUNC_SPEC`, all virtual member functions with `BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC` and append to all unimplemented virtual member functions  `BOOST_AFIO_HEADERS_ONLY_VIRTUAL_UNDEFINED_SPEC`. This inserts the correct markup to generate both optimal header only and optimal non header only outcomes.
    10081010
    1009  2. Precompiled headers:: todo
    1010 
    1011  3. extern template pre-instantiated copies of your templates with their most common template parameters into a separate static library:: todo
     1011'''2. Precompiled headers'''
     1012
     1013 You probably noticed that in the table above that precompiled headers gain nothing on clang, +13% on GCC and +70% on MSVC. Those percentages vary according to source code, but I have found them fairly similar across my own projects - on MSVC, precompiled headers are a must have on an already much faster compiler than any of the others.
     1014
     1015 Turning on precompiled headers in Boost.Build is easy:
     1016 {{{
     1017cpp-pch afio_pch : afio_pch.hpp : <include>. ;
     1018 }}}
     1019 And now simply link your program to afio_pch to enable. If you're on cmake, you definitely should check out https://github.com/sakra/cotire.
     1020
     1021'''3. `extern template` your templates with their most common template parameters in the headers, and force instantiate those same common instances into a separate static library'''
     1022
     1023 The following demonstrates the technique:
     1024 {{{#!c++
     1025// Header.hpp
     1026template<class T> struct Foo
     1027{
     1028  T v;
     1029  inline Foo(T _v);
     1030};
     1031// Definition must be made outside struct Foo for extern template to have effect
     1032template<class T> inline Foo<T>::Foo(T _v) : v(_v) { }
     1033
     1034// Inhibit automatic instantiation of struct Foo for common types
     1035extern template struct Foo<int>;
     1036extern template struct Foo<double>;
     1037
     1038
     1039// Source.cpp
     1040#include "Header.hpp"
     1041#include <stdio.h>
     1042
     1043// Force instantiation of struct Foo with common types. Usually compiled into
     1044// a separate static library as bundling it into the main shared library can
     1045// introduce symbol visibility problems, so it's easier and safer to use a static
     1046// library
     1047template struct Foo<int>;
     1048template struct Foo<double>;
     1049
     1050int main(void)
     1051{
     1052  Foo<long> a(5);   // Works!
     1053  Foo<int> b(5);    // Symbol not found if not force instantiated above
     1054  Foo<double> c(5); // Symbol not found if not force instantiated above
     1055  printf("a=%l, b=%d, c=%lf\n", a.v, b.v, c.v);
     1056  return 0;
     1057}
     1058 }}}
     1059 The idea behind this is to tell the compiler to not instantiate common instantiations of your template types on demand for every single compiland as you will explicitly instantiate them exactly once elsewhere. This can give quite a bump to build times for template heavy libraries.
    10121060
    10131061