Почему uncompiled, многократно использовались регулярные выражения, намного медленнее в Python 3?

Отвечая на этот вопрос (и прочитав этот ответ на аналогичный вопрос), я подумал, что знаю, как Python кэширует регулярные выражения.

Но потом я подумал, что проверю это, сравнив два сценария:

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

Однако результаты были ошеломляющими (в Python 3.3):

>>> import timeit >>> timeit.timeit(setup="import re", ... stmt='r=re.compile(r"\w+")\nfor i in range(10):\n r.search(" jkdhf ")') 18.547793477671938 >>> timeit.timeit(setup="import re", ... stmt='for i in range(10):\n re.search(r"\w+"," jkdhf ")') 106.47892003890324 

Это более чем в 5,7 раза медленнее! В Python 2.7 все еще наблюдается увеличение в 2,5 раза, что также больше, чем я ожидал.

Изменено ли кэширование регулярных выражений между Python 2 и 3? Документы , похоже, не предлагают этого.

One Solution collect form web for “Почему uncompiled, многократно использовались регулярные выражения, намного медленнее в Python 3?”

Код изменился.

В Python 2.7 кеш – простой словарь; если в нем хранится больше элементов _MAXCACHE , весь кеш очищается перед сохранением нового элемента. _compile() кэше требует только создания простого ключа и тестирования словаря, см. 2.7 реализацию _compile()

В Python 3.x кеш был заменен декоратором @functools.lru_cache(maxsize=500, typed=True) . Этот декоратор выполняет гораздо большую работу и включает в себя блокировку потока, настройку очереди LRU кэша и сохранение статистики кеша (доступной через re._compile.cache_info() ). См. 3.3 реализацию _compile() и functools.lru_cache() .

Другие заметили такое же замедление, и подали проблему 16389 в Pugon bugtracker . Я ожидаю, что 3.4 будет намного быстрее; либо реализация lru_cache улучшена, либо модуль re снова переместится в пользовательский кеш.

Обновление: с исправлением 4b4dddd670d0 изменение кэша вернулось к простой версии, указанной в 3.1. Версия Python 3.2.4 и 3.3.1 включает эту ревизию.

  • Выбор элементов в массиве numpy с использованием регулярных выражений
  • Соответствие регулярных выражений между двумя строками?
  • pandas находит строки среди рядов и возвращают ключевые слова
  • использование regex в jinja 2 для прослушиваемых книг
  • Разделение разделенных запятыми строк в python
  • Анализ IP-адреса / сети из текстового файла с использованием python
  • Получить корневую область связи
  • python - проблемы с регулярным выражением и unicode
  • Python - лучший язык программирования в мире.