Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add extern template in non-header mode #1452

Closed
alex3d opened this issue Dec 4, 2019 · 6 comments
Closed

Add extern template in non-header mode #1452

alex3d opened this issue Dec 4, 2019 · 6 comments

Comments

@alex3d
Copy link

alex3d commented Dec 4, 2019

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):

  • with extern template: ~ 0.6s
  • without extern template: ~ 2.5s
#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;
}
@vitaut
Copy link
Contributor

vitaut commented Dec 4, 2019

Thanks for the suggestion but you can get better compile times by using the core API: https://fmt.dev/dev/api.html#core-api

@vitaut vitaut closed this as completed Dec 4, 2019
@alex3d
Copy link
Author

alex3d commented Dec 4, 2019

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

@vitaut
Copy link
Contributor

vitaut commented Dec 6, 2019

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.

@alex3d
Copy link
Author

alex3d commented Dec 6, 2019

I think we could avoid duplication by splitting src/format.cc into something like:

  • include/fmt/format-non-header.h
FMT_EXTERN template FMT_API std::string internal::vformat<char>(
    string_view, basic_format_args<format_context>);
...
  • src/format.cc
#define FMT_EXTERN
#include "fmt/format-non-header.h"
  • include/fmt/format.h
#define FMT_EXTERN extern
#include "fmt/format-non-header.h"

If it is ok, I'll make PR.

@vitaut
Copy link
Contributor

vitaut commented Dec 6, 2019

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.

@vitaut
Copy link
Contributor

vitaut commented Apr 26, 2020

Added extern template in 6f435f5 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!

@vitaut vitaut closed this as completed Apr 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants