私は、自分が書いたパフォーマンスの悪い翻訳者と何週間も格闘していました。次の簡単な基準について
#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
ではスローポークのように思われますが、エミュレートする必要がある動作が非常に遅くなる理由がわかりません。