Тому я пішов до джерела, і схоже, що повільність у роботі з двобайтовими символами. По суті, для кожного прочитаного символу потрібно зателефонувати, 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-продуктивність-виграш /