Значительная разница в скорости fprintf без «-std = c99»
Я неделями боролся с плохо работающим переводчиком, которого я написал. На следующем простом 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
}
мы видим следующий результат
bash-3.1$ gcc -O2 -static test.c -o test
bash-3.1$ time ./test
real 0m0.334s
user 0m0.015s
sys 0m0.016s
Как видите, в момент добавления флага "-std = c99" производительность падает:
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
Я использую компилятор gcc 4.6.2 mingw32.
Размер сгенерированного файла составляет около 12 МБ, поэтому разница между ними составляет около 21 МБ / с.
Бегdiff
показывает, что сгенерированные файлы идентичны.
Я предположил, что это как-то связано с блокировкой файлов вfprintf
, из которых программа интенсивно использует, но я не смог найти способ отключить это в версии C99.
Я пыталсяflockfile
в потоке я использую в начале программы, и соответствующийfunlockfile
в конце, но был встречен с ошибками компилятора о неявных объявлениях и ошибками компоновщика, требующими неопределенных ссылок на эти функции.
Может ли быть другое объяснение этой проблемы, и что более важно, есть ли способ использовать C99 на Windows, не платя такую огромную цену производительности?
Редактировать:Посмотрев на код, сгенерированный этими опциями, он выглядит как в медленных версиях, mingw придерживается следующего:
_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
В быстрой версии этого просто не существует; в противном случае оба абсолютно одинаковы. Я предполагаю__mingw_vfprintf
кажется, что это медленный удар, но я понятия не имею, какое поведение ему нужно для эмуляции, что делает его таким медленным.