Чем быстрее всего отрезать строку в кодировке 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)
Евгений, а вот такие эксперименты, кроме того что это забавно и разница действительно огромна, имеют ли они ещё какой-то смысл для вас?
Мне кажется такие вещи вредно включать в долговременную память. Позиции могут измениться с любой новой версией языка или библиотек.
Хотел показать, только что на hackety.org натолкнулся, аналог NodeBox на Lua. I thought you might like.
http://www.4p8.com/lew/gallery.html
Комментарий для alisey.myopenid.com:
Для меня это текущая задача — в моём движке есть функция отрезания текста, используется она часто, я, было, сделал ветвление, в зависимости от библиотеки, которая есть, а, оказывается, это не требуется — всех делает regexp.
Может имеет смысл подпатчить iconv_substr? (не локально, в рамках развития проекта). Всё-таки разница в 10 раз ...
И написать тестик (в рамках пхп-девелопмента же), чтобы сравнивать две реализации и если вдруг регекспы затормозят — выдать предупреждение.
Комментарий для Евгения Степанищева:
A bug report: комментарии не отдаются по рсс. Глянь например мой поток — там ошибки в пхп: http://bolknote.ru/rss/zencd.livejournal.com
А вообще комментарии по рсс это сила. Жаль всех на эту технологию на пересадишь :). Да и преобразователь уведомлений-по-емейлу в уведомления-по-рсс (для единства) непонятно как реализовать.
Комментарий для zencd.livejournal.com:
RSS починил. Реализовать просто — робот получает e-mail, формирует RSS.
Комментарий для Евгения Степанищева:
Оффтоп эгейн: я смотрю тег <title></title> пустой — предлагаю писать туда название статьи (если есть) — в рсс-ридере (мне) было бы удобнее понимать к какой статье комментарий относится. Впрочем, не настаиваю.
Комментарий для zencd.livejournal.com:
Я вот долго думал — что туда писать, пожалуй, можно и название статьи, да. Спасибо за идею!
Комментарий для zencd.livejournal.com:
http://razetdinov.ya.ru/replies.xml?item_no=104
Искал, ничего толкого не нашёл. В итоге создал ящик на гмыле и подписался по imap.
Комментарий для razetdinov.ya.ru:
OMG! Gmail умеет отдавать RSS? Это гениально. Добавил запароленный feed в Google Reader, помотрим что получится. (А получается пока что простейший pipe!)
Комментарий для zencd.livejournal.com:
Уже пробовал, в гмэйловом RSS не отдаются тела сообщений :-(
Комментарий для razetdinov.ya.ru:
значит нужно просто найти другого емейл-провайдера
всё равно нам туда не заходить при новом раскладе :)
Комментарий для zencd.livejournal.com:
Я использую gmail-аккаунт исключительно для рассылок, читаю через imap, благо, Опера позволяет читать почту в одной ленте с рассылками. Но даже imap у гугла работает криво: http://razetdinov.ya.ru/replies.xml?item_no=178 Поэтому, если найдёшь лучше, свисти)
Кол-во повторений в фигурных скобках {} в рег. выражениях имеет ограничение (65535 ?). Попробуйте отрезать 100000 символов :)
Мою реализацию utf8_substr() смотрите здесь:
http://forum.dklab.ru/viewtopic.php?t=17146
P.S.
Ввод несуществующего имени для OpenID получает PHP wanring и notice на странице.
К сожалению, циклы в PHP тормозные в отличие, например, от C# и Python.
Где-то в интернете приводились тесты по этой теме.
Комментарий для rin-nas.moikrug.ru:
У меня задачи собственные, мне столько резать не надо :)
Warning: preg_replace(): Compilation failed: number too big in {} quantifier at offset 9 in /root/- on line 6
Но буду иметь ввиду, спасибо, я об этом не знал. Значит вариант такой — проверяем длину, далее — в зависимости от.
Взять первые 200 символов
preg_replace(’/^(.{200}).*/us’, ’\1’, $txt);
Комментарий для Григорий fliber.net:
Ну и? Вы статью не читали что ли?