Очистка кэша модуля Python re

при чтении документации на Python re модуль я решил посмотреть на re.py исходный код.

когда я открыл его, я нашел это:

_cache = {}
_MAXCACHE = 100

def _compile(*key):
    cachekey = (type(key[0]),) + key
    p = _cache.get(cachekey)
    if p is not None:
        return p

    #...Here I skip some part of irrelevant to the question code...

    if len(_cache) >= _MAXCACHE:
        _cache.clear()
    _cache[cachekey] = p
    return p

почему кэш очищается с помощью_cache.clear() когда он достигает _MAXCACHE записей?

это общий подход, чтобы очистить кэш полностью и начать с нуля?

почему просто не используется самое долгое время назад обналиченное значение удаляется?

3 ответов


если бы мне пришлось угадать, я бы сказал, что это было сделано таким образом, чтобы избежать необходимости отслеживать, когда / как долго отдельные значения хранились в кэше, что создало бы как память, так и обработку накладных расходов. Поскольку используемый объект кэширования является словарем, который по своей сути неупорядочен, нет хорошего способа узнать, какие элементы порядка были добавлены к нему без какого-либо другого объекта кэширования. Это можно решить с помощью OrderedDict вместо стандартного словаря, предполагая, что вы работаете с Python >= 2.7, но в противном случае вам нужно будет значительно изменить способ кэширования, чтобы устранить необходимость в clear().


вот цитата от одного из разработчиков нового regex модуль, запланированный на 3.3 что касается кэширования, это часть списка функций, которые отделяют новый модуль от текущего re модуль.

7) измените повторно скомпилированный кэш выражений, чтобы лучше обрабатывать состояние трепки. В настоящее время при компиляции регулярных выражений, результат кэшируется так, что если то же выражение компилируется снова, он извлекается из кэша и нет нужно проделать дополнительную работу. Этот кэш поддерживает до 100 записей. Как только 100-я запись будет достигнута, кэш очищается, и должна произойти новая компиляция. Опасность, всем быть редко, что можно скомпилировать 100-е выражение только для того, чтобы найти это перекомпилирует его и делать ту же работу снова и снова, когда он может было сделано 3 выражения назад. В слегка измененном виде это логика, это можно установить произвольный счетчик, который дает отметку времени каждая составлена запись и вместо того, чтобы очистить весь кэш, когда он достигает емкости, только исключает самую старую половину кэша, держа та половина, что более свежая. Это должно ограничить возможность thrashing к случаям, когда очень большое количество регулярных выражений постоянно перекомпилируется. В дополнение к этому, я обновлю лимит до 256 записей, что означает, что 128 последних сохраняются.

http://bugs.python.org/issue2636

этот кажется, указывает на то, что это, скорее всего, лень разработчика или "акцент на читаемость", который объясняет текущее поведение кэширования.


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

есть несколько вещей, чтобы подумайте о При расчете эффективности кэша:

  1. среднее время вызова на кэш-хитах (очень короткое)
  2. среднее время вызова на промахи кэша (больше)
  3. частота попадания в кэш (довольно редко)
  4. время вызова, когда кэш очищается или обрезается (довольно редко)

вопрос в том, имеет ли смысл увеличение #3, Если это означает увеличение #2 и #4. Я думаю, что это не так, или разница настолько незначительна что предпочтительнее сохранять код простым.