Así que fui a la fuente, y parece que la lentitud está en el manejo de caracteres de doble byte. Esencialmente, para cada carácter leído, debe llamar mbrtowc()
para intentar convertirlo en un carácter ancho, luego se prueba ese carácter ancho para ver si es un separador de palabras, un separador de línea, etc.
De hecho, si cambio mi LANG
variable de configuración regional por defecto en_US.UTF-8
(UTF-8 es un conjunto de caracteres multibyte) y lo configuro en " C
" (conjunto de caracteres de un solo byte simple), wc
puedo usar optimizaciones de un solo byte, lo que lo acelera considerablemente, tomando solo alrededor de un cuarto del tiempo que antes.
Además, solo tiene que verificar cada carácter si está haciendo recuentos de palabras ( -w
), longitud de línea ( -L
) o caracteres ( -m
). Si solo está haciendo recuentos de bytes y / o líneas, puede omitir el manejo de caracteres anchos y luego se ejecuta extremadamente rápido, más rápido que md5sum
.
Lo pasé por gprof
, y las funciones que se utilizan para manejar los caracteres de varios bytes ( mymbsinit()
, mymbrtowc()
, myiswprint()
, etc.) están ocupando aproximadamente el 30% del tiempo de ejecución solo, y el código que los pasos a través de la memoria intermedia es mucho más compleja porque tiene que maneja pasos de tamaño variable a través del búfer para caracteres de tamaño variable, así como rellena los caracteres parcialmente completados que abarcan el búfer de regreso al comienzo del búfer para que pueda manejarse la próxima vez.
Ahora que sé qué buscar, encontré algunas publicaciones que mencionan la lentitud utf-8 con algunas utilidades:
/programming/13913014/grepping-a-huge-file-80gb-any-way-to-speed-it-up
http://dtrace.org/blogs/brendan/2011/12/08 / 2000x-performance-win /