• Шаблоны для вашего сайта
  • Сделать сайт
  • Реклама
  • Berry CSS
  • Albireo Framework
  • Бесплатный HTML-курс
  • Telegram-канал
  • Обратная связь
MaxSite.org
О создании сайтов и не только
Создание сайтов под ключ →
Вход
×
или зарегистрироваться

Кэширование в PHP

PHPПросмотров: 7902Комментарии: 824 апреля 2020 г.

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

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

Совершенно бессмысленно создавать кэш для функций, которые редко вызываются в коде. В этом случае затраты на кэширование просто не «окупаются».

Существует два основных подхода к организации кэша: в файле и в памяти.

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

function my1()
{
    static $cache = false;
    
    if ($cache) return $cache;
    
    $out = ... что-то сложное и ресурсоёмкое ...
    
    $cache = $out;
    
    return $out;
}

Если функция имеет входящие аргументы, которые влияют на итоговый результат, то кэшируется не вся функция, а лишь самый ресурсоёмкий участок кода.

function my2($args)
{
    static $cache = false;
    
    if ($cache) {
        $data = $cache;
    } else {
        $data = ... что-то сложное и ресурсоёмкое ...
        $cache = $data;
    }
 
    $out = ... то что зависит от $data и $args
    
    return $out;
}

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

В ООП действуют аналогично, только вместо глобальной переменной применяют singleton/multiton с паттерном Registry.

Кэш в памяти — достаточно простой вариант для реализации. Если вы уже перешли на PHP 7, то учитывайте, что в этой версии очень здорово доработали оптимизацию, поэтому перед доработкой функций, убедитесь, что её выполнение действительно затратно (например с помощью функций профилирования).

Другой вид кэша — файловый. Он позволяет хранить результаты достаточно долго. В таком кэшировании вместо выполнения кода, отдаётся результат из файла-хранилища.

Например вы реализуете функцию, которая работает с csv-файлом: его получение, обработка, проверка и результат помещается в массив, который передаётся уже дальше по коду. Это затратные операции, поэтому полученный массив нужно сохранить в файл. Здесь не имеет смысла применять static-кэш, поскольку функция будет срабатывать для каждого посетителя сайта. Если же мы сохраним в файл, то обработка произойдёт только один раз.

Лучшим способом для хранения php-данных в файле — сериализация. Также можно использовать формат JSON — это для случаев, если нужно сделать кэш читаемым.

Файловый кэш может быть каким-то «глобальным», как например в MaxSite CMS, или «локальным», скажем на уровне шаблона — где задаётся какой-то фиксированный файл кэша определенной функции. «Глобальный» вариант реализуется достаточно просто — есть функции, которые либо добавляют, либо возвращают данные из кэша. Как именно он организован уже не имеет значения.

«Локальный» вариант обычно реализуется по такому алгоритму.

  • Проверяется существование файла кэша.
  • Если он есть, то он считывается и деселиализуется.
  • Если нет, то выполняется участок кода, результат которого сериализуется и записывается в файл кэша.
function my3($file)
{
    $cacheFile = $file . '.cache.txt';
    
    $flag = true; // флаг, что нужна полная обработка
    
    if (file_exists($cacheFile)) {
    
        // проверка устаревания кэша
        if (filemtime($cacheFile) > filemtime($file)) {
        
			$cache = file_get_contents($cacheFile);
			$cache = @unserialize($cache);
			
			if ($cache) {
				$data = $cache;
				$flag = false;
			}
		}
    }
    
    if ($flag) {
        // требуется полная обработка данных
        
        $data = ... что-то делаем ...
        
        // сохраняем в кэш
        file_put_contents($cacheFile, serialize($data));
    }
    
    ... дальше выполняем код с $data ...
}

При необходимости в такую функцию можно добавить ещё и static-кэширование. Это при условии, что обработка данных также ресурсозатратно. То есть смотреть по ситуации.

Кэширование вывода базируется на предыдущих вариантах и используется, когда даже нет смысла выполнять функции. То есть формируется готовый для вывода html-код, он загоняется в кэш (обычно файловый) и потом просто отдаётся как есть. Это самый быстрый в мире кэш. (Кто в курсе, то именно так работает мой maxcache для вп — он формирует кэш из готовых страниц так, что вп даже не запускается.)

Для организации такого кэша используется буферизация вывода.

... если нет кэша, то {
 
    ob_start();
 
    ... формируем html-вывод любым вариантом ...
 
    // результат оказывается в $out
    $out = ob_get_contents();
 
    // обнуляем буфер
    if (ob_get_length()) ob_end_clean();
 
    ... сохраняем $out в кэш ...
} else {
   ... сразу отдаём кэш ...
}

Такой кэш самый эффективный, но его использование будет оправдано для достаточно больших кусков html-кода. При этом нужно учитывать, что в кэш может попасть содержимое индивидуальное для каждого посетителя, например ссылка на профиль. То есть кэш должен учитывать такие ситуации. В MaxSite CMS по этому принципу работает плагин global_cache, где проверяется залогиненность посетителя: если она есть, то кэш для него не работает.

PS Вы можете подписаться а мой telegram-канал, где я рассказываю о PHP, MaxSite CMS и т.п. На сайте они публикуются.


Создание сайтов (Украина) →
Виды PHP-роутинга
Приватные репозитории GitHub для работы с клиентами
twitter.com facebook.com
Другие записи сайта
Контекстные ссылки: за и против
Контекстные ссылки: за и против
Приватные репозитории GitHub для работы с клиентами
Приватные репозитории GitHub для работы с клиентами
База SQLite и основы SQL. Часть 8
База SQLite и основы SQL. Часть 8
Что нам стоит сайт построить?
Что нам стоит сайт построить?
Шаблон «Template method» (Шаблонный метод)
Шаблон «Template method» (Шаблонный метод)
PHP-фреймворк Slim 4
PHP-фреймворк Slim 4

Комментариев: 8 RSS

1Сергей24-04-2020 18:48

Спс. И не забрасывайте телеграм канал. То как вы там пишете - сюда бы в документашку добавить. Оч понятно

2Виктор24-04-2020 20:37

а можно управлять временем жизни кеша?

3MAX24-04-2020 21:11

Хороший вопрос. :) Можно, но это более сложная задача. Самый простой способ — это смотреть время жизни файла кэша и если он более старый, чем текущее время + N минут, то он считается устаревшим его следует создать заново. Этот вариант реализован в моём LPF (mso_get_cache и mso_add_cache) http://lpf.maxsite.com.ua/.

Более сложный вариант — прописывать временную метку в начало файла кэша. Так работает кэш MaxSite CMS (и CodeIgniter). То есть перед unsetialize содержимое файла прогоняется через регулярку, по ней считывается время, а остаток уже десериализируется.

Так же может создаваться отдельный файл (в MaxSite CMS cache/_mso_cache_last.txt), где прописывается время последнего сброса кэша. По нему определяется «общее» устаревание кэша: когда оно достигнуто, то удаляются все файлы кэша. Это позволяет как бы синхронизировать все данные сайта.

4Аноним24-04-2020 22:20

"..текущее время + N минут" управляется через .htaccess, насколько я понимаю.

или есть более тонкие инструменты в LPF?

5Аноним24-04-2020 22:27

Где бы подробнее почитать про

ob_start();

ob_end_clean();

при использовании этих функций в своих страницах, формируемых плагинами.

6MAX25-04-2020 08:01

"..текущее время + N минут" управляется через .htaccess, насколько я понимаю.

Нет, .htaccess здесь ни при чём. Смотрится время файла, как я описал выше.

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

В оф.документации PHP: https://www.php.net/manual/ru/function.ob-start.php

7M21-05-2020 00:31

А как управлять временем жизни кэша из первого примера (где if ($cache)) - как сбросить, если надо обновить инфу и "пересобрать" кэш?

8MAX21-05-2020 08:53

В этом примере кэш - статическая переменная, которая живёт в пределах одного «пользователя». Если функция в разных вызовах в пределах одного процесса отдаёт разный результат, то кэширование в ней просто не нужно.

Оставьте комментарий!

Комментарий будет опубликован после проверки. Вы соглашаетесь с правилами сайта.

(обязательно)

Навигация
  • Шаблоны для MaxSite CMS 22
  • jQuery и JavaScript 6
  • Java и Android 5
  • PHP/ООП 25
  • SQL 17
  • Albireo Framework 11
  • Berry CSS 7
  • CSS, HTML, LESS, SASS 23
  • PHP 37
  • Тайм-менеджмент 9
  • Софт 37
  • SEO 13
  • Git. GitHub 3
  • CodeIgniter 5
  • Landing Page 3
  • Alpine.js 14
  • Фильмы 2
  • Дневник 55

Вот здесь можно заказать создание сайта, шаблона или лендинга. Также вы можете выбрать готовые шаблоны для MaxSite CMS по небольшой цене. Также можно купить отдельные модули, компоненты для вашего сайта.

MaxSite.org
Как создать свой сайт

Услуги по созданию сайтов, блогов, лендингов
Обратная связь • Реклама на сайте
Карта сайта
Мои проекты
  • Шаблоны для вашего сайта
  • Заказать создание сайта
  • MaxSite CMS
  • Berry CSS (CSS Utilities)
  • Albireo Framework
  • UniCSS (Universal Atomic CSS)
  • Landing Page Framework
  • Бесплатные НТML-курсы
Ссылки
  • Telegram-канал
  • Github
  • Twitter
  • Telegram-бот
  • RSS
© MaxSite.org, 2006-2022. Работает на MaxSite CMS | Время: 0.2816 | SQL: 20 | Память: 4.63MB | Вход