Итак, я пошел к источнику, и похоже, что медлительность заключается в обработке двухбайтовых символов. По сути, для каждого прочитанного символа необходимо вызвать его, mbrtowc()
чтобы попытаться преобразовать его в широкий символ, затем этот широкий символ проверяется, чтобы определить, является ли он разделителем слов, разделителем строк и т. Д.
Действительно, если я изменю свою LANG
переменную локали по умолчанию en_US.UTF-8
(UTF-8 является многобайтовым набором символов) и установлю ее на " C
" (простой однобайтовый набор символов), wc
она сможет использовать однобайтовую оптимизацию, что значительно ускоряет ее, займет всего около четверти, как и раньше.
Кроме того, он должен только проверять каждый символ, если он выполняет подсчет слов ( -w
), длины строки ( -L
) или символа ( -m
). Если он выполняет только подсчет байтов и / или строк, он может пропустить обработку широких символов, а затем он работает очень быстро - быстрее, чем md5sum
.
Я побежал через gprof
, и функции, которые используются для обработки символов мультибайтные ( mymbsinit()
, mymbrtowc()
, myiswprint()
, и т.д.) занимают около 30% только во время выполнения, а также код , который шаги через буфер является гораздо более сложным , поскольку он должен обрабатывать шаги переменного размера через буфер для символов переменного размера, а также вставлять любые частично завершенные символы, которые охватывают буфер, обратно в начало буфера, чтобы его можно было обработать в следующий раз.
Теперь, когда я знаю, что искать, я нашел несколько постов, в которых упоминается медлительность utf-8 с некоторыми утилитами:
/programming/13913014/grepping-a-huge-file-80gb-any-way-to-speed-it-up
http://dtrace.org/blogs/brendan/2011/12/08 / 2000x эффективность выигрыша /