Diferença de velocidade fprintf massiva sem “-std = c99”

Eu vinha lutando há semanas com um tradutor de baixo desempenho que eu havia escrito. No seguinte simples bechmark

#include<stdio.h>

int main()
{
    int x;
    char buf[2048];
    FILE *test = fopen("test.out", "wb");
    setvbuf(test, buf, _IOFBF, sizeof buf);
    for(x=0;x<1024*1024; x++)
        fprintf(test, "%04d", x);
    fclose(test);
    return 0
}

nós vemos o seguinte resultado

bash-3.1$ gcc -O2 -static test.c -o test
bash-3.1$ time ./test

real    0m0.334s
user    0m0.015s
sys     0m0.016s

Como você pode ver, no momento em que o sinalizador "-std = c99" é adicionado, o desempenho desaba:

bash-3.1$ gcc -O2 -static -std=c99 test.c -o test
bash-3.1$ time ./test

real    0m2.477s
user    0m0.015s
sys     0m0.000s

O compilador que estou usando é o gcc 4.6.2 mingw32.

O arquivo gerado é de cerca de 12M, então esta é uma diferença entre cerca de 21MB / s entre os dois.

Corridadiff mostra que os arquivos gerados são idênticos.

Eu assumi que isso tem algo a ver com o bloqueio de arquivosfprintf, dos quais o programa faz uso pesado, mas eu não consegui encontrar uma maneira de mudar isso na versão C99.

eu tenteiflockfile no fluxo que eu uso no início do programa, e um correspondentefunlockfile no final, mas foi recebido com erros de compilador sobre declarações implícitas e erros de linker reivindicando referências indefinidas para essas funções.

Poderia haver outra explicação para esse problema e, mais importante, há alguma maneira de usar o C99 no Windows sem pagar um preço de desempenho tão alto?

Editar:

Depois de olhar para o código gerado por essas opções, parece que nas versões lentas, mingw varas no seguinte:

_fprintf:
LFB0:
    .cfi_startproc
    subl    $28, %esp
    .cfi_def_cfa_offset 32
    leal    40(%esp), %eax
    movl    %eax, 8(%esp)
    movl    36(%esp), %eax
    movl    %eax, 4(%esp)
    movl    32(%esp), %eax
    movl    %eax, (%esp)
    call    ___mingw_vfprintf
    addl    $28, %esp
    .cfi_def_cfa_offset 4
    ret
    .cfi_endproc 

Na versão rápida, isso simplesmente não existe; caso contrário, ambos são exatamente iguais. eu assumo__mingw_vfprintf parece ser o slowpoke aqui, mas eu não tenho idéia do comportamento que precisa para emular o que torna tão lento.

questionAnswers(4)

yourAnswerToTheQuestion