2009-12-23 10 views
7

Estoy tratando de entender por qué grep creado por mí es mucho más lento que el que viene con el sistema y tratando de encontrar las opciones de compilación usadas por grep que viene con el sistema.grep desarrollado más lento que grep que viene con Linux

OS Versión: CentOS versión 5.3 (final) grep en el sistema:

 
    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 construido por mí:

 
    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) 

El rendimiento de grep sistema (330 milisegundos) es mucho más rápido que grep que construí (22430 msecs) cuando ejecuté una búsqueda de expresiones regulares en un archivo de texto de lista grande.

A continuación se presenta el comando Solía ​​tiempo ..

 
% time src/grep ".*asa.*" large_list.txt > /dev/null 
real 0m22.430s 
user 0m22.291s 
sys 0m0.080s 

O

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

El sistema está usando grep claramente algunas opciones optiomizing que está dando gran diferencia de rendimiento.

¿Puede algún organismo ayudarme con las opciones con las que se puede compilar el sistema grep?

Aquí es las opciones de compilación para uno de los archivos de origen cuando construyo ..
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

La salida de ./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 

Gracias, Kumar

Respuesta

4

Usted compilado con la bandera -O2. ¿Por qué no usaste la bandera -03? Consulte here para obtener una explicación de las opciones de optimización disponibles con gcc.

El uso del compilador ICC de Intel también puede ayudar a mejorar el rendimiento, aunque esto realmente depende de la aplicación. Además, no es gratis.

Editar, acabo de ver el distintivo -g en su línea de compilación. Quite eso ya que está activando cosas de depuración y esto puede causar un rendimiento bastante serio.

+1

tienen casi el mismo tiempo con el O3 .. reales \t 0m22.271s usuario \t 0m22.163s sys \t 0m0.079s El tamaño del grep con -O3 es 344944 bytes – kumar

0

Con una brecha de rendimiento tan grande, probablemente sea una diferencia de algoritmo/código, no solo una diferencia en el nivel de optimización del compilador. ¿Qué te hace sospechar del compilador?

+0

me dieron el código grep de GNU (2.5.4) y no debería haber ningún cambio importante en el código cuando se compara con el 2.5.1 que tiene el sistema. No estoy usando ninguno de mis códigos para ejecutar esta prueba. – kumar

+0

Oh, lo tengo. Entendí mal. –

1

Otro aspecto a destacar además de las opciones -O es que parece que está construyendo con símbolos de depuración "-g".

La depuración generalmente aumenta el tamaño del binario y puede reducir el rendimiento de dicho archivo binario, yo la imagen grep es bastante estable y realmente no necesita símbolos de depuración para ello.

+0

Quitar -g definitivamente redujo el tamaño a 101733 (con -O2), pero el tiempo sigue siendo el mismo .. real \t 0m22.358s usuario \t 0m22.231s sys \t 0m0.093s – kumar

10

¿Por qué no acaba de obtener el SRPM de CentOS para el binario grep y compara sus opciones de compilación con las suyas? Supongo que esto es mucho más eficiente que tener toda la comunidad de StackOverflow moviéndose ciegamente en la oscuridad hasta que golpeen algo.

EDITAR: ¿Está utilizando una configuración regional con una codificación multibyte?(Nota: si no tiene idea de lo que eso significa, entonces la respuesta es probablemente "Sí", ya que UTF-8 ha sido el predeterminado para la mayoría de las distribuciones de Linux desde hace varios años y, de hecho, RedHat (y por lo tanto CentOS) fueron los primeros en hacer el cambio).

En ese caso, GNU grep es perro lento. Y esto no solo se aplica a GNU grep, sino a casi todas las herramientas de GNU que hacen algún tipo de procesamiento de texto. La FSF se niega a aceptar cualquier parche para mejorar el rendimiento de multibyte, a menos que se haya demostrado que esos parches no ralentizan las codificaciones de ancho fijo. Sin embargo, desde cualquier parche para mejorar el rendimiento para codificaciones multibyte debe al menos contiene alguna declaración if en alguna parte, en realidad es imposible escribir un parche que no al menos reduzca la velocidad de codificaciones de ancho fijo al menos la sobrecarga de ese if declaración. Por lo tanto, el rendimiento de UTF-8 de las herramientas de GNU será y seguirá chupando hasta el final de los tiempos.

De todos modos, la mayoría de los distribuidores de Linux no dan una rata de bleep lo que piensa la FSF y parche GNU grep de todos modos. El Fedora Rawhide SRPM contiene un parche llamado grep-2.5.3-egf-speedup.patch, que acelera el rendimiento UTF-8 del grep de GNU en varios órdenes de magnitud. (Como este parche ya es de 2005, asumo que también se usa en CentOS). Este parche también se usa en Mac OSX, Debian, Ubuntu, ..., casi nadie usa GNU grep distribuido por GNU. El procesamiento de texto en una codificación multibyte nunca será tan rápido como en una codificación de ancho fijo, pero al menos debe ser comparable, no 50x (o incluso 1500x como algunas personas han informado) más lento.

También hay otro parche llamado dfa-optional, lo que hace que sólo tiene que utilizar grep motor de expresiones regulares de GNU libc en lugar de su propia, que no sólo es mucho más rápido cuando se trata de UTF-8, pero también tiene muchos menos errores.

Por lo tanto, es posible que desee volver a ejecutar sus puntos de referencia con el conjunto export LC_ALL=POSIX. Si eso soluciona su problema, debe aplicar cualquiera de los dos parches mencionados anteriormente.

Más información también está disponible en estos informes de error de dos RedHat:

La moraleja de la historia: a pesar de la creencia popular, los distribuidores de Linux hacen saben lo lo están haciendo, al menos algunas veces. No los adivines.

+0

Gracias por la excelente sugerencia. Traté de construir desde el srpm, pero el rendimiento aún es lento en comparación con el binario grep en el sistema o en las rpm. Tal vez debe ser construido en un entorno específico para obtener las configuraciones correctas? He publicado la pregunta en uno de los foros de te centos. Veo el mismo comportamiento en otros sabores de Linux también. – kumar

1

¿Qué versión de GCC estás utilizando? IIRC, GCC 4 se rediseñó significativamente, lo que invalidó parte del código de optimización por un tiempo.

Cuestiones relacionadas