встроенный grep медленнее, чем grep, который поставляется с Linux - PullRequest
7 голосов
/ 24 декабря 2009

Я пытаюсь понять, почему созданный мной grep намного медленнее, чем тот, который поставляется с системой, и пытаюсь выяснить, какие опции компилятора использует grep, поставляемый с системой.

Версия ОС: выпуск CentOS 5.3 (финальный) grep по системе:

  Version: grep (GNU grep) 2.5.1
  Size: 88896 bytes
  ldd output: 
 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 построен мной:

  Version: 2.5.1
  Size: 256437 bytes
  ldd output:
 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
real 0m22.430s
user 0m22.291s
sys 0m0.080s

OR

% time bin/grep ".*asa.*" large_list.txt > /dev/null
real 0m0.331s
user 0m0.236s
sys 0m0.081s

Система grep явно использует некоторые опции оптимизации, которые дают огромную разницу в производительности.

Может ли какой-нибудь орган помочь мне с какими опциями может быть собран системный grep?

Вот параметры компиляции для одного из исходных файлов при сборке.
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:

checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking for gawk... (cached) gawk
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables... 
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
checking for a BSD-compatible install... /usr/bin/install -c
checking for ranlib... ranlib
checking for getconf... getconf
checking for CFLAGS value to request large file support... 
checking for LDFLAGS value to request large file support... 
checking for LIBS value to request large file support... 
checking for _FILE_OFFSET_BITS... no
checking for _LARGEFILE_SOURCE... no
checking for _LARGE_FILES... no
checking for function prototypes... yes
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking for string.h... (cached) yes
checking for size_t... yes
checking for ssize_t... yes
checking for an ANSI C-conforming const... yes
checking for inttypes.h... yes
checking for unsigned long long... yes
checking for ANSI C header files... (cached) yes
checking for string.h... (cached) yes
checking for stdlib.h... (cached) yes
checking sys/param.h usability... yes
checking sys/param.h presence... yes
checking for sys/param.h... yes
checking for memory.h... (cached) yes
checking for unistd.h... (cached) yes
checking libintl.h usability... yes
checking libintl.h presence... yes
checking for libintl.h... yes
checking wctype.h usability... yes
checking wctype.h presence... yes
checking for wctype.h... yes
checking wchar.h usability... yes
checking wchar.h presence... yes
checking for wchar.h... yes
checking for dirent.h that defines DIR... yes
checking for library containing opendir... none required
checking whether stat file-mode macros are broken... no
checking for working alloca.h... yes
checking for alloca... yes
checking whether closedir returns void... no
checking for stdlib.h... (cached) yes
checking for unistd.h... (cached) yes
checking for getpagesize... yes
checking for working mmap... yes
checking for btowc... yes
checking for isascii... yes
checking for iswctype... yes
checking for mbrlen... yes
checking for memmove... yes
checking for setmode... no
checking for strerror... yes
checking for wcrtomb... yes
checking for wcscoll... yes
checking for wctype... yes
checking whether mbrtowc and mbstate_t are properly declared... yes
checking for stdlib.h... (cached) yes
checking for mbstate_t... yes
checking for memchr... yes
checking for stpcpy... yes
checking for strtoul... yes
checking for atexit... yes
checking for fnmatch... yes
checking for stdlib.h... (cached) yes
checking whether  defines strtoumax as a macro... no
checking for strtoumax... yes
checking whether strtoul is declared... yes
checking whether strtoull is declared... yes
checking for strerror in -lcposix... no
checking for inline... inline
checking for off_t... yes
checking whether we are using the GNU C Library 2.1 or newer... yes
checking argz.h usability... yes
checking argz.h presence... yes
checking for argz.h... yes
checking limits.h usability... yes
checking limits.h presence... yes
checking for limits.h... yes
checking locale.h usability... yes
checking locale.h presence... yes
checking for locale.h... yes
checking nl_types.h usability... yes
checking nl_types.h presence... yes
checking for nl_types.h... yes
checking malloc.h usability... yes
checking malloc.h presence... yes
checking for malloc.h... yes
checking stddef.h usability... yes
checking stddef.h presence... yes
checking for stddef.h... yes
checking for stdlib.h... (cached) yes
checking for string.h... (cached) yes
checking for unistd.h... (cached) yes
checking for sys/param.h... (cached) yes
checking for feof_unlocked... yes
checking for fgets_unlocked... yes
checking for getcwd... yes
checking for getegid... yes
checking for geteuid... yes
checking for getgid... yes
checking for getuid... yes
checking for mempcpy... yes
checking for munmap... yes
checking for putenv... yes
checking for setenv... yes
checking for setlocale... yes
checking for stpcpy... (cached) yes
checking for strchr... yes
checking for strcasecmp... yes
checking for strdup... yes
checking for strtoul... (cached) yes
checking for tsearch... yes
checking for __argz_count... yes
checking for __argz_stringify... yes
checking for __argz_next... yes
checking for iconv... yes
checking for iconv declaration... 
         extern size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
checking for nl_langinfo and CODESET... yes
checking for LC_MESSAGES... yes
checking whether NLS is requested... yes
checking whether included gettext is requested... no
checking for libintl.h... (cached) yes
checking for GNU gettext in libc... yes
checking for dcgettext... yes
checking for msgfmt... /usr/bin/msgfmt
checking for gmsgfmt... /usr/bin/msgfmt
checking for xgettext... /usr/bin/xgettext
checking for bison... bison
checking version of bison... 2.3, ok
checking for catalogs to be installed...  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 ru rw sk sl sr sv tr uk vi zh_TW
checking for dos file convention... no
checking host system type... (cached) x86_64-unknown-linux-gnu
checking host system type... (cached) x86_64-unknown-linux-gnu
checking for DJGPP environment... no
checking for environ variable separator... :
checking for working re_compile_pattern... yes
checking for getopt_long... yes
configure: WARNING: Included lib/regex.c not used
checking whether strerror_r is declared... yes
checking for strerror_r... yes
checking whether strerror_r returns char *... no
checking for strerror... (cached) yes
checking for strerror_r... (cached) yes
checking for vprintf... yes
checking for doprnt... no
checking for ANSI C header files... (cached) yes
checking for working malloc... yes
checking for working realloc... yes
checking for pcre_exec in -lpcre... yes
configure: creating ./config.status
config.status: creating Makefile
config.status: creating lib/Makefile
config.status: creating lib/posix/Makefile
config.status: creating src/Makefile
config.status: creating tests/Makefile
config.status: creating po/Makefile.in
config.status: creating intl/Makefile
config.status: WARNING:  intl/Makefile.in seems to ignore the --datarootdir setting
config.status: creating doc/Makefile
config.status: creating m4/Makefile
config.status: creating vms/Makefile
config.status: creating bootstrap/Makefile
config.status: creating config.h
config.status: config.h is unchanged
config.status: executing depfiles commands
config.status: executing default-1 commands
config.status: creating po/POTFILES
config.status: creating po/Makefile
config.status: executing stamp-h commands

Спасибо, Кумар

Ответы [ 5 ]

10 голосов
/ 24 декабря 2009

Почему бы вам просто не получить SRPM от CentOS для двоичного файла grep и сравнить их параметры компиляции с вашими? Я предполагаю, что это гораздо эффективнее, чем когда все сообщество StackOverflow слепо копается в темноте, пока не наткнется на что-либо.

EDIT: вы используете локаль с многобайтовой кодировкой? (Примечание: если вы не знаете, что это значит, то ответ, вероятно, «Да», поскольку UTF-8 по умолчанию используется большинством дистрибутивов Linux уже несколько лет, и действительно RedHat (и, следовательно, CentOS) были первыми сделать переключатель).

В этом случае GNU grep будет медленным. И это относится не только к GNU grep, но и практически ко всем инструментам GNU, которые выполняют какую-то обработку текста. FSF отказывается принимать какие-либо исправления для улучшения многобайтовой производительности, если не доказано, что эти исправления не замедляют кодирование с фиксированной шириной. Однако, поскольку любой патч для повышения производительности для многобайтовых кодировок должен , по крайней мере, содержать где-нибудь оператор if, на самом деле невозможно написать патч, который по крайней мере не замедляет фиксированный кодирование по крайней мере на издержки этого оператора if. Таким образом, производительность UTF-8 инструментов GNU будет продолжать отстой до конца времени.

В любом случае, большинство дистрибьюторов Linux не дают крысам бип , что думает FSF, и все равно исправляют GNU grep. Fedora Rawhide SRPM содержит патч grep-2.5.3-egf-speedup.patch, который ускоряет работу GNU grep на UTF-8 на несколько порядков. (Поскольку этот патч уже выпущен в 2005 году, я предполагаю, что он также используется в CentOS.) Этот патч также используется в Mac OSX, Debian, Ubuntu, ..., почти никто не использует GNU grep, распространяемый GNU. Обработка текста в многобайтовой кодировке никогда не будет такой быстрой, как в кодировке с фиксированной шириной, но она должна быть, по крайней мере, сопоставимой, а не в 50 раз (или даже в 1500 раз, как сообщали некоторые люди) медленнее.

Есть также еще один патч под названием dfa-optional, который заставляет grep просто использовать движок регулярных выражений GNU libc вместо своего собственного, который не только на намного быстрее при работе с UTF-8 но также имеет гораздо меньше ошибок.

Итак, вы можете перезапустить тесты с установленным export LC_ALL=POSIX. Если это решит вашу проблему, вам нужно применить один из двух вышеупомянутых патчей.

Дополнительная информация также доступна в этих двух отчетах об ошибках RedHat:

Мораль этой истории: несмотря на распространенное мнение, дистрибьюторы Linux do знают, что они делают, по крайней мере иногда. Не угадывайте их.

4 голосов
/ 24 декабря 2009

Вы скомпилировали с флагом -O2. Почему вы не использовали флаг -03. См. здесь для объяснения параметров оптимизации, доступных с gcc.

Использование компилятора Intel ICC также может помочь повысить производительность, хотя это действительно зависит от приложения. Кроме того, это не бесплатно.

Edit, я только что увидел флаг -g на вашей строке компиляции. Удалите это, так как он включает отладочную информацию, и это может вызвать довольно серьезное снижение производительности

1 голос
/ 24 декабря 2009

Какую версию GCC вы используете? IIRC, GCC 4 был значительно переработан, что на некоторое время лишило законной силы часть кода оптимизации.

1 голос
/ 24 декабря 2009

Еще одна мысль, которую стоит отметить, кроме опций -O, похоже, что вы строите с отладочными символами "-g".

Отладка обычно увеличивает размер бинарного файла и может снизить производительность указанного бинарного файла, я бы сказал, что образ grep довольно стабилен, и вам не нужны для этого символы отладки.

0 голосов
/ 24 декабря 2009

При таком большом разрыве в производительности это, вероятно, разница в алгоритме / коде, а не просто разница в уровне оптимизации компилятора. Что заставляет вас подозревать компилятор?

...