我曾经苦于一位我自己写的翻译器表现不佳已经好几个星期了。 在下面这个简单的基准测试中
#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。
生成的文件大约有12M,因此这两者之间存在着21MB/s左右的差异。
运行diff
显示生成的文件完全相同。
我认为这与程序中大量使用的fprintf
文件锁有关,但我无法找到在C99版本中关闭它的方法。
我尝试在程序开头使用flockfile
函数,并在结尾处使用相应的funlockfile
函数,但却遇到了隐式声明的编译器错误以及链接器错误声称这些函数未定义。
除了文件锁,还有其他可能导致这个问题的原因吗?更重要的是,在Windows上是否有使用C99而不付出如此巨大性能代价的方法?
编辑:
查看这些选项生成的代码后,发现在慢速版本中,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
似乎是这里的拖累,但我不知道它需要模仿什么行为才能使其如此缓慢。在快速版本中,这个东西就不存在;否则,两者完全相同。我认为
__mingw_vfprintf
似乎是这里的拖累,但我不知道它需要模仿什么行为才能使其如此缓慢。
printf
上,以至于我犯了这个网站的基本规则。我甚至没有想到问题可能出在其他地方。 - Dave_fprintf
不存在。那么,主循环是什么样子的呢? - rodrigofprintf
,主循环是相同的。我现在正在尝试查看mingw源代码,看看是否有任何瓶颈。 - Dave