LINUX.ORG.RU

Странная скорость str_replace и preg_replace в php


0

1

Из таблицы в 2М записей выгребается по 10К и на них натравливается str_replace и preg_replace. Естественно, не построчно, а на массив.

Получается странная фигня. str_replace по 20 паттернам работает 50-100 секунд. preg_replace по общей свертке - 10 секунд.

Почему так?

★★★★★

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

Deleted
()

str_replace() обрабатывает массив последовательно, а не параллельно. Т.е. если в массиве поиска 20 элементов, текст будет просмотрен 20 раз.

prge_replace() строит конечный автомат, и если для поиска/замены достаточно одного регулярного выражения (если я правильно понял), то будет сделан всего лишь один просмотр текста (плюс-минус с учётом жадности и backtracking).

sjinks ★★★
()
Ответ на: комментарий от sjinks

Это все понятно. И паттерн preg_replace оптимизирован, чтобы с константы начинался.

Просто принято считать («английские ученые доказали»), что регулярки НАМНОГО медленнее строковых функций. А у меня получилось, что скорость такая же. А если сравнивать с str_ireplace, то еще и повыше.

Vit ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Сегодня-завтра код в репе публичном будет. Пока малость не дочищен для коммита.

Vit ★★★★★
() автор топика
Ответ на: комментарий от sjinks

>Т.е. если в массиве поиска 20 элементов, текст будет просмотрен 20 раз.

нет, не в этом дело.

глянул в исходники... простой вызов str_replace уводит стек вызова вглубь по циклу ажно на 3-4 раза. брррррр. вникать сильно не стал, но не удивлен тормознутостью этой функции.

вызов prge_replace делает ровно то же самое (последние пара вызовов в стеке ровно те же, что и в str_replace), но глубина вызова при этом на 1-2 вызова меньше.

таким образом скорость работы последней будет быстрее до SQRT(T(f)) раз.

Deleted
()
Ответ на: комментарий от Vit

я смотрел именно исходники php. не знаю как в других местах реализовано.

и кстати, регексповая функция юзает pcre только для разбора шаблона. замена строки идет одной и той же функцией, что и для str_replace.

Deleted
()
Ответ на: комментарий от Vit

если так интересно, можешь сам детально посмотреть исходники. я очень бегло глянул. не вникал особливо в алгоритмические тонкости поиска вхождения.

Deleted
()
Ответ на: комментарий от Deleted

Честно говоря, я не любитель в сорцах ковыряться. У меня чисто практическая задача: отпарсить 2 гига постов в XML для сфинкса.

Теперь вот гоняем бенчмарки, удивляемся, что тормоза совсем не там где ждали.

Vit ★★★★★
() автор топика
Ответ на: комментарий от Vit

>отпарсить 2 гига постов в XML

ну так первое, что нужно было сделать перед написанием тулзы сделать бенчмаркинг самого главного функционала на разных языках :). хотя я не знаю конкретных условий и ограничений для решения этой задачи, чтобы сделать правильные выводы.

а простой перловый регексп с этой задачей быстрее или медленнее справляется?

Deleted
()
Ответ на: комментарий от Deleted

Не хотелось бы в исследования ради исследований впадать. А грубую оценку можно и на глаз построить. Все-таки есть конкретная задача, которая решена с минимумом усилий и приемлимым результатом. Индексирование с прямой выборкой из базы занимает около 10 минут. А через XML будет на 5 минут дольше. Вполне соразмерно.

Кому интересно, конвертор очень скоро появится тут: https://github.com/rcdesign/vb-sphinx_search

Если есть какие-то готовые бенчмарки, что в пыхе тормозят массивы и т.п. - буду признателен за ссылки.


Vit ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Спасибо. Очень интересно. Сейчас заюзаем.

Vit ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Разница в том, что для preg_replace все позиции для замены известы заранее — об этом заботится pcre_exec(3); в этом случае замена тривиальна; для замены НЕ вызываются функции из ext/standard/string.c (в ext/pcre есть своя статическая функция с похожим названием).

Если же посмотреть на php_str_replace_in_subject() в ext/standard/string.c (фактически это и есть реализация str_replace()), она проходит по всему массиву $search и для каждого его элементы вызывает php_str_to_str_ex(), которая каждый раз просматривает строку заново.

sjinks ★★★
()
Ответ на: комментарий от sjinks

>в ext/pcre есть своя статическая функция с похожим названием

хмм, не обратил внимание видать.

Deleted
()
Ответ на: комментарий от Deleted

Вона, сорец, если кому еще интересно

https://github.com/rcdesign/vb-sphinx_search/tree/master/system_upload/usr/lo...

Через mysql_nd делать выборки не стали, потому что в пыхе по дефолту нет, а компилить лень. Еще пытались пошаманить с генерацией XML, но там уже тоже ловить нечего.

Субъективно замедление на 2 миллионах постов не очень большое. Ну может 7 минут вместо 5 бегает - ерунда ведь.

Полноценные бенчмарки строить влом. Но и так видно - зря Аксенов пугал народ, что очистка регекспами капитально убивает скорость.

Vit ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.