- PVSM.RU - https://www.pvsm.ru -

HDD посвящается: усмиряем приложение, прожорливое на дисковое время

Корень всех зол

Долгое время у меня была проблема — система очень сильно тормозила после старта. У меня ноутбук с жёстким диском (HDD) и Ubuntu 14.04.
Как выяснилось, причина крылась в одной лишь программе — демоне Dropbox. Dropbox — это онлайновое файловое хранилище, а его демон — программка, синхронизирующая файлы, расположенные в определённой папке, с онлайн-хранилищем. На старте демон начинает считывать свой кэш. У меня он занимает не одну сотню мегабайт, а удалять его вручную не стоит — есть вероятность потерять данные. Учитывая, что у меня жёсткий диск — устройство с механическими частями — демон начинал потреблять время доступа к нему настолько, что пользоваться компьютером и запускать приложения становилось малореально, пока он не прогрузится. Убрать его из автозапуска и запускать вручную? Неприятное решение, у меня и так есть вещи, которые я на старте вынужден запускать сам (например, iotop, он без прав суперпользователя не запускается). Нужно было найти способ сделать приложение менее прожорливым именно на диск.

ionice нам в помощь. Или нет?

Первое, о чём я услышал по этой теме, была утилитка ionice. Она позволяет изменять приоритет доступа к диску для заданного процесса. Согласно мануалу [1], существуют три класса приоритетности ввода/вывода. Меня интересовал idle, поскольку он, как я понял из описания, нейтрализует прожорливость приложения, пропуская всегда вперёд него процессы других классов приоритета. Казалось, дело в шляпе, и всё, что надо сделать, это:

ionice -c3 -p $(pgrep dropbox)

Сделано. Эффекта — ноль. Как же так? Ладно, роем дальше.

Scheduler'ы, или «я ничего не понял, но звучит круто»

Как выяснилось [2], по умолчанию ionice на моей системе вообще не функционирует, поскольку должен быть включён планировщик CFQ [3]. А по умолчанию в новых Убунтах включён планировщик deadline [4]. Не стану вдаваться в подробности, чем они отличаются, ибо сам не до конца въехал. В общем, читаю краткое пояснение по этому делу [5], а потом меняю планировщик командой (вернее, я добавил эту команду в /etc/rc.local, чтобы планировщик GFQ выставлялся на старте автоматически):

echo cfq > /sys/block/sda/queue/scheduler

Заметка

Кстати, в разделе «замечания» мануала [1] отмечено, что поддержка классов и приоритетов работает на CFQ. Но поскольку до туда всё равно никто не дочитывает… XD

Что-то в системе слегка изменилось. Индикатор load при старте системы стал подниматься выше 11, а процессорная нагрузка стала состоять по большей части из wait. Не уверен, что это всё значит в долгосрочной перспективе, но проблема осталась — переключение на CFQ и последующее применение ionice на процесс dropbox на производительность системы на старте никакого заметного эффекта не произвело: ни положительного, ни отрицательного.

Ну кто столько потоков запускает?! О специфике демона Dropbox.

Я уж было разочаровался, но тут я заметил, что в top показан только один процесс dropbox, а iotop показывает несколько. И кстати, почему в top колонка идентификаторов процессов называется PID, а в iotop — TID? В чём разница между ними? Ответ быстро нашёлся [6]. В моём же случае самое важное открытие: демон Dropbox для своих дел запускает несколько потоков. Много потоков. Выяснилось, что не один десяток. И диск начинают читать иногда по нескольку одновременно. Так вот откуда такие тормоза! А ionice не работал потому, что, присвоив класс приоритета основному процессу, он не передаёт этот класс приоритета дочерним потокам. Поэтому они как были со стандартным классом приоритета, так с ним и остались.
Что ж, как говорят британцы, будем применять bodging [7]. По-нашему, «костыли». Сделаем скриптик, который будет засекать процесс dropbox и все его дочерние потоки, брать их идентификаторы (PID или TID, в данном случае ionice'у это изофаллично до лампочки без особой разницы), и присваивать всем класс idle время от времени (на случай, если dropbox убивает часть дочерних потоков и/или создаёт новые).

#!/bin/bash

while true
do
	#собираем список дочерних потоков
	TIDS=( $(ps -L --pid $(pgrep -x dropbox) -o tid=) )

	for i in "${TIDS[@]}"
	do
		echo $i
		#присваиваем приоритет idle
		ionice -c3 -p $i
	done

	sleep 5

done

Добавляем в автозапуск, перезагружаемся.
И всё заработало почти как будто демона Dropbox вообще нету. Эврика!

Итоги
Таким образом можно работать с любым процессом, потребляющим много дискового времени. Достаточно задать приоритет с помощью ionice и не забывать о подводных камнях, в частности:

  • следить, не запускает ли процесс прожорливые дочерние потоки
  • иметь в виду, что на некоторых системах планировщик ввода/вывода по умолчанию — не CFQ (который поддерживает классы и приоритеты)

Какие ещё вещи следует учитывать? Расскажите о своём опыте в комментариях.

Автор: Highstaker

Источник [8]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/linux/119729

Ссылки в тексте:

[1] мануалу: http://xgu.ru/wiki/man:ionice

[2] выяснилось: http://serverfault.com/a/602384/173515

[3] CFQ: https://en.wikipedia.org/wiki/CFQ

[4] deadline: https://en.wikipedia.org/wiki/Deadline_scheduler

[5] краткое пояснение по этому делу: https://stackoverflow.com/questions/1009577/selecting-a-linux-i-o-scheduler

[6] Ответ быстро нашёлся: http://stackoverflow.com/a/8787888/2052138

[7] bodging: https://www.youtube.com/watch?v=lIFE7h3m40U

[8] Источник: https://habrahabr.ru/post/282828/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best