Почему 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 включает эту ревизию.

Interesting Posts

Как сделать поле условно опциональным в WTForms?

Как отображать объекты InLine в интерфейсе администратора Django

Запрос фильтра Django – не работает

Parsing json object отправлен с использованием метода Ajax GET в Django

scikit изучает создание фиктивных переменных

Как отсортировать похожие значения в отсортированном списке (на основе второго значения) кортежей на основе другого значения (третьего значения) в кортеже в порядке убывания

Как объединить столбец datetime в ближайший квартал

Maya Python API 2.0 не имеет MItDag, так как график прохождения DAG?

Python: bytearray vs array

Локальная переменная, на которую ссылаются перед назначением

Используйте Python для выбора строк с определенным диапазоном значений в одном столбце

Pandas Column математические операции Нет ошибки нет ответа

Реверсивные биты целого числа Python

В Python командной строки args без импорта?

Длина строки в Jinja / Flask

Python - лучший язык программирования в мире.