Политика замены страниц (Replacement Policies)#
Если при включенном Native Persistence объем данных, который DataGrid хранит на диске, больше объема памяти вне heap, нужно вытеснить страницу данных из памяти Off-Heap на диск, чтобы загрузить страницу с диска в целиком заполненную память Off-Heap. Этот процесс называется заменой или ротацией страниц (page replacement, page rotation).
Когда Native Persistence выключен, вместо замены страниц используется вытеснение данных (eviction) — подробнее об этом написано в разделе «Политика вытеснения данных из кеша (Eviction Policies)».
Когда DataGrid нужна страница данных, ее поиск начинается с памяти вне heap. Если нужная страница данных не нашлась в Off-Heap, она загружается с диска. Если память вне heap переполнена, нужно выбрать другую страницу для замены (для хранения на диске и вытеснения).
Алгоритмы поиска страниц для замены:
Алгоритм по замене страниц настраивается с помощью свойства PageReplacementMode в DataRegionConfiguration. По умолчанию используется алгоритм CLOCK.
Пример настройки алгоритма замены страниц:
<bean class="org.apache.ignite.configuration.IgniteConfiguration">
<!-- Конфигурация памяти. -->
<property name="dataStorageConfiguration">
<bean class="org.apache.ignite.configuration.DataStorageConfiguration">
<property name="dataRegionConfigurations">
<list>
<!--
Определение персистентного региона данных с режимом замены страниц Segmented-LRU.
-->
<bean class="org.apache.ignite.configuration.DataRegionConfiguration">
<!-- Название региона данных. -->
<property name="name" value="persistent_data_region"/>
<!-- Включите режим Persistence. -->
<property name="persistenceEnabled" value="true"/>
<!-- Максимальный размер — 20 Гб (ОЗУ). -->
<property name="maxSize" value="#{20L * 1024 * 1024 * 1024}"/>
<!-- Включение алгоритма замены страниц SEGMENTED-LRU для данного региона. -->
<property name="pageReplacementMode" value="SEGMENTED_LRU"/>
</bean>
</list>
</property>
</bean>
</property>
<!-- Остальная конфигурация. -->
</bean>
// Конфигурация узла.
IgniteConfiguration cfg = new IgniteConfiguration();
// Конфигурация памяти.
DataStorageConfiguration storageCfg = new DataStorageConfiguration();
// Создание нового региона данных.
DataRegionConfiguration regionCfg = new DataRegionConfiguration();
// Название региона.
regionCfg.setName("persistent_data_region");
// Включение режима Persistence.
regionCfg.setPersistenceEnabled(true);
// Максимальный размер — 20 Гб (ОЗУ).
regionCfg.setMaxSize(20L * 1024 * 1024 * 1024);
// Включение алгоритма замены страниц SEGMENTED-LRU для данного региона.
regionCfg.setPageReplacementMode(PageReplacementMode.SEGMENTED_LRU);
// Установка конфигурации региона данных.
storageCfg.setDataRegionConfigurations(regionCfg);
// Применение новой конфигурации.
cfg.setDataStorageConfiguration(storageCfg);
Выбор алгоритма зависит от нагрузки. Для большинства случаев подходит алгоритм CLOCK, он используется по умолчанию.
Алгоритм Random-LRU#
При каждом обращении к странице обновляется ее временная метка. Если произошла ошибка и страница отсутствует, но пришло время замены, алгоритм случайным образом выбирает пять страниц из памяти и вытесняет страницу с последней временной меткой.
У алгоритма нулевая стоимость обслуживания, но он не эффективен с точки зрения поиска следующей страницы для замены. Его рекомендуется использовать в средах, где не требуется замена страниц (при работе с достаточно большим регионом данных для хранения всего объема) или где замена страниц происходит очень редко.
Алгоритм Segmented-LRU#
Алгоритм Segmented-LRU — устойчивый к сканированию вариант алгоритма LRU (Least Recently Used). Список страниц Segmented-LRU делится на два типа: сегмент для испытаний и защищенный сегмент. Страницы каждого сегмента упорядочены от наименее до наиболее посещаемых. Новые страницы добавляются в конец сегмента испытаний. Существующие страницы удаляются из текущего местоположения и добавляются в конец защищенного сегмента. Все страницы в нем используются как минимум два раза. У защищенного сегмента есть ограничения по размеру, поэтому переход страницы из сегмента испытаний может привести к миграции LRU-страницы из защищенного сегмента в конец сегмента испытаний. Это даст странице еще одну попытку использования перед заменой. Страница для замены выбирается из наименее посещаемых страниц сегмента испытаний.
Segmented-LRU требует дополнительной памяти для хранения списка страниц, который обновляется при каждом посещении каждой страницы. При этом алгоритм использует практически оптимальную политику выбора страниц для замены. В связи с этим в средах без замены страниц по сравнению с алгоритмами Random-LRU и CLOCK может быть небольшое снижение производительности, но для сред с высокой частотой замены страниц и большим количеством единовременных сканирований эффективность Segmented-LRU может превосходить остальные алгоритмы.
Алгоритм CLOCK#
Алгоритм CLOCK хранит в памяти циклический список страниц, в котором «стрелка» (hand) указывает на последний просмотренный фрейм страницы в списке. Если происходит ошибка (страница отсутствует и пустых фреймов нет), в месте нахождения hand проверяется флаг попадания (hit flag) страницы. Если значение hit flag — 0, вместо страницы, на которую показывает hand, помещается новая, а сам указатель перемещается на одну позицию дальше. Если значение hit flag ненулевое, флаг очищается, указатель hand увеличивается и процесс повторяется до тех пор, пока не произойдет замена страницы.
У алгоритма почти нулевая стоимость обслуживания. Эффективность замены страниц CLOCK больше Random-LRU и меньше Segmented-LRU.