Compilation speed could be reduced significantly with the addition of extern template declaration in non-header mode.
Compilation times for the following snippet (with cmake release build):
#include <fmt/format.h>
namespace fmt{
extern template FMT_API format_context::iterator internal::vformat_to(
internal::buffer<char>&, string_view, basic_format_args<format_context>);
// ... all templates from fmt/src/format.cc
}
int main(){
fmt::memory_buffer b;
fmt::format_to(b, "Hello, {}!", "world");
return 0;
}
Thanks for the suggestion but you can get better compile times by using the core API: https://fmt.dev/dev/api.html#core-api
Is there some downsides of using extern template?
Compilation time of (code using) format.h with extern templates are comprable to core.h .
I can think only of inlining, but this probably should not be the problem with string formatting library and could be resolved by lto
The main drawback is duplication but I guess it can be addressed by only having the following two instantiations extern:
extern template FMT_API std::string internal::vformat<char>(
string_view, basic_format_args<format_context>);
extern template FMT_API format_context::iterator internal::vformat_to(
internal::buffer<char>&, string_view, basic_format_args<format_context>);
A PR would be welcome.
I think we could avoid duplication by splitting src/format.cc into something like:
FMT_EXTERN template FMT_API std::string internal::vformat<char>(
string_view, basic_format_args<format_context>);
...
#define FMT_EXTERN
#include "fmt/format-non-header.h"
#define FMT_EXTERN extern
#include "fmt/format-non-header.h"
If it is ok, I'll make PR.
If that's just two declarations I mentioned earlier then duplicating is fine. I don't think the rest save much and I'd rather not introduce another header just for this.
Added extern template in https://github.com/fmtlib/fmt/commit/6f435f55c88f6a143e064fa061ee32ae4152bca9 which brought the compile time from 2.3s to 0.3s with -O2 or from 0.6s to 0.3s with the default settings (-O0).
Before (-O2):
% time g++ -c test.cc -I include -std=c++17 -O2
g++ -c test.cc -I include -std=c++17 -O2 2.22s user 0.08s system 99% cpu 2.311 total
After (-O2):
% time g++ -c test.cc -I include -std=c++17 -O2
g++ -c test.cc -I include -std=c++17 -O2 0.26s user 0.04s system 98% cpu 0.303 total
Before (default):
% time g++ -c test.cc -I include -std=c++17
g++ -c test.cc -I include -std=c++17 0.53s user 0.06s system 98% cpu 0.601 total
After (default):
% time g++ -c test.cc -I include -std=c++17
g++ -c test.cc -I include -std=c++17 0.24s user 0.06s system 98% cpu 0.301 total
Thanks for the suggestion!
Most helpful comment
Added
extern templatein https://github.com/fmtlib/fmt/commit/6f435f55c88f6a143e064fa061ee32ae4152bca9 which brought the compile time from 2.3s to 0.3s with -O2 or from 0.6s to 0.3s with the default settings (-O0).Before (-O2):
After (-O2):
Before (default):
After (default):
Thanks for the suggestion!