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

Difference in performance between the default and explicit presentation specifiers in format string compilation #4108

Open
ZENOTME opened this issue Aug 5, 2024 · 1 comment

Comments

@ZENOTME
Copy link

ZENOTME commented Aug 5, 2024

Format Specification can used to constrain the type safety but I find that when format using Format Specification, there is a huge decline in performance. Is there way to avoid this.

test code usin google bench

constexpr const char *log_fmt =
   "arg1:{} arg2:{} arg3:{} arg4:{} arg5:{} arg6:{} arg7:{} arg8:{} arg9:{} arg10:{} "
        "arg11:{}(ms) arg12:{} arg13:{} arg14:{} arg15:{} arg16:{} arg17:{} arg18:{}";
constexpr const char *log_const_fmt =
    "arg1:{:p} arg2:{:d} arg3:{:p} arg4:{:s} arg5:{:s} arg6:{:d} arg7:{:s} arg8:{:d} arg9:{:s} arg10:{:d} "
    "arg11:{:g}(ms) arg12:{:s} arg13:{:d} arg14:{:s} arg15:{:s} arg16:{:d} arg17:{:d} arg18:{:s}";
char prefix[] = "arg1:0x12345678 arg2:12345 arg3:0x87654321 arg4:example_user ";
void *arg1 = (void *)0x12345678;    
unsigned long arg2 = 12345;         
void *arg3 = (void *)0x87654321;  
const char *arg4 = "example_user"; 
int arg4_1 = 12;                 
const char *arg5 = "example_C";   
int arg5_1 = 9;                   
int arg6 = 100;                   
const char *arg7 = "example_G";   
int arg7_1 = 9;                   
int arg8 = 200;                   
const char *arg9 = "example_S";   
int arg9_1 = 9;                   
int arg10 = 300;                  
float arg11 = 123.123;          
const char *arg12 = "00000";    
int arg13 = 0;                  
const char *arg14 = "No error"; 
const char *arg15 = "query_id"; 
int arg15_1 = 8;                
int arg16 = 42;                 
long arg17 = 9876543210;        
const char *arg18 = "SELECT * FROM table WHERE id = 1"; 
int arg18_1 = 32; 

template<typename... Args>
char* compile_format(Args...args) {
    fmt::basic_memory_buffer<char, 320> buf;
    fmt::format_to(fmt::appender(buf), FMT_COMPILE(log_fmt), args...);
    return buf.data();
}

static void bench_spdlog_compile_format(benchmark::State& state)
{
    for (auto _: state) {
        benchmark::DoNotOptimize(compile_format(arg1, arg2, (int)(long)arg3, arg4, arg5, arg6,
              arg7, arg8, arg9, arg10, arg11, arg12, arg13,
              arg14, arg15, arg16, arg17, arg18));
    }
}
BENCHMARK(bench_spdlog_compile_format);

template<typename... Args>
char* compile_constrain_format(Args...args) {
    fmt::basic_memory_buffer<char, 320> buf;
    fmt::format_to(fmt::appender(buf), FMT_COMPILE(log_const_fmt), args...);
    return buf.data();
}

static void bench_spdlog_constrain_compile_format(benchmark::State& state)
{
    for (auto _: state) {
        benchmark::DoNotOptimize(compile_constrain_format(arg1, arg2, arg3, arg4, arg5, arg6,
              arg7, arg8, arg9, arg10, arg11, arg12, arg13,
              arg14, arg15, arg16, arg17, arg18));
    }
}
BENCHMARK(bench_spdlog_constrain_compile_format);

result

bench_spdlog_compile_format 349 ns 349 ns 1971834
bench_spdlog_constrain_compile_format 2586 ns 2586 ns 270360

@vitaut
Copy link
Contributor

vitaut commented Aug 5, 2024

The default format is more optimized in the format string compilation. In general it doesn't make sense to use redundant specifiers but we could handle them in the same way (note that g is not equivalent to the default though). A PR would be welcome.

@vitaut vitaut changed the title Format Specification has a huge decline in performance Difference in performance between the default and explicit presentation specifiers in format string compilation Aug 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants