UTF-8: как быстрее измерить длину строки в PHP
Я потихоньку буду писать как получается оптимизировать самые важные функции работы
Сейчас, после перевода «Вики» мы столкнулись с тем, что некоторые операции занимают непозволительно много времени.
Простые оптимизации я уже применил: выкинул из класса
Одна из самых частоиспользуемых функций — strlen, которая определяет длину строки. Я всегда считал, что самый быстрый способ подсчитать длину
Мои тесты показывают что это не так. Самый быстрый способ (по крайней мере в PHP 5.3.2) — это mb_strlen, strlen/utf8_decode — на втором месте, потом идёт sizeof+preg_split, а самый медленный — iconv_strlen.
Для интереса я вкомпилил в PHP функцию для быстрого подсчёта длины строки
bolk-dev ~/uni/ $ php ../test/test_strlen.php | sort -k2 -t:
Fast UTF-8: 0.68232107162476
mb_strlen: 0.88710689544678
strlen/utf8_decode: 1.5211808681488Это тысяча итераций на файле в 400КБ.
Я оставил функцию mb_strlen.
Добавлено позднее: другая быстрая функция дала ещё худший результат: 0,79, против прежнего варианта в 0,68.
Добавлено ещё позже: а вот третья функция показала действительно впечатляющие результаты:
bolk-dev ~/uni/ $ php ../test/test_strlen.php | sort -k2 -t:
More Fast UTF-8: 0.12948799133301
mb_strlen: 0.88710689544678
strlen/utf8_decode: 1.5211808681488Это уже дело — она почти в 7 раз быстрее лучшего результата PHP.
Вкратце, алгоритм такой: строка циклом выравнивается по границе четырёх
Добавлено через несколько дней: есть и ещё более быстрая функция.
Комментарии 16
интерес академический.
PHP — это универсальное решение, mbstring использует libmbfl, которая так же универсальное решение.
Если вам нужно работать только с UTF8, то написать экстеншен на С для работы только с UTF8 — это довольно небольшая задача. А если у вас действительно много работы со строками, то вынос этой задачи в спец. экстеншен — это логичный (и единственно верный!=)) выход.
по ссылке на третью функцию прекрасное:
ой. 8)
а на 3х мегабайтах?
Вот так выглядит:
mb_strlen: 6.9003229141235
strlen/utf8_decode: 12.082993984222
More Fast
Для PHP 5.2.x strlen/utf8_decode было быстрее, чем mb_strlen.
Сделаю у себя тесты, при необходимости внесу правки.
http://code.google.com/p/php5-utf8/source/list
function utf8len($x){preg_match_all('/./iu', $x, $a);return count($a[0]);}
А как вам этот вариант?