Функции и принципы работы дискового кэша существенно отличаются от общих
алгоритмов кэширования, обсуждавшихся в разд.
Страничный обмен. Дело в том, что характер обращения к файлам обычно
существенно отличается от обращений к областям кода и данных задачи. Например,
компилятор С и макропроцессор ТЕХ рассматривают
входные и выходные файлы как потоки данных. Входные файлы прочитываются
строго последовательно и полностью, от начала до конца. Аналогично, выходные
файлы полностью перезаписываются, и перезапись тоже происходит строго
последовательно. Попытка выделить аналог рабочей области при таком характере
обращений обречена на провал независимо от алгоритма, разве что рабочей
областью будут считаться все входные и выходные файлы.
Тем не менее кэширование или, точнее, буферизация данных при работе с
диском имеет смысл и во многих случаях может приводить к значительному
повышению производительности системы. Если отсортировать механизмы повышения
производительности в порядке их важности, мы получим следующий список.
Кэширование значительно повышает производительность дисковой подсистемы,
но создает ряд проблем, причем некоторые из них довольно неприятного свойства.
Первая из проблем — та же, что и у отложенной записи. При использовании
отложенной записи программа не знает, успешно ли завершилась физическая
запись. При работе с дисками один из основных источников ошибок — физические
ошибки диска. Однако многие современные файловые системы поддерживают
так называемый hotfixing (горячую починку)
— механизм, обеспечивающий динамическую замену "плохих" логических
блоков на "хорошие", что в значительной мере компенсирует эту
проблему.
Вторая проблема гораздо серьезнее и тоже свойственна всем механизмам отложенной
записи: если в промежутке между запросом и физической записью произойдет
сбой всей системы, то данные будут потеряны. Например, пользователь сохраняет
отредактированный файл и. не дождавшись окончания физической записи, выключает
питание — содержимое файла оказывается потеряно или повреждено. Другая
ситуация, до боли знакомая всем пользователям DOS/Windows З.х/Windows
95: пользователь сохраняет файт и в это время система зависает — результат
тот же. Аналогичного результата можно достичь, не вовремя достав дискету
или другой удаляемый носите-ц, из привода (чтобы избежать этого, механика
многих современных дисководов позволяет программно заблокировать носитель
в приводе).
Очень забавно наблюдать, как пользователь, хотя бы раз имевший неприятный
опыт общения с дисковым кэшем SMARTDRV, копирует данные с чужого компьютера
на дискету. Перед тем, как извлечь ее из дисковода, он оглядывается на
хозяина машины и с опаской спрашивает: "У тебя там никаких кэшей
нет?". В эпоху MS DOS авторам доводилось наблюдать такое поведение
у нескольких десятков людей.
Если откладывается запись не только пользовательских данных, но и модифицированных
структур файловой системы, ситуация еще хуже: системный сбой может привести
не только к потере данных, находившихся в кэше, но и к разрушению файловой
системы, т. е. в худшем случае, к потере всех данных на диске.
Методы обеспечения целостности данных при системном сбое подробнее обсуждаются
в разд. Устойчивость ФС к сбоям.
Находившиеся в кэше данные при фатальном сбое гибнут всегда, но существуют
способы избежать.повреждения системных структур данных на диске без отказа
от использования отложенной записи.
Третья проблема, связанная с дисковым кэшем, — это выделение памяти под
него. Уменьшение кэша приводит к снижению производительности дисковой
подсистемы, увеличение же кэша отнимает память у пользовательских процессов.
В системах с виртуальной памятью это может привести к увеличению дисковой
активности за счет увеличения объема подкачки, что ведет к снижению как
дисковой, так и общей производительности системы. Перед администратором
системы встает нетривиальная задача: найти точку оптимума. Положение этой
точки зависит от следующих параметров:
При этом зависимость количества страничных отказов от объема памяти,
доступной приложениям, имеет существенно нелинейный вид. Это же утверждение
справедливо для связи между размером дискового кэша и соответствующей
экономией обращений к диску. Таким образом, задача подбора оптимального
размера кэша — это задача нелинейной оптимизации. Самое неприятное, что
ключевой исходный параметр — характер обращений к диску — не количественный,
а качественный; точнее сказать, его можно измерить лишь при помощи очень
большого числа независимых количественных параметров.
Во многих ситуациях невозможно теоретически оценить положение оптимальной
точки, и единственным способом оказывается эксперимент: прогон типичной
для данной машины смеси заданий при различных объемах кэша. При этом нужно
иметь возможность различать дисковую активность, связанную с обращениями
к файлам и со страничным обменом. Большинство современных ОС предоставляют
для этой цели различные инструменты системного мониторинга. Чаше, однако,
объем кэша выставляется на глаз, а к дополнительной настройке прибегают,
только если производительность оказывается слишком низкой.
Возникает вполне естественное желание возложить подбор размера кэша на
саму систему, т. е. менять размер кэша динамически в зависимости от рабочей
нагрузки. Кроме упрощения работы администратора, такое решение имеет еще
одно большое преимущество: система начинает "автомагически"
подстраиваться под изменения нагрузки.
Но далеко не все так просто. Если объем памяти в системе превосходит потребности
прикладных программ, то динамический дисковый кэш может формироваться
по очень простому "остаточному" принципу — все, что не пригодилось
приложениям, отдается под кэш. Однако оперативная память до сих пор относительно
дорога и представляет собой дефицитный ресурс, поэтому наибольший практический
интерес представляет ситуация, когда памяти не хватает даже приложениям,
не говоря уже о кэше. Тем не менее и в этой ситуации кэш некоторого объема
бывает нужен.
Разумной политикой была бы подстройка кэша в зависимости от количества
страничных отказов: если число отказов становится слишком большим, система
уменьшает кэш; если же число отказов мало, а идут интенсивные обращения
к диску, система увеличивает кэш. Получается саморегулирующаяся система
с отрицательной обратной связью. Однако, если вдуматься, то видно, что
вместо одной произвольной переменной (объема статического кэша) мы вынуждены
ввести как минимум три:
На практике, часто также вводятся параметры, ограничивающие минимальный
и максимальный размеры кэша.
Оптимальные значения этих переменных зависят практически от тех же самых
параметров, что и объем статического кэша, но подбор значений экспериментальным
путем оказывается значительно сложнее, потому что вместо одномерной нелинейной
оптимизации мы вынуждены занимать трехмерной нелинейной оптимизацией.
Кроме того, читатель, знакомый с теорией управления, должен знать чт неудачный
подбор параметров у системы с отрицательной обратной связь может приводить
к колебательному процессу вместо саморегуляции, в дм куссиях USENET news
приводились примеры развития таких колебаний динамическом кэше системы
Windows NT при компиляции большого проекта в условиях недостатка памяти.
Вполне возможно, что низкая производительность Windows NT/2000/XP на машинах
с небольшим количеством памяти объясняется вовсе не низким качеством реализации
и даже не секретным сговором между фирмой Microsoft и производителями
оперативной памяти, а просто плохо сбалансированным динамическим кэшем.