Read Look-Ahead и read-ahead (readahead) - это баг или фича

archive view archive save

Кто бы мог подумать, что Read Look-Ahead и read-ahead (readahead) могут оказаться страшнейшим багом, а не фичей! Баг сей ярко выражен в жутком свопинге, когда выполняется чтение больших файлов, в результате которого всё встаёт колом на одном месте без движений в какую либо сторону.

Днями ранее мы писали про проблему со скачиванием большого файла БД Беркли размером 80G, когда FileZilla вместо 80G накачало целых 83G и качало бы дальше ели бы её принудительно не остановили (перекачивали заново wget-ом).

Так вот, пробовали мы этот файл БД Беркли 80G как-то читать...

Всё встаёт колом на одном месте без любых движений в какую либо сторону. iotop показывает скорость чтения под 60+ МБ, но в итоге всей системе наступает .опа.

Изменения любых параметров подсистемы vm.* никак не влияли на итоговый результат.

  1. Описание read-ahead (readahead)
  2. Отключение read-ahead (readahead)
  3. Бенчмарк
  4. readahead - бага или фича

Описание read-ahead (readahead)

Если короче говоря, простыми словами подытожить, то все эти фичи read-ahead и read-lookahead, -

  • в пределах дорожки диска (секторов) с которой были запрошены данные, кроме фактически нужных данных ещё дополнительно последовательно (подряд) читает шо попало на случай а вдруг в хозяйстве пригодится (как одна поломанная лыжа на балконе);
  • нужные данные вместе с readahead-шлаком складываются тебе в оперативку (в кеш-буфера), а когда она заканчивается, то весь тот высер передвигается тебе в своп;
  • при чтении больших файлов, которые ещё могут быть разосраны разбросаны (aka non-contiguous) по по куче разных дорожек/секторов (участков диска), а также при больших значениях readahead в настройках диска, - объёмы лишних данных оперативка -> своп могут нарастать как снежный ком;
  • аналогичная ситуация может произойти даже в случае, когда запрошенные данные расположены на одной дорожке, - это вовсе не означает, что программе кроме фактически запрошенных потребуются ещё и дополнительно считанные readahead данные;
  • проблема особо ярко выражена, когда программа выполняется с неконтролируемой (нет настроек) многопоточностью (threads);
  • финал выше изложенного думаю заранее известен: заканчивается РАМа, заканчивается своп, и наступает.., - ночь.

Вот, как-то так оно (упреждающее чтение) и работает:

Всё выше изложенное в равной степени применимо и к упреждающему чтению с файла подкачки (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 из бага в фичу заняло секунды времени, в отличии от времени потраченного на написание данного материала.

Выше изложенное в очередной раз подтверждает, что больше не всегда означает лучше.


Комментарии в блоге
Новое на форуме