Регулярные выражения для чайников php. Регулярные выражения (шаблоны)

26.02.2019

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

История [ | ]

Впервые слово «cache» в компьютерном контексте было использовано в 1967 году во время подготовки статьи для публикации в журнале «». Статья касалась усовершенствования памяти в разрабатываемой модели 85 из серии IBM System/360 . Редактор журнала Лайл Джонсон попросил придумать более описательный термин, нежели «высокоскоростной буфер», но из-за отсутствия идей сам предложил слово «cache». Статья была опубликована в начале 1968 года, авторы были премированы IBM , их работа получила распространение и впоследствии была улучшена, а слово «кэш» вскоре стало использоваться в компьютерной литературе как общепринятый термин .

Функционирование [ | ]

Кэш - это память с большей скоростью доступа, предназначенная для ускорения обращения к данным, содержащимся постоянно в памяти с меньшей скоростью доступа (далее «основная память»). Кэширование применяется ЦПУ , жёсткими дисками , браузерами , веб-серверами , службами DNS и WINS .

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

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

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

Если кэш ограничен в объёме, то при промахе может быть принято решение отбросить некоторую запись для освобождения пространства. Для выбора отбрасываемой записи используются разные алгоритмы вытеснения .

При модификации элементов данных в кэше выполняется их обновление в основной памяти. Задержка во времени между модификацией данных в кэше и обновлением основной памяти управляется так называемой политикой записи .

В кэше с немедленной записью каждое изменение вызывает синхронное обновление данных в основной памяти.

В кэше с отложенной записью (или обратной записью ) обновление происходит в случае вытеснения элемента данных, периодически или по запросу клиента. Для отслеживания модифицированных элементов данных записи кэша хранят признак модификации (изменённый или «грязный» ). Промах в кэше с отложенной записью может потребовать два обращения к основной памяти: первое для записи заменяемых данных из кэша, второе для чтения необходимого элемента данных.

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

Аппаратная реализация [ | ]

Кэш центрального процессора [ | ]

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

Эксклюзивная кэш-память предполагает уникальность информации, находящейся в различных уровнях кэша (предпочитает фирма AMD).

В неэксклюзивной кэши могут вести себя как угодно.

Уровни кэша [ | ]

Кэш центрального процессора разделён на несколько уровней. Максимальное количество кэшей - четыре. В универсальном процессоре в настоящее время число уровней может достигать трёх. Кэш-память уровня N+1, как правило, больше по размеру и медленнее по скорости доступа и передаче данных, чем кэш-память уровня N.

  • Вторым по быстродействию является кэш второго уровня - L2 cache, который обычно, как и L1, расположен на одном кристалле с процессором. В ранних версиях процессоров L2 реализован в виде отдельного набора микросхем памяти на материнской плате. Объём L2 от 128 кбайт до 1−12 Мбайт. В современных многоядерных процессорах кэш второго уровня, находясь на том же кристалле, является памятью раздельного пользования - при общем объёме кэша в n Мбайт на каждое ядро приходится по n/c Мбайта, где c - количество ядер процессора.
  • Кэш третьего уровня наименее быстродействующий, но он может быть очень большим - более 24 Мбайт. L3 медленнее предыдущих кэшей, но всё равно значительно быстрее, чем оперативная память. В многопроцессорных системах находится в общем пользовании и предназначен для синхронизации данных различных L2.

Ассоциативность кэша [ | ]

Одна из фундаментальных характеристик кэш-памяти - уровень ассоциативности - отображает её логическую сегментацию, которая вызвана тем, что последовательный перебор всех строк кэша в поисках необходимых данных потребовал бы десятков тактов и свёл бы на нет весь выигрыш от использования встроенной в ЦП памяти. Поэтому ячейки ОЗУ жёстко привязываются к строкам кэш-памяти (в каждой строке могут быть данные из фиксированного набора адресов), что значительно сокращает время поиска.

При одинаковом объёме кэша схема с большей ассоциативностью будет наименее быстрой, но наиболее эффективной (после четырёхпотоковой реализации прирост «удельной эффективности» на один поток растет мало).

Кэширование внешних накопителей [ | ]

Многие периферийные устройства хранения данных используют внутренний кэш для ускорения работы, в частности, жёсткие диски используют кэш-память от 1 до 256 Мбайт (модели с поддержкой NCQ /TCQ используют её для хранения и обработки запросов), устройства чтения CD/DVD/BD-дисков также кэшируют прочитанную информацию для ускорения повторного обращения.

Операционная система также использует часть оперативной памяти в качестве кэша дисковых операций (например, для внешних устройств, не обладающих собственной кэш-памятью, в том числе жёстких дисков, flash-памяти и гибких дисков). Часто для кэширования жёстких дисков предоставляется вся свободная (не выделенная процессам) оперативная память.

Применение кэширования внешних накопителей обусловлено следующими факторами:

При чтении кэш позволяет прочитать блок один раз, затем хранить одну копию блока в оперативной памяти для всех процессов и выдавать содержимое блока «мгновенно» (по сравнению с запросом к диску). Существует техника «предзапроса» - в фоновом режиме операционной системой считываются в кэш также несколько следующих блоков (после нужного).

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

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

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

Программная реализация [ | ]

Политика записи при кэшировании [ | ]

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

Существуют две основные политики записи кэш-памяти - сквозная запись (write-through) и отложенная запись (write-back):

Алгоритм работы кэша с отложенной записью [ | ]

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

Процесс читает данные в полученный буфер и освобождает его. В случае модификации процесс перед освобождением помечает буфер как «грязный». При освобождении буфер помещается в голову списка свободных буферов.

Таким образом:

  1. если процесс прочитал некоторый блок в буфер, то велика вероятность, что другой процесс при чтении этого блока найдёт буфер в оперативной памяти;
  2. запись данных во внешнюю память выполняется только тогда, когда не хватает «чистых» буферов, либо по запросу.

Алгоритм вытеснения [ | ]

Если список свободных буферов пуст, то выполняется алгоритм вытеснения буфера. Алгоритм вытеснения существенно влияет на производительность кэша. Существуют следующие алгоритмы:

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

Кэширование, выполняемое операционной системой [ | ]

Кэш оперативной памяти состоит из следующих элементов:

Кэширование интернет-страниц [ | ]

В процессе передачи информации по сети может использоваться кэширование интернет-страниц - процесс сохранения часто запрашиваемых документов на (промежуточных) прокси-серверах или машине пользователя, с целью предотвращения их постоянной загрузки с сервера-источника и уменьшения трафика . Таким образом, информация перемещается ближе к пользователю. Управление кэшированием осуществляется при помощи HTTP -заголовков.

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

Кэширование результатов работы [ | ]

Многие программы записывают куда-либо промежуточные или вспомогательные результаты работы, чтобы не вычислять их каждый раз, когда они понадобятся. Это ускоряет работу, но требует дополнительной памяти (оперативной или дисковой). Примером такого кэширования является.

См. также [ | ]

Примечания [ | ]

  1. Кэш // Большой орфографический словарь русского языка / под ред.

Кэширование — это один из способов оптимизации Web приложений. В любом приложении встречаются медленные операции (SQL запросы или запросы к внешним API), результаты которых можно сохранить на некоторое время. Это позволит выполнять меньше таких операций, а большинству пользователей показывать заранее сохраненные данные.

Наиболее популярная технология кеширования для Web приложений — Memcache .

Когда нужно кэшировать

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

  • Используйте классы или функции, для работы с данными. Не используйте повторяющихся SQL выборок в основном приложении.
  • Используйте обертки для работы с внешними API.

Что кэшировать?

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

  • Результаты запросов к внешним сервисам (RSS, SOAP, REST и т.п.).
  • Результаты медленных выборок из базы данных.
  • Сгенерированные html блоки либо целые страницы.

Кэширование выборок из баз данных

Запросы к базе данных — наиболее распространенный пример. На основе Мemcache реализуется очень просто:

!$list = memcache_get("online_users") ) { $sql = "SELECT * FROM users WHERE last_visit > UNIX_TIMESTAMP() - 60*10"; $q = mysql_query($sql); while ($row = mysql_fetch_assoc($q)) $list = $row; memcache_set("online_users", $list, 60*60); } return $list; } $list = get_online_users(); ...

# Запрос на получение пользователей кэшируется на 1 час

Обновление данных

Если Вы кэшируете данные, которые могут обновляться, необходимо очищать кэш после каждого обновления:

memcache_delete("user" . $id); }

Кэширование списков

Допустим, Вы кэшируете данные каждого пользователя, как в примере, а также их списки (например, список online пользователей). При обновлении данных пользователя, Вы удаляете данные из кэша только для указанного пользователя. Но его данные могут также присутствовать в списке online пользователей, которые тоже лежат в кэше. Сбрасывать списки при каждом обновлении данных любого пользователя не эффективно. Поэтому обычно используют такой подход:

  1. Кэшируют списки, которые состоят только из ID пользователей.
  2. Для вывода списка отправляют отдельный запрос для получения данных каждого пользователя.

Реализация выглядит так:

id FROM users WHERE last_visit > UNIX_TIMESTAMP() - 60*10"; $q = mysql_query($sql); while ($row = mysql_fetch_assoc($q)) $list = $row["id"] ; memcache_set("online_users", $list, 60*60); } return $list; } $list = get_online_users(); foreach ($list as $id) { $user = get_user($id); ... }

# Получим список ID пользователей и для каждого из них получим актуальные данные

Для получения данных сразу нескольких объектов можно использовать Multiget .

Повторные запросы

Некоторые данные могут запрашиваться несколько раз в рамках одной страницы, например:

get_user($_SESSION["id"])["name"] )?>

... Email: get_user($_SESSION["id"])["email"] ?> ... get_user($_SESSION["id"])["nick"] ?>">Моя страница ...

Каждый вызов get_user() будет получать данные из кэша. Если Memcache стоит на отдельном сервере, это вызовет большой сетевой трафик и задержки.

Чтобы этого избежать, можно использовать дополнительный кэш внутри самого приложения:

global $app_cache; if ($app_cache["user" . $id]) return $app_cache["user" . $id]; if (!$data = memcache_get("user" . $id)) { $sql = "SELECT * FROM users WHERE id= " . intval($id); $q = mysql_query($sql); $data = mysql_fetch_assoc($q); memcache_set("user" . $id, $data, 60*60); $app_cache["user" . $id] = $data; } return $data; } function save_user($id, $data) { global $app_cache; mysql_query("UPDATE users SET ... WHERE id = " . intval($id)); memcache_delete("user" . $id); unset($app_cache["user" . $id]); }

В реальных приложениях, имеет смысл иметь обертку для Memcache с дополнительным кэшом:

inner_cache)) return $this->inner_cache[$key]; $data = memcache_get($this->resource, $key); $this->inner_cache[$key] = $data; return $data["value"]; } public static function set($key, $value, $ttl) { memcache_set($key, $value, $ttl); $this->inner_cache[$key] = $value; } public static function del($key) { memcache_delete($key); unset($this->inner_cache[$key]); } }

# $inner_cache хранит дополнительный кэш

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

public static $inner_cache_enabled = true; public static function get($key) { if (self::$inner_cache_enabled && array_key_exists($key, $this->inner_cache)) return $this->inner_cache[$key]; $data = memcache_get($this->resource, $key); $this->inner_cache[$key] = $data; return $data["value"]; } public static function set($key, $value, $ttl) { memcache_set($key, $value, $ttl); if (self::$inner_cache_enabled) $this->inner_cache[$key] = $value; } public static function del($key) { memcache_delete($key); unset($this->inner_cache[$key]); } } ... mem_cache::$inner_cache_enabled = false;

# Отключаем внутренний кэш

Подогревание

При обновлении особенно тяжелых данных следует использовать не сброс кэша, а прямое обновление данных в нем:

# операции по обновлению внешних ресурсов $data = file_get_contents("http://rss.com/rss"); memcache_set("rss", $data, 60*60); }

Это позволит избежать дополнительной нагрузки при выполнении тяжелых выборок, когда ключ удаляется. Такую методику обычно используют в cron задачах, чтобы периодически обновлять результаты очень тяжелых выборок.

Время жизни (ttl)

ttl (время жизни) — это время, после которого, данные будут удалены из кэша. В Memcache устанавливается в секундах:

60*60 );

# Установка ttl на 1 час

Чаще всего ttl ставят от нескольких минут до нескольких дней. Не используйте значение 0 (бесконечное хранение), это может засорить память.

LRU

Любой кэш работает по принципу вытеснения если ему не хватает памяти. Т.е. если Memcache может использовать максимум 1G памяти, а Вы пытаетесь сохранить ключей на 2G, то половину из этих данных Memcache удалит. Для определения, какие именно ключи удалять, используется алгоритм LRU (Least Recently Used):

Memcache постарается удалить прежде всего те данные, которые запрашивались очень давно (т.е. менее популярные удалит, а более популярные оставит).

Кэширование очень медленных запросов

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

Чтобы этого избежать, необходимо использовать специальную методику дублирования .

Атомарные операции

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

Memcache поддерживает две атомарные операции увеличения и уменьшения чисел:

# Увеличит счетчик на 1, функция memcache_decrement() уменьшает счетчик

Самое важное

Кэширование в приложениях на основе Memcache — это очень сильный инструмент. Не забывайте, что Memcache не гарантирует Вам сохранности данных. Это значит, что нельзя рассчитывать на то, что сохраненные на 60 минут данные будут находиться в кэше именно 60 минут.

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

В качестве кэша используются разные устройства: для уменьшения среднего времени доступа к оперативной памяти – быстродействующая статическая память; для ускорения доступа к данным на диске – буферы в оперативной памяти. Виртуальная память также является одним из вариантов реализации принципа кэширования данных. В этом случае оперативная память выступает в роли кэша по отношению к внешней памяти (диску), и кэширование используется для частичной замены оперативной памяти диском за счет перемещения временно неиспользуемого кода и данных на диск с целью освобождения места для активных процессов. Содержимое стандартной кэш-памяти представляет собой совокупность записей о загруженных в нее элементах данных из основной памяти (рис.5.26.). Каждая запись об элементе данных включает:

Значение элемента данных;

Адрес элемента данных в основной памяти;

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


При каждом обращении к основной памяти по физическому адресу просматривается содержимое кэш-памяти с целью определения требуемых данных. Поиск в кэш-память осуществляется по содержимому – по взятому из запроса значению поля адреса в оперативной памяти. Если данные обнаруживаются в кэш-памяти, произошло кэш-попадание (cache-hit ), то они считываются и результат передается источнику запроса. Если нужные данные отсутствуют, произошел кэш-промах (cache-miss ), то они считываются из основной памяти, передаются источнику запроса и одновременно с этим копируются в кэш-память.

Эффективность кэширования и среднее время доступа к данным в системе зависят от вероятности попадания в кэш. Поэтому использование кэш-памяти эффективно только при высокой вероятности кэш-попадания. Вероятность обнаружения данных в кэше зависит от следующих факторов: от объемов кэша и кэшируемой памяти, от алгоритма замещения данных в кэше, от особенностей выполняемой программы и времени ее работы, от уровня мультипрограммирования и других особенностей вычислительного процесса. В большинстве реализаций кэш-памяти процент кэш-попаданий выше 90%, это объясняется наличием у данных объективных свойств: пространственной и временной локальности.

Временная локальность характеризуется признаком: если произошло обращение по некоторому адресу, то следующее обращение по тому же адресу с большой вероятностью произойдет в ближайшее время. Пространственная локальность характеризуется признаком: если произошло обращение по некоторому адресу, то с высокой степенью вероятности в ближайшее время произойдет обращение к соседним адресам.



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

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

В процессе работы содержимое кэш-памяти постоянно обновляется, так как периодически происходит вытеснение данных. Вытеснение означает объявление свободной определенной области кэш-памяти. Если вытесняемые данные не были изменены, производится сброс бита действительности. Если вытесняемые данные за время нахождения в кэше были изменены (модифицированы) дополнительно производится копирование данных в основную память. Алгоритм замены данных в кэш-памяти существенно влияет на ее эффективность, поэтому он должен быть максимально быстрым и обеспечивать максимально возможную вероятность кэш-попаданий.

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

1.Сквозная запись (write through ). При каждом запросе к основной памяти и при записи в нее просматривается кэш. Если данные по запрашиваемому адресу отсутствуют, то запись выполняется только в основную память. Если же данные, к которым выполняется обращение, находятся в кэше, то запись выполняется одновременно в кэш и основную память.

2.Обратная запись (write back ). При возникновении запроса к памяти выполняется просмотр кэша. Если запрашиваемых данных отсутствуют, то запись выполняется только в основную память. В ином случае запись производится только в кэш-память, при этом в описателе данных делается специальная отметка (признак модификации), которая указывает на то, что при вытеснении этих данных из кэша необходимо переписать их в основную память.

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

Алгоритм поиска и алгоритм замещения данных в кэше зависят от способа отображения основной памяти на кэш-память. Используются следующие схемы отображения:

1.Случайное отображение . Элемент оперативной памяти и его адрес размещается в произвольном месте кэш-памяти. Критерием поиска в кэше является адрес оперативной памяти из запроса. Для поиска запрошенных данных используется алгоритм ассоциативного поиска , при котором сравнения с записями кэша выполняются параллельно. Признак (адрес данных в оперативной памяти), по которому выполняется сравнение, называется тегом (tag ). Вытеснение устаревших данных происходит только в случае, полного заполнения кэш-памяти. Выбор данных на выгрузку осуществляется среди всех записей кэша и основывается на приемах, аналогичных алгоритмам замещения страниц. Электронная реализация схемы приводит к удорожанию памяти, поэтому ассоциативная кэш-память используется в случаях, когда для обеспечения высокого процента попадания достаточно небольшого объема памяти.

2.Детерминированное отображение . Элемент основной памяти всегда отображается в одно и то же место кэш-памяти. Кэш-память разделена на строки, каждая из которых имеет свой номер и предназначена для хранения одной записи об одном элементе данных. Между номерами строк кэш-памяти и адресами оперативной памяти устанавливается соответствие «один ко многим»: одному номеру строки соответствует несколько адресов оперативной памяти. Отображение осуществляется при помощи специальных функций, например, путем простого выделения нескольких разрядов из адреса оперативной памяти, которые интерпретируются как номер строки кэш-памяти.

Для поиска данных в кэше используется прямой доступ к записи по номеру строки, полученному путем обработки адреса оперативной памяти из запроса. Но в найденной строке могут находиться данные из любой ячейки оперативной памяти, младшие разряды адреса которой совпадают с номером строки, поэтому дополнительно выполняется проверка. Для выполнения проверки каждая строка кэш-памяти дополняется тегом, содержащим старшую часть адреса данных в оперативной памяти. При совпадении тега с соответствующей частью адреса из запроса констатируется кэш-попадание. Если произошел кэш-промах, то данные считываются из оперативной памяти и копируются в кэш. Если строка кэш-памяти, в которую должен быть скопирован элемент данных из оперативной памяти, содержит другие данные, то они вытесняются из кэша.

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

По номеру группы, полученному из адреса оперативной памяти из запроса;

В пределах группы путем ассоциативного просмотра всех записей в группе на случай совпадения старших частей адресов оперативной памяти.

При промахе данные копируются по свободному адресу из однозначно заданной группы. Если свободных адресов в группе нет, то выполняется вытеснение данных по определенным алгоритмам.

Схема работы кэша

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

Прогресс требовал увеличения объемов для хранения данных , в то время как быстрота их обработки отставала с самого зарождения компьютеров. Именно из-за этого и был разработан такой «мост». Процесс занесения информации в кэш-память получил название «кэширование ». Собственно, поэтому и важно её своевременно очищать – для сохранения эффективности считывания.

Кэширование в браузерах


Алгоритм кэширования в браузерах

Зачастую, говоря о кэшировании, многие вспоминают о cache -файлах в браузерах. И неудивительно, так как их очистка – один из основных советов, который дают пользователям при возникновении ошибок.

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

Кэш в Windows

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

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

Кэш на андройде

На смартфонах с операционной системой Android ситуация выглядит похожим образом, за одним существенным «но» — объем предоставленной памяти значительно ниже , чем на персональном компьютере. Помимо этого, программы после запуска хранятся в трей-листе, откуда их потом можно заново развернуть , со всеми сохраненными изменениями, совершенными в последней сессии.

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

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

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

Я думаю, что когда у Вас есть такой замечательный инструмент как memcached, так и хочется использовать его для решения любой проблемы с производительностью. Но во многих случаях он не должен быть первым инструментом который Вы пытаетесь использовать. И вот почему:

- Кэширование может работать не для всех пользователе й - Вы открываете страницу - она загружается быстро. Но так ли это для всех пользователей? Кэширование очень часто позволяет оптимизировать время загрузки для большинства посетителей, но часто в реальности Вам надо чтобы страница загружалась быстро для всех без исключения (если следовать принципу six sigma). На практике запрос может промахиваться мимо кэша всегда для одного и того же пользователя, что еще более усугубляет ситуацию (Прим. переводчика : Я знаю совершенно реальный случай, когда в электронном магазине кэш срабатывал для 99% процентов пользователей и не работал для 1% посетителей имевших длинную историю покупок, как результат магазин работал медленно как раз для активных покупателей).

- Кэширование может уводить Вас в сторону от решения проблемы - Вы смотрите на наиболее медленно загружающуюся страницу и пытаетесь ее оптимизировать. Но хитрость здесь в том, что в реальности проблема с производительностью может лежать в другой области (опять six sigma). Вы «залечиваете» проблему кэшируя, например, страницу целиком, но сама проблема с производительностью никуда не уходит и остается скрытой (Прим. переводчика : с тем чтобы всплыть на других страницах еще и еще и еще раз).

- Управление кэшем в реальности непростая задача - Вы когда-нибудь боролись с "убеганием кэша " или с ситуацией когда большое количество элементов кэша инвалидируются одновременно?

Альтернативный подход

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

Что это за способы?

Перед тем как вводить оптимизацию убедитесь что Вы прошлись по этому достаточно простому списку:

- Вы понимаете план исполнения каждого запроса? Если нет, установите long_query_time=0 и используйте команду mk-query-digest, чтобы получить полный список запросов. Выполните для каждого из них EXPLAIN, проанализируйте план исполнения.

Вы используете SELECT * чтобы потом использовать только небольшой набор столбцов? Или вы выбираете из БД много строк, но используете только некоторые из них? Если это так - то вы выбираете слишком много данных, ограничивая оптимизацию уровня СУБД, такую например как использование индексов.

Знаете ли Вы сколько именно запросов Вы используете для генерации одной страницы? Все ли они действительно необходимы? Можно ли какие-то из этих запросов превратить в один запрос или вообще убрать? (Прим. переводчика : Очень распространенная проблема. Реально знаю случай когда на странице отображался список учеников в классе, а затем в цикле для каждого ученика запрашивалась дополнительная информация, включая название класса. После переделки количество запросов сократилось с 61 до 3-х).

Думаю что как вывод можно сказать: «Оптимизация очень редко уменьшает сложность приложения. Старайтесь избегать усложнения, за счет оптимизации только того, что действительно надо оптимизировать» - цитата со слайда Джастина - instrumentation-for-php .

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

Прим. переводчика : Совершенно реальный диалог произошедший не так давно:
- Так у нас проблемы с производительностью, надо добавить кэширование, вертикальное партиционирование и NoSQL DB для логинов
- Парни - я тут посмотрел EXPLAIN - у Вас fullscan запрос на 4,000 строк, я попробовал создать индекс- все ускорилось в 26 раз.

Несколько замечаний к переводу

1. Термин cache stampeding - я перевел как убегание кэша (был соблазн перевести как «просрачивание», но это было бы неправильно). Если коротко, это ситуация, когда например определенный запрос выполняется достаточно долго и результаты этого запроса кэшируются, когда затем эти данные рано или поздно уходят из кэша, и одновременно рендерится 10 страниц на которых эти данные нужны, то в БД отправляется 10 медленных запрсов, вместо одного. Обычно с этим борются пере запрашивая данные до того как они будут выкинуты из кэша. см например
2. Хочу обратить внимание, что в статье не говорится что кэшировать данные не надо. Их надо кэшировать, но только после того как Вы попробуете несколько простых способов оптимизации запросов к БД. Иными словами начинать надо с простого.