Чем быстрее всего отрезать строку в кодировке UTF-8

Решил протестировать — чем быстрее всего можно отрезать строку в кодировке UTF-8. В PHP для этой цели (помимо использования извращений, типа SQL-запроса) можно использовать: mb_substr из модуля «Multibyte string function», iconv_substr из модуля iconv, preg_replace в режиме UTF-8 из Perl-Compatible regular expression function и собственную реализацию прохода по UTF-8 строке.

Я взял строку в 700 UTF-8-символов и отрезал от неё 500 разными функциями. Вот что получилось (PHP 5.2.4 без акселераторов):

  • хуже всех справилась реализация на чистом PHP — 0.34 сек
  • получше — iconv_substr. 0.063 сек
  • ещё лучше — mb_substr. 0.0175 сек
  • лучше всех — preg_replace. 0.005 сек
    Если кому интересно, вот моя функция по проходу по строке в кодировке UTF-8:
$len = strlen($text);
    for ($pos = $cutted = 0; $cutted < $cut && $pos < $len; ++$cutted)
    {
            $ch = ord($text[$pos]);

            // multibyte char
            if (0x80 & $ch)
            {
                    for (; $ch & 0x80; ++$pos, $ch <<= 1);
            }
            else
            {
                    $pos++;
            }
    }

Итак, лучший способ отрезать первые $N символов UTF-8 таков:

preg_replace('/^(.{'.$N.'}).*$/uSs', '$1', $text)
Поделиться
Отправить
17 комментариев
Alisey (alisey.myopenid.com)

Евгений, а вот такие эксперименты, кроме того что это забавно и разница действительно огромна, имеют ли они ещё какой-то смысл для вас?
Мне кажется такие вещи вредно включать в долговременную память. Позиции могут измениться с любой новой версией языка или библиотек.

Хотел показать, только что на hackety.org натолкнулся, аналог NodeBox на Lua. I thought you might like.
http://www.4p8.com/lew/gallery.html

Евгений Степанищев (bolknote.ru)

Комментарий для alisey.myopenid.com:

Для меня это текущая задача — в моём движке есть функция отрезания текста, используется она часто, я, было, сделал ветвление, в зависимости от библиотеки, которая есть, а, оказывается, это не требуется — всех делает regexp.

zencd.livejournal.com

Может имеет смысл подпатчить iconv_substr? (не локально, в рамках развития проекта). Всё-таки разница в 10 раз ...

И написать тестик (в рамках пхп-девелопмента же), чтобы сравнивать две реализации и если вдруг регекспы затормозят — выдать предупреждение.

zencd.livejournal.com

Комментарий для Евгения Степанищева:

A bug report: комментарии не отдаются по рсс. Глянь например мой поток — там ошибки в пхп: http://bolknote.ru/rss/zencd.livejournal.com

А вообще комментарии по рсс это сила. Жаль всех на эту технологию на пересадишь :). Да и преобразователь уведомлений-по-емейлу в уведомления-по-рсс (для единства) непонятно как реализовать.

Евгений Степанищев (bolknote.ru)

Комментарий для zencd.livejournal.com:

RSS починил. Реализовать просто — робот получает e-mail, формирует RSS.

zencd.livejournal.com

Комментарий для Евгения Степанищева:

Оффтоп эгейн: я смотрю тег <title></title> пустой — предлагаю писать туда название статьи (если есть) — в рсс-ридере (мне) было бы удобнее понимать к какой статье комментарий относится. Впрочем, не настаиваю.

Евгений Степанищев (bolknote.ru)

Комментарий для zencd.livejournal.com:

Я вот долго думал — что туда писать, пожалуй, можно и название статьи, да. Спасибо за идею!

razetdinov (razetdinov.ya.ru)

Комментарий для zencd.livejournal.com:

http://razetdinov.ya.ru/replies.xml?item_no=104
Искал, ничего толкого не нашёл. В итоге создал ящик на гмыле и подписался по imap.

zencd.livejournal.com

Комментарий для razetdinov.ya.ru:

OMG! Gmail умеет отдавать RSS? Это гениально. Добавил запароленный feed в Google Reader, помотрим что получится. (А получается пока что простейший pipe!)

razetdinov (razetdinov.ya.ru)

Комментарий для zencd.livejournal.com:

Уже пробовал, в гмэйловом RSS не отдаются тела сообщений :-(

zencd.livejournal.com

Комментарий для razetdinov.ya.ru:

значит нужно просто найти другого емейл-провайдера
всё равно нам туда не заходить при новом раскладе :)

razetdinov (razetdinov.ya.ru)

Комментарий для zencd.livejournal.com:

Я использую gmail-аккаунт исключительно для рассылок, читаю через imap, благо, Опера позволяет читать почту в одной ленте с рассылками. Но даже imap у гугла работает криво: http://razetdinov.ya.ru/replies.xml?item_no=178 Поэтому, если найдёшь лучше, свисти)

rin-nas.moikrug.ru

Кол-во повторений в фигурных скобках {} в рег. выражениях имеет ограничение (65535 ?). Попробуйте отрезать 100000 символов :)

Мою реализацию utf8_substr() смотрите здесь:
http://forum.dklab.ru/viewtopic.php?t=17146

P.S.
Ввод несуществующего имени для OpenID получает PHP wanring и notice на странице.

rin-nas.moikrug.ru

К сожалению, циклы в PHP тормозные в отличие, например, от C# и Python.
Где-то в интернете приводились тесты по этой теме.

Евгений Степанищев (bolknote.ru)

Комментарий для rin-nas.moikrug.ru:

У меня задачи собственные, мне столько резать не надо :)

Warning: preg_replace(): Compilation failed: number too big in {} quantifier at offset 9 in /root/- on line 6

Но буду иметь ввиду, спасибо, я об этом не знал. Значит вариант такой — проверяем длину, далее — в зависимости от.

Григорий fliber.net

Взять первые 200 символов
preg_replace(’/^(.{200}).*/us’, ’\1’, $txt);

Евгений Степанищев (bolknote.ru)

Комментарий для Григорий fliber.net:

Ну и? Вы статью не читали что ли?

Популярное