Мемоизация

Оригинальное название: memoization

Коротко

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

Что такое «Мемоизация»

Название происходит от английского memo — «памятка». Идею описал британский исследователь Дональд Мичи в 1968 году. Если функция вызывается много раз с одними и теми же данными, а считает долго, проще один раз записать ответ и дальше брать его из записи. Платить приходится памятью: таблица результатов растёт с каждым новым набором аргументов.

Условие: чистая функция

Мемоизировать можно только функцию, результат которой зависит исключительно от аргументов и которая ничего не меняет вокруг себя. Сумма двух чисел, расчёт доставки по весу и тарифу, разбор строки — подходят. Функция, которая читает текущее время, остатки со склада или курс валют, — нет: при тех же аргументах она должна возвращать новые данные, а мемоизация вернёт старые.

Пример на PHP

Классический случай — числа Фибоначчи. Наивная рекурсия пересчитывает одни и те же значения экспоненциальное число раз. Статический массив внутри функции живёт между вызовами и служит памяткой:

function fib(int $n): int
{
    static $memo = [0 => 0, 1 => 1];

    if (!isset($memo[$n])) {
        $memo[$n] = fib($n - 1) + fib($n - 2);
    }
    return $memo[$n];
}

echo fib(80); // 23416728348467685

С памяткой каждое значение считается один раз, и ответ приходит мгновенно. Без неё вызов fib(80) не завершится за разумное время. В JavaScript-интерфейсах похожую задачу решают useMemo в React и вычисляемые свойства во Vue.

Мемоизация, кеш и transient — в чём разница

Мемоизация — частный случай кеша, привязанный к конкретной функции и её аргументам. Обычно она живёт в памяти одного процесса: в PHP — до конца обработки запроса. Общий кеш хранит любые данные и может переживать запросы. В WordPress для этого есть объектный кеш (wp_cache_get(), wp_cache_set()), а для данных со сроком жизни — transient, который сохраняется в базе или в Redis. Если результат нужен только внутри одного запроса, например функция вызывается из нескольких мест шаблона, хватает статической переменной. Если между запросами — нужен уже полноценный кеш с правилами сброса.

Обновлено:

Все термины раздела «Backend»

Что будем искать? Например,Продвижение