7

私が構築したgrepがシステムに付属するものよりもはるかに遅い理由を理解しようとしており、システムに付属しているgrepで使用されるコンパイラオプションを見つけようとしています。

OS バージョン: CentOS リリース 5.3 (最終) システム上の grep:

  バージョン: grep (GNU grep) 2.5.1
  サイズ: 88896 バイト
  ldd 出力:
 libpcre.so.0 => /lib64/libpcre.so.0 (0x0000003991800000)
 libc.so.6 => /lib64/libc.so.6 (0x0000003985a00000)
 /lib64/ld-linux-x86-64.so.2 (0x0000003984a00000)

私が作成したgrep:

  バージョン: 2.5.1
  サイズ: 256437 バイト
  ldd 出力:
 libpcre.so.0 => /lib64/libpcre.so.0 (0x0000003991800000)
 libc.so.6 => /lib64/libc.so.6 (0x0000003985a00000)
 /lib64/ld-linux-x86-64.so.2 (0x0000003984a00000)

大きなリスト テキスト ファイルに対して正規表現検索を実行すると、システム grep のパフォーマンス (330 ミリ秒) は、私が構築した grep (22430 ミリ秒) よりもはるかに高速です。

以下は、私が時間を計るのに使用したコマンドです..

% time src/grep ".*asa.*" large_list.txt > /dev/null
実質 0m22.430s
ユーザー 0m22.291s
システム 0m0.080s

また

% time bin/grep ".*asa.*" large_list.txt > /dev/null
実質 0m0.331s
ユーザー 0分0.236秒
システム 0m0.081s

システム grep は明らかに、パフォーマンスに大きな違いをもたらすいくつかの最適化オプションを使用しています。

システム grep がどのオプションで構築されているかについて、誰かが私を助けてくれますか?

これは、ビルド時のソース ファイルの 1 つのコンパイル オプションです。
gcc -DLIBDIR=\"/usr/local/lib\" -DHAVE_CONFIG_H -I. -I.. -I.. -I. -I../intl -g -O2 -MT xstrtol.o -MD -MP -MF .deps/xstrtol.Tpo -c -o xstrtol.o xstrtol.c

./configure の出力:

BSD 互換のインストールをチェックしています... /usr/bin/install -c
ビルド環境が正常かどうかを確認しています...はい
スレッドセーフな mkdir -p... /bin/mkdir -p をチェックしています
gawk をチェック中... gawk
make が $(MAKE) を設定しているかどうかをチェックしています... はい
ビルド システムの種類を確認しています... x86_64-unknown-linux-gnu
ホスト システムの種類を確認しています... x86_64-unknown-linux-gnu
gawk をチェック中... (キャッシュされた) gawk
gcc をチェックしています... gcc
Cコンパイラのデフォルトの出力ファイル名をチェックしています... a.out
Cコンパイラが動作するかどうかをチェックしています...はい
クロスコンパイルしているかどうかを確認しています...いいえ
実行可能ファイルのサフィックスをチェックしています...
オブジェクトファイルのサフィックスをチェックしています... o
GNU Cコンパイラを使用しているかどうかをチェックしています...はい
gccが-gを受け入れるかどうかを確認しています...はい
ISO C89を受け入れるためのgccオプションをチェックしています...必要ありません
make で使用されるインクルードのスタイルをチェックしています... GNU
gcc の依存スタイルをチェックしています... gcc3
BSD 互換のインストールをチェックしています... /usr/bin/install -c
ranlib をチェックしています... ranlib
getconf をチェックしています... getconf
大きなファイルのサポートを要求する CFLAGS 値をチェックしています...
大きなファイルのサポートを要求する LDFLAGS 値をチェックしています...
大きなファイルのサポートを要求するための LIBS 値をチェックしています...
_FILE_OFFSET_BITS をチェックしています... いいえ
_LARGEFILE_SOURCE をチェックしています... いいえ
_LARGE_FILES をチェックしています... いいえ
関数プロトタイプをチェックしています...はい
Cプリプロセッサの実行方法をチェックしています... gcc -E
長い行を処理する grep のチェックと -e... /bin/grep
egrep をチェックしています... /bin/grep -E
ANSI C ヘッダー ファイルをチェックしています...はい
sys/types.h をチェックしています...はい
sys/stat.h をチェックしています...はい
stdlib.hをチェックしています...はい
string.h をチェックしています...はい
memory.h をチェックしています...はい
strings.h をチェックしています...はい
inttypes.h のチェック...はい
stdint.hをチェックしています...はい
unistd.hをチェックしています...はい
string.h のチェック... (キャッシュ) はい
size_t をチェックしています...はい
ssize_t をチェックしています...はい
ANSI C準拠の定数をチェックしています...はい
inttypes.h のチェック...はい
unsigned long long のチェック...はい
ANSI C ヘッダー ファイルをチェックしています... (キャッシュ) はい
string.h のチェック... (キャッシュ) はい
stdlib.h のチェック... (キャッシュ) はい
sys/param.h のユーザビリティをチェックしています...はい
sys/param.h の存在を確認しています...はい
sys/param.h をチェックしています...はい
memory.h のチェック... (キャッシュ) はい
unistd.h のチェック... (キャッシュ) はい
libintl.h のユーザビリティをチェックしています...はい
libintl.h の存在を確認しています...はい
libintl.hをチェックしています...はい
wctype.h のユーザビリティをチェックしています...はい
wctype.h の存在を確認しています...はい
wctype.hをチェックしています...はい
wchar.h のユーザビリティをチェックしています...はい
wchar.h の存在を確認しています...はい
wchar.hをチェックしています...はい
DIRを定義するdirent.hをチェックしています...はい
opendirを含むライブラリをチェックしています...必要ありません
stat ファイルモード マクロが壊れているかどうかを確認しています...いいえ
alloca.h の動作を確認しています...はい
割り当てをチェックしています...はい
closedir が void を返すかどうかを確認しています...いいえ
stdlib.h のチェック... (キャッシュ) はい
unistd.h のチェック... (キャッシュ) はい
getpagesize をチェックしています...はい
動作中の mmap をチェックしています...はい
btowcをチェックしています...はい
isasciiをチェックしています...はい
iswctypeをチェックしています...はい
mbrlenをチェックしています...はい
memmove をチェックしています...はい
setmode をチェックしています... いいえ
strerror をチェックしています...はい
wcrtombをチェックしています...はい
wcscollをチェックしています...はい
wctypeをチェックしています...はい
mbrtowc と mbstate_t が適切に宣言されているかどうかを確認しています...はい
stdlib.h のチェック... (キャッシュ) はい
mbstate_t をチェックしています...はい
memchrをチェックしています...はい
stpcpyをチェックしています...はい
strtoulをチェックしています...はい
atexitをチェックしています...はい
fnmatch をチェックしています...はい
stdlib.h のチェック... (キャッシュ) はい
strtoumax をマクロとして定義しているかどうかをチェックしています...いいえ
strtoumaxをチェックしています...はい
strtoul が宣言されているかどうかを確認しています...はい
strtoull が宣言されているかどうかを確認しています...はい
-lcposix で strerror をチェックしています... いいえ
インラインをチェックしています...インライン
off_tをチェックしています...はい
GNU C Library 2.1以降を使用しているかどうかを確認しています...はい
argz.h のユーザビリティをチェックしています... はい
argz.h の存在を確認しています...はい
argz.h をチェックしています...はい
limits.h の使いやすさをチェックしています... はい
limits.h の存在を確認しています... はい
limits.h のチェック...はい
locale.h のユーザビリティをチェックしています...はい
locale.h の存在を確認しています...はい
locale.h をチェックしています...はい
nl_types.h のユーザビリティをチェックしています...はい
nl_types.h の存在を確認しています...はい
nl_types.h のチェック...はい
malloc.h のユーザビリティをチェックしています...はい
malloc.hの存在を確認しています...はい
malloc.hをチェックしています...はい
stddef.h のユーザビリティをチェックしています...はい
stddef.h の存在を確認しています...はい
stddef.h をチェックしています...はい
stdlib.h のチェック... (キャッシュ) はい
string.h のチェック... (キャッシュ) はい
unistd.h のチェック... (キャッシュ) はい
sys/param.h のチェック... (キャッシュ) はい
feof_unlocked のチェック...はい
fgets_unlocked をチェックしています...はい
getcwd をチェックしています...はい
getegid をチェックしています...はい
geteuid をチェックしています...はい
getgid をチェックしています...はい
getuid をチェックしています...はい
mempcpyをチェックしています...はい
munmap をチェックしています...はい
putenv をチェックしています...はい
setenvをチェックしています...はい
setlocaleをチェックしています...はい
stpcpy をチェック中... (キャッシュ) はい
strchrをチェックしています...はい
strcasecmpをチェックしています...はい
strdupをチェックしています...はい
strtoul のチェック... (キャッシュ) はい
tsearch をチェックしています...はい
__argz_count をチェックしています...はい
__argz_stringify をチェックしています...はい
__argz_next をチェックしています...はい
iconvをチェックしています...はい
iconv 宣言をチェックしています...
         extern size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
nl_langinfo と CODESET をチェックしています...はい
LC_MESSAGES をチェックしています...はい
NLSが要求されているかどうかを確認しています...はい
含まれている gettext が要求されているかどうかを確認しています...いいえ
libintl.h のチェック... (キャッシュ) はい
libcでGNU gettextをチェックしています...はい
dcgettext をチェックしています...はい
msgfmt をチェックしています... /usr/bin/msgfmt
gmsgfmt をチェック中... /usr/bin/msgfmt
xgettext をチェックしています... /usr/bin/xgettext
バイソンをチェックしています...バイソン
bison のバージョンを確認しています... 2.3、わかりました
インストールするカタログをチェックしています... af be bg ca cs da de el eo es et eu fi fr ga gl he hr hu id it ja ko ky lt nb nl pl pt pt_BR ro rw sk sl sr sv tr uk vi zh_TW
dos ファイルの規則をチェックしています... いいえ
ホスト システムの種類を確認しています... (キャッシュ) x86_64-unknown-linux-gnu
ホスト システムの種類を確認しています... (キャッシュ) x86_64-unknown-linux-gnu
DJGPP環境をチェックしています...いいえ
環境変数セパレーターをチェックしています...:
re_compile_pattern の動作を確認しています...はい
getopt_long をチェックしています...はい
configure: 警告: 同梱の lib/regex.c は使用されていません
strerror_r が宣言されているかどうかを確認しています...はい
strerror_rをチェックしています...はい
strerror_r が char *... no を返すかどうかを確認しています
strerror をチェックしています... (キャッシュ) はい
strerror_r のチェック... (キャッシュ) はい
vprintf をチェックしています...はい
doprnt をチェックしています... いいえ
ANSI C ヘッダー ファイルをチェックしています... (キャッシュ) はい
動作しているmallocをチェックしています...はい
再割り当てが機能しているかどうかを確認しています...はい
-lpcre で pcre_exec をチェックしています...はい
構成: ./config.status の作成
config.status: Makefile の作成
config.status: lib/Makefile の作成
config.status: lib/posix/Makefile の作成
config.status: src/Makefile を作成しています
config.status: テストの作成/Makefile
config.status: po/Makefile.in を作成しています
config.status: intl/Makefile の作成
config.status: 警告: intl/Makefile.in は --datarootdir 設定を無視しているようです
config.status: doc/Makefile を作成しています
config.status: m4/Makefile の作成
config.status: vms/Makefile の作成
config.status: ブートストラップ/Makefile の作成
config.status: config.h の作成
config.status: config.h は変更されていません
config.status: depfiles コマンドの実行
config.status: default-1 コマンドの実行
config.status: po/POTFILES の作成
config.status: po/Makefile の作成
config.status: stamp-h コマンドの実行

ありがとう、クマール

4

5 に答える 5

10

CentOS の SRPM の grep バイナリを入手して、それらのコンパイル オプションを自分のものと比較してみませんか? これは、StackOverflow コミュニティ全体が何かにぶつかるまで暗闇の中でやみくもに動き回るよりもはるかに効率的であると思います。

編集: マルチバイトエンコーディングのロケールを使用していますか? (注: それが何を意味するのかわからない場合、答えはおそらく「はい」です。なぜなら、ここ数年、ほとんどの Linux ディストリビューションで UTF-8 がデフォルトであり、実際に RedHat (したがって CentOS) が最初に UTF-8 を採用したからです。切り替えます)。

その場合、GNU grep非常に遅いです。これは GNU grep だけでなく、何らかのテキスト処理を行うほとんどすべての GNU ツールに当てはまります。FSF は、パッチが固定幅エンコーディングを遅くしないことが証明されていない限り、マルチバイト パフォーマンスを改善するためのパッチを受け入れることを拒否します。ただし、マルチバイトエンコーディングのパフォーマンスを向上させるパッチには、少なくともどこかに何らかのステートメントが含まれている必要あるため、少なくともそのステートメントifのオーバーヘッドによって固定幅エンコーディングを少なくとも遅くしないパッチを作成することは実際には不可能です。ifしたがって、GNU ツールの UTF-8 のパフォーマンスは、時間の終わりまで引き続き低下します。

とにかく、ほとんどの Linux ディストリビューターは、FSF が考​​えていることをまったく気にせず、とにかく GNU grep にパッチを当てています。Fedora Rawhide SRPMには、 grep-2.5.3-egf-speedup.patchGNU grep の UTF-8 パフォーマンスを数桁高速化するというパッチが含まれています。(このパッチはすでに 2005 年のものなので、CentOS でも使用されていると思います。) このパッチは Mac OSX、Debian、Ubuntu などでも使用されています。GNU によって配布されている GNU grep を使用する人はほとんどいません。マルチバイトエンコーディングでのテキスト処理は、固定幅エンコーディングほど速くはありませんが、少なくとも同等であり、50 倍 (一部の人々が報告しているように 1500 倍) 遅くはありません。

と呼ばれる別のパッチもありますdfa-optional。これは、grep がそれ自体の代わりに GNU libc の正規表現エンジンを使用するようにするもので、UTF-8 を処理するときにはるかに高速であるだけでなく、バ​​グもはるかに少なくなります。

そのため、setを使用してベンチマークを再実行することをお勧めしますexport LC_ALL=POSIX。これで問題が解決した場合は、上記の 2 つのパッチのいずれかを適用する必要があります。

詳細情報は、次の 2 つの RedHat バグレポートでも入手できます。

この話の教訓: 一般に信じられていることとは裏腹に、Linux ディストリビューター自分たちが何をしているのかを知っていることがあります。少なくとも時々はそうです。それらを再推測しないでください。

于 2009-12-24T00:22:59.367 に答える
4

-O2フラグを付けてコンパイルしました。-03なぜ旗を使わなかったのですか?gcc で利用可能な最適化オプションの説明については、こちらを参照してください。

Intel の ICC コンパイラを使用することもパフォーマンスの向上に役立ちますが、これはアプリによって異なります。また、無料ではありません。

編集、コンパイル行に -g フラグが表示されました。デバッグ機能がオンになっているため、これを削除します。これにより、パフォーマンスが大幅に低下する可能性があります

于 2009-12-23T22:27:04.747 に答える
1

どのバージョンの GCC を使用していますか? IIRC、GCC 4 は大幅に再設計され、しばらくの間、一部の最適化コードが無効になりました。

于 2009-12-24T05:35:45.547 に答える
1

-O オプション以外に注意すべきもう 1 つの考えは、デバッグ シンボル "-g" を使用してビルドしているように見えることです。

デバッグは通常、バイナリ サイズを増加させ、バイナリのパフォーマンスを低下させる可能性があります。grep は非常に安定しており、デバッグ シンボルは実際には必要ありません。

于 2009-12-23T22:37:51.517 に答える
0

パフォーマンスの大きな違いは、おそらくアルゴリズム/コードの違いであり、コンパイラの最適化レベルの違いだけではありません。コンパイラを疑う理由は何ですか?

于 2009-12-23T22:31:04.393 に答える