Кто бы мог подумать, что Read Look-Ahead и read-ahead (readahead) могут оказаться страшнейшим багом, а не фичей! Баг сей ярко выражен в жутком свопинге, когда выполняется чтение больших файлов, в результате которого всё встаёт колом на одном месте без движений в какую либо сторону.
Днями ранее мы писали про проблему со скачиванием большого файла БД Беркли размером 80G, когда FileZilla вместо 80G накачало целых 83G и качало бы дальше ели бы её принудительно не остановили (перекачивали заново wget-ом).
Так вот, пробовали мы этот файл БД Беркли 80G как-то читать...
Всё встаёт колом на одном месте без любых движений в какую либо сторону. iotop показывает скорость чтения под 60+ МБ, но в итоге всей системе наступает .опа.
Изменения любых параметров подсистемы vm.*
никак не влияли на итоговый результат.
Описание read-ahead (readahead)
Если короче говоря, простыми словами подытожить, то все эти фичи read-ahead и read-lookahead, -
- в пределах дорожки диска (секторов) с которой были запрошены данные, кроме фактически нужных данных ещё дополнительно последовательно (подряд) читает шо попало на случай а вдруг в хозяйстве пригодится (как одна поломанная лыжа на балконе);
- нужные данные вместе с readahead-шлаком складываются тебе в оперативку (в кеш-буфера), а когда она заканчивается, то весь тот высер передвигается тебе в своп;
- при чтении больших файлов, которые ещё могут быть разосраны разбросаны (aka non-contiguous) по по куче разных дорожек/секторов (участков диска), а также при больших значениях readahead в настройках диска, - объёмы лишних данных оперативка -> своп могут нарастать как снежный ком;
- аналогичная ситуация может произойти даже в случае, когда запрошенные данные расположены на одной дорожке, - это вовсе не означает, что программе кроме фактически запрошенных потребуются ещё и дополнительно считанные readahead данные;
- проблема особо ярко выражена, когда программа выполняется с неконтролируемой (нет настроек) многопоточностью (threads);
- финал выше изложенного думаю заранее известен: заканчивается РАМа, заканчивается своп, и наступает.., - ночь.
Вот, как-то так оно (упреждающее чтение) и работает:
- От пола до потолка засыпал мусором двухкомнатную квартиру канавин… - youtube
- В Перми начали уборку в квартире, заваленной до потолка мусором - youtube
Всё выше изложенное в равной степени применимо и к упреждающему чтению с файла подкачки (vm.page-cluster).
На мелких файлах read-ahead (readahead) может быть полезна, но при работе с большими файлами, - может превратится в страшнейший БАГ!
Это касается не только HDD, но и SSD дисков, где тормоза могут быть не такими лютыми, но принцип работы read-ahead (readahead) от этого не меняется!
Отключение read-ahead (readahead)
Отключение read-ahead (readahead) на уровне ОС:
sudo vi /etc/sysctl.conf ... vm.swappiness=0 vm.page-cluster=0 sudo sysctl -p
Отключение read-ahead (readahead) на уровне HDD:
# setting fs readahead to 0 sudo hdparm -a0 /dev/sda # setting drive read-lookahead to 0 (off) sudo hdparm -A0 /dev/sda # setting multcount to обычно 8 или 16 (по-умолчанию) sudo hdparm -m8 --yes-i-know-what-i-am-doing /dev/sda
Справедливости ради нужно отметить, что изначальное значение readahead в настройках HDD было подозрительно и неприлично велико (16384):
# sudo hdparm /dev/sda /dev/sda: multcount = 16 (on) IO_support = 1 (32-bit) readonly = 0 (off) readahead = 16384 (on) geometry = 60801/255/63, sectors = 976773168, start = 0
Т.е. 16384 секторов * 512 б (традиционный HDD sector size, диск 500 ГБ) / 1024 = 8192 кб - это 8 мб упреждающего чтения получилось?!
Возникает вопрос, как такое неприлично большое значение появилось в настройках HDD?
! Когда, после отключения попытка установить то же самое значение 16384 завершились ошибкой:
sudo hdparm -a16384 /dev/sda -a: bad/missing filesystem-read-ahead value (0..2048)
Возможно это результат работы старой версии hdparm, в которой не было такого лимита.
В текущей же версии программы hdparm значение для readahead допустимо в пределах 0-2048 сектора, что при 512 б разметке равно 1 МБ, что в условиях малого количества РАМы да при чтении больших файлов вероятно тоже многовато будет.
ОС манипулирует блоками: In practice, operating systems typically operate on blocks of data, which may span multiple sectors.[3]
Блочное ли устройство и размер блока можно узнать выполнив:
ls -l /dev/sda brw-rw---- 1 root disk 8, 0 сен 21 17:28 /dev/sda sudo blockdev --getbsz /dev/sda1 4096
Ещё раз подумав над вопросом: Так readahead и read-lookahead - это бага или всё же фича? Упреждающее чтение попробовали включить взад, но с малыми значениями:
# 8 КБ упреждающего чтения sudo hdparm -a16 /dev/sda # включаем взад read-lookahead sudo hdparm -A1 /dev/sda
А что с отключенным vm.page-cluster=0, какие там размер чтения linux swap page-cluster size? Ответ очевиден из документации ядра Линуха: в своп скидываются страницы РАМы, RAM page size которых можно проверить выполнив:
grep -ir pagesize /proc/self/smaps KernelPageSize: 4 kB MMUPageSize: 4 kB sudo getconf PAGESIZE 4096
Так и сделаем:
sudo sysctl -w vm.page-cluster=1
vm.page-cluster=1
будет читать по 2 страницы * 4 КБ = 8 КБ, что соразмерно с новыми настройками readahead=16
в нашем многострадальном HDD.
Бенчмарк
Никаких бенчмарк-прог не нужно, разницу можно заметить по так сказать органолептическим показателям.
После изменения значения read-ahead (readahead) с аномально высокого 16384 на 16, а vm.page-cluster=1
, при вычитке файла БД Беркли 80G стало возможным ещё и одновременная работа до 10 программ, среди которых браузер, текстовый редактор, почтовый клиент, ФМ, HDD заметно зажужжал и стал ощутимо греется.
В сравнении с тем, что было и что стало, - это космос, Аллилуйя!
Вот тебе и весь бенчмарк.
readahead - бага или фича
Ответ всегда зависит от того, с какой точки зрения смотреть на предмет
Важно не только чем, куда, когда, зачем и почему, но также важно ещё и как - это что-то происходит!
Факторов множество и от их параметров конфигурации зависит конечный результат, а также ответ на вопрос: Так readahead и read-lookahead - это бага или всё же фича?
Этот HDD диск нам Любі друзі підарілы
, с настройками которого очевидно ранее уже экспериментировали.
С прежними значениями readahead в 16384 секторов, при чтении 80-гигового файла БД readahead оказался лютым багом, но при изменении значения на 16 секторов (8 КБ) readahead превратился в полезную фичу.
Превращение readahead из бага в фичу заняло секунды времени, в отличии от времени потраченного на написание данного материала.
Выше изложенное в очередной раз подтверждает, что больше не всегда означает лучше.