почему команда linux cp не потребляет диск IO?

os: centos7

тестовый файл: a.txt 1.2G

команда монитора: iostat -xdm 1

The first scene: cp a.txt b.txt #b.txt is not exist 

введите описание изображения здесь

 The second scene: cp a.txt b.txt #b.txt is exist 

введите описание изображения здесь

Почему первая сцена не потребляет IO, но вторая сцена потребляет IO?

Вполне возможно, что данные не были сброшены на диск во время первой операции cp , но были во время второго.

Попробуйте установить vm.dirty_background_bytes на что-то маленькое, например 1048576 (1 MiB), чтобы убедиться, что это так; запустите sysctl -w vm.dirty_background_bytes=1048576 , а затем ваш первый сценарий cp должен показать I / O.

Что тут происходит?

За исключением случаев синхронного и / или прямого ввода-вывода, запись на диск получает буферизацию в памяти до тех пор, пока не будет достигнут порог, после чего они начнут сбрасываться на диск в фоновом режиме. Этот порог не имеет официального имени, но он контролируется vm.dirty_background_bytes и vm.dirty_background_ratio , поэтому я назову его «Dirty Background Threshold». Из документов ядра :

vm.dirty_background_bytes

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

Примечание: dirty_background_bytes является аналогом dirty_background_ratio . Только один из них может быть указан одновременно. Когда один файл sysctl записывается, он сразу же учитывается для оценки границ грязной памяти, а другой отображается как 0 при чтении.

dirty_background_ratio

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

Общая доступная память не равна общей системной памяти.

vm.dirty_bytes и vm.dirty_ratio

Есть второй порог, помимо этого. Ну, больше предел, чем порог, и он контролируется vm.dirty_bytes и vm.dirty_ratio . Опять же, у него нет официального имени, поэтому мы назовем его «Dirty Limit». После того, как все данные будут «записаны», но не будут переданы базовому блочному устройству, дальнейшие попытки write придется ждать завершения ввода-вывода. (Точные данные о том, какие данные им придется ждать, непонятно для меня и может быть функцией планировщика ввода-вывода. Я не знаю.)

Зачем?

Диски медленные. Особенно прямая ржавчина, поэтому, пока голова R / W на диске движется, чтобы удовлетворить запрос на чтение, запросы на запись не могут обслуживаться до тех пор, пока запрос на чтение не будет завершен, и запрос на запись может быть запущен. (И наоборот)

КПД

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

Мы можем настроить, сколько данных буферизуется, прежде чем ядро ​​попытается записать его на диск с помощью vm.dirty_background_bytes и vm.dirty_background_ratio .

Слишком много буферизованных данных записи!

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

Итак, у нас есть vm.dirty_bytesvm.dirty_ratio ); это позволяет нам сказать: «Эй, подожди минутку, настало время получить данные на диск, пока это не станет хуже».

Все еще слишком много данных

Однако жесткая остановка ввода-вывода очень разрушительна; диск уже медленный с точки зрения процессов чтения, и для этих данных может потребоваться от нескольких секунд до нескольких минут ; рассмотрите значение vm.dirty_bytes умолчанию 20. Если у вас есть система с 16 ГБ ОЗУ и без обмена, вы можете обнаружить, что ваш I / O заблокирован, пока вы ожидаете, что данные 3.4GiB будут сброшены на диск. На сервере с 128 ГБ ОЗУ? У вас будет время ожидания обслуживания, пока вы ждете 27.5GiB данных!

Поэтому полезно сохранить vm.dirty_bytes (или vm.dirty_ratio , если хотите) достаточно низко, чтобы, если вы нажмете этот жесткий порог, он будет минимально подрывать ваши услуги.

Какие хорошие ценности?

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

На рабочих станциях и ноутбуках с единственными дисками мне нравится устанавливать vm.dirty_background_bytes примерно в 1MiB и vm.dirty_bytes между 8MiB и 16MiB. Я очень редко нахожу пропускную способность за пределами 16MiB для однопользовательских систем, но зависания при задержке могут стать довольно плохими для любых синхронных рабочих нагрузок, таких как хранилища данных веб-браузера.

На чем-либо с полосатым массивом четности, я нахожу несколько кратных ширины полосы массива, чтобы быть хорошим стартовым значением для vm.dirty_background_bytes ; это уменьшает вероятность необходимости выполнять последовательность чтения / обновления / записи при обновлении четности, улучшая пропускную способность массива.

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

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