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.