igor@0: \section{Приоритезация ввода/вывода в Xen} igor@0: igor@0: \subsection{Приоритеты для использования Disk I/O} igor@0: \subsubsection{ionice} igor@5: С выходом CFQ v3 в Linux 2.6.13 появилась возможность выставлять приоритеты использования дисковой подсистемы для процессов, чего раньше так не хватало. Подобно утилите \textbf{nice}, предназначенной для назначения приоритетов использования процессора, появилась утилита \textbf{ionice}, назначает для процессов приоритеты ввода/вывода. igor@0: igor@0: Синтаксис команды прост: igor@0: igor@0: \begin{verbatim} igor@0: ionice -c класс -n приоритет -p PID igor@0: \end{verbatim} igor@0: igor@0: Класс: igor@0: igor@0: \begin{itemize} igor@5: \item 3 (Idle) — Получает приоритет на использование жесткого диска только когда другие программы ничего не пишут. Приоритеты не используются. igor@5: \item 2 (Best Effort) — Класс по умолчанию. Доступные приоритеты [0-7]. igor@5: \item 1 (Real Time) — Даёт преимущественный доступ к диску процессу, несмотря на другие процессы. Доступные приоритеты [0-7]. igor@0: \end{itemize} igor@0: igor@5: Подробнее: man ionice igor@5: igor@5: \subsubsection{Приоритеты ввода/вывода гостевых доменов Xen} igor@5: После запуска гостевых систем по \textbf{ps} \texttt{aux} можно видеть в квадратных скобках появившиеся драйвера блочных устройств xvd, после которых указан igor@0: ID гостевого домена. Приоритеты для этих процессов можно устанавливать igor@5: с помощью \textbf{ionice}, точно также как и для всех остальных. igor@5: igor@5: \begin{verbatim} igor@5: $ ps aux | grep xvd igor@5: root 616 0.0 0.0 0 0 ? S< 16:05 0:00 [xvd 1 07:00] igor@5: igor 773 0.0 0.0 3892 764 pts/0 R+ 16:08 0:00 grep xvd igor@5: \end{verbatim} igor@5: igor@5: Изменение приоритета ввода/вывода нужно выполнять для процесса 616. igor@5: igor@5: Аналогичным образом можно выполнять и приоритезацию igor@5: ввода/вывода для HVM-доменов, igor@5: только для этого нужно применять igor@5: \textbf{ionice} к процессам \textbf{qemu-dm}, igor@5: работающим в домене 0. igor@5: igor@5: \begin{verbatim} igor@5: $ ps aux | grep qemu-dm igor@5: root 645 8.3 0.1 27272 2400 ? Sl 16:05 0:09 /usr/lib/xen-3.2-1/bin/qemu-dm -d 2 -domain-name winxp-hdd ... igor@5: igor 769 0.0 0.0 3888 764 pts/0 R+ 16:07 0:00 grep qemu-dm igor@5: \end{verbatim} igor@0: igor@0: \subsubsection{Эксперименты} igor@5: Проведём 2 эксперимента для операций чтения и записи. igor@0: igor@0: Выставим одной гостевой системе класс \textit{Real Time}, а второй — \textit{Idle}. igor@0: igor@0: Запустим одновременно \textit{dd} на обеих системах для записи небольшого файла. Конечно слово «одновременно» здесь весьма условно. igor@0: Для повышения точности лучше провести несколько измерений. igor@0: igor@0: \begin{verbatim} igor@0: %# dd if=/dev/zero of=/root/file.txt bs=1024 count=10240000 igor@0: \end{verbatim} igor@0: igor@0: В результате средняя скорость в первой гостевой системе -- 40Mb/sec, во второй -- 20Mb/sec. igor@0: igor@0: Другим экспериментом является операция тестирования скорости чтения диска с помощью \textit{hdparm}: igor@0: igor@0: \begin{verbatim} igor@0: %# hdparm -t /dev/xvda igor@0: \end{verbatim} igor@0: igor@0: В результате в первом гостевом домене скорость — 25Mb/sec, во втором — 2Mb/sec. igor@0: igor@0: \subsubsection{Заключение} igor@0: Недостатком данного решения является отсутствие соответствующих опций в конфигурационном файле гостевых доменов Xen, igor@5: что означает, что при каждом старте домена необходимо устанавливать его приоритет заново. igor@0: igor@0: Следует обратить внимание, что данная возможность доступна только для CFQ. igor@0: igor@0: Проверьте, какой способ приоритезации используется: igor@0: igor@0: \begin{verbatim} igor@0: cat /sys/block/ИМЯ_ДИСКА/queue/scheduler igor@0: \end{verbatim} igor@0: igor@5: Название активного планировщика должно быть в квадратных скобках. igor@0: Например: igor@0: igor@0: \begin{verbatim} igor@0: $ cat /sys/block/sda/queue/scheduler igor@0: noop anticipatory deadline [cfq] igor@0: \end{verbatim} igor@0: igor@5: igor@5: \subsection{Приоритезация ввода/вывода с помощью dm-band} igor@5: igor@5: \textbf{dm-band} — драйвер операционной системы Linux, позволяющий управлять скоростью работы с блочными устройствами. Предназначен для использования в виртуализированной среде и с группами процессов (cgroups). В настоящее время dm-band работает как драйвер device-mapper. igor@5: igor@5: \subsubsection{Что такое dm-band} igor@5: \textbf{dm-band} — это контроллер, регулирующий полосу пропускания при выполнении операций ввода/вывода с блочным устройством, igor@5: реализованный как драйвер device-mapper. igor@5: Несколько работ, использующих одно физическое устройство, igor@5: должны делить между собой его полосу пропускания. igor@5: \textbf{dm-band} выделяет каждой работе полосу пропускания в соответствии igor@5: с её весом, который может задаваться административно. igor@5: igor@5: В настоящее время работой (job) может быть группа процессов с одинаковым igor@5: идентификатором pid, pgrp или uid. igor@5: В будущем планируется сделать поддержку cgroup. igor@5: Работой также может быть виртуальная машина Xen или KVM. igor@5: igor@5: \begin{verbatim} igor@5: # dmsetup message band1 0 weight 40 igor@5: # dmsetup message band2 0 weight 10 igor@5: \end{verbatim} igor@5: igor@5: \subsubsection{Как работает dm-band} igor@5: У каждого band-устройства есть как минимум одна его группа, igor@5: которая по умолчанию так и называется — default group. igor@5: igor@5: Band-групп у устройства может быть и несколько. igor@5: У каждой band-группы есть (1) вес и (2) закреплённая за ней работа. igor@5: \textbf{dm-band} выделяет маркеры группе пропорционально её весу. igor@5: igor@5: Если у группы есть в запасе маркеры, запрос ввода/вывода, сделанный igor@5: её работой, передаётся ниже. igor@5: Если же маркеров у группы не осталось, обращение блокируется. igor@5: Когда группа делает запрос ввода/вывода, она тратит один маркер. igor@5: Когда маркеры заканчиваются у всех групп, igor@5: работающих с данным устройством, \textbf{dm-band} пополняет их запас. igor@5: igor@5: При таком подходе работа, закреплённая за band-группой с большим весом, igor@5: гарантированно получит возможность сделать большее количество igor@5: запросов ввода/вывода. igor@5: igor@5: Полоса пропускания (bandwidth) в \textbf{dm-band} определяется igor@5: как отношение времени обработки маркеров данного устройства igor@5: к времени обработки маркеров всех устройств. igor@5: Время обработки маркера определяется длительностью цикла igor@5: ввода/вывода, включающим время поиска (seek latency), задержку igor@5: на обработку прерывания (interrupt latency) и прочее. igor@5: igor@5: \subsubsection{Как его использовать} igor@5: Ниже показано как управлять полосой пропускания при доступе igor@5: к дискам. В примере используется один диск с двумя разделами. igor@5: igor@5: Более подробная информация представлена в igor@5: документации на ядро Linux, в файле \texttt{Document/device-mapper/band.txt}. igor@5: igor@5: \paragraph{Создание и привязка band-устройств} igor@5: Нужно создать два band-устройства \texttt{band1} и \texttt{band2} и привязать их к разделам igor@5: \texttt{/dev/sda1} и \texttt{/dev/sda2} соответственно: igor@5: \begin{verbatim} igor@5: # dmsetup remove band1 igor@5: # dmsetup remove band2 igor@5: \end{verbatim} igor@5: igor@5: Если команды выполнятся успешно, igor@5: будут созданы новые файлы устройств \texttt{/dev/mapper/band1} и \texttt{/dev/mapper/band2}. igor@5: igor@5: \paragraph{Управление полосой пропускания} igor@5: Назначим \texttt{band1} и \texttt{band2} веса 40 и 10 соответственно: igor@5: igor@5: \begin{verbatim} igor@5: # dmsetup message band1 0 weight 40 igor@5: # dmsetup message band2 0 weight 10 igor@5: \end{verbatim} igor@5: igor@5: После этих команд \texttt{band1} сможет использовать 80\% — 40/(40+10)\(\ast{}\)100 — igor@5: полосы пропускания к физическому диску \texttt{/debv/sda}, igor@5: а \texttt{band2} — оставшиеся 20\%. igor@5: igor@5: \paragraph{Дополнительные возможности} igor@5: В этом примере будут созданы две дополнительные band-группы для \texttt{band1}. igor@5: В первую группу входят все процессы с user-id 1000, igor@5: а во вторую — процессы с user-id 2000. igor@5: Их веса соответственно 30 и 20. igor@5: igor@5: Сначала тип band-групп \texttt{band1} устанавливается равным \texttt{user}. igor@5: Затем группы с user-id 1000 и 2000 присоединяются к \texttt{band1}. igor@5: И последнее, назначаются веса для групп с user-id 1000 и 2000. igor@5: igor@5: \begin{verbatim} igor@5: # dmsetup message band1 0 type user igor@5: # dmsetup message band1 0 attach 1000 igor@5: # dmsetup message band1 0 attach 2000 igor@5: # dmsetup message band1 0 weight 1000:30 igor@5: # dmsetup message band1 0 weight 2000:20 igor@5: \end{verbatim} igor@5: igor@5: Теперь процессы в группе с user-id 1000 igor@5: могут использовать 30\% — 30/(30+20+40+10)\(\ast{}\)100 — igor@5: доступной физической полосы пропускания диска. igor@5: igor@5: \begin{verbatim} igor@5: Band Device Band Group Weight igor@5: band1 user id 1000 30 igor@5: band1 user id 2000 20 igor@5: band1 default group(the other users) 40 igor@5: band2 default group 10 igor@5: \end{verbatim} igor@5: igor@5: \paragraph{Удаление band-устройств} igor@5: Удалить band-устройства, которые больше не используются, igor@5: можно так: igor@5: igor@5: \begin{verbatim} igor@5: # dmsetup remove band1 igor@5: # dmsetup remove band2 igor@5: \end{verbatim} igor@5: igor@5: \subsubsection{Планы на будущее} igor@5: Что можно было бы сделать в будущих версиях: igor@5: \begin{itemize} igor@5: \item Добавить поддержку Cgroup; igor@5: \item Управлять скоростью записи и чтения по отдельности; igor@5: \item Добавить поддержку WRITE\_BARRIER; igor@5: \item Оптимизировать; igor@5: \item Добавить дополнительные инструменты для настройки (или хватит одного \textbf{dmsetup}?); igor@5: \item Создать новые политики планировщика BIOs (или достаточно уже существующей, весовой?). igor@5: \end{itemize} igor@5: igor@5: \subsubsection{Замеры} igor@5: Ниже представлены результаты замеров, которые выполнил разработчик \textbf{dm-band}, Ryo Tsuruta. igor@5: Они подтверждают то, что \textbf{dm-band} работает так, как и ожидалось. igor@5: В ходе экспериментов создаётся несколько band-групп на нескольких физических разделах igor@5: и выполняется интенсивный ввод/вывод на эти устройства. igor@5: igor@5: \paragraph{Железо для испытаний} igor@5: igor@5: \begin{verbatim} igor@5: DELL Dimention E521: igor@5: igor@5: Linux kappa.local.valinux.co.jp 2.6.23.14 #1 SMP igor@5: Thu Jan 24 17:24:59 JST 2008 i686 athlon i386 GNU/Linux igor@5: Detected 2004.217 MHz processor. igor@5: CPU0: AMD Athlon(tm) 64 X2 Dual Core Processor 3800+ stepping 02 igor@5: Memory: 966240k/981888k available (2102k kernel code, 14932k reserved, igor@5: 890k data, 216k init, 64384k highmem) igor@5: scsi 2:0:0:0: Direct-Access ATA ST3250620AS 3.AA PQ: 0 ANSI: 5 igor@5: sd 2:0:0:0: [sdb] 488397168 512-byte hardware sectors (250059 MB) igor@5: sd 2:0:0:0: [sdb] Write Protect is off igor@5: sd 2:0:0:0: [sdb] Mode Sense: 00 3a 00 00 igor@5: sd 2:0:0:0: [sdb] Write cache: enabled, read cache: enabled, igor@5: doesn't support DPO or FUA igor@5: sdb: sdb1 sdb2 < sdb5 sdb6 sdb7 sdb8 sdb9 sdb10 sdb11 sdb12 sdb13 sdb14 igor@5: sdb15 > igor@5: \end{verbatim} igor@5: igor@5: \paragraph{Результаты тестирования управления полосой пропускания для разделов} igor@5: Конфигурация для эксперимента \#1: igor@5: \begin{itemize} igor@5: \item Создать три раздела \texttt{sdb5}, \texttt{sdb6} и \texttt{sdb7}. igor@5: \item Назначить веса 40, 20 и 10 соответственно для \texttt{sdb5}, \texttt{sdb6} и \texttt{sdb7}. igor@5: \item Запустить 128 процессов, выполняющих одновременно случайные операции прямого чтения и прямой записи блоков размером 4KB igor@5: \item Подсчитать количество выполненных операций в течение 60 секунд. igor@5: \end{itemize} igor@5: igor@5: \begin{verbatim} igor@5: результат эксперимента #1 igor@5: --------------------------------------------------------------------------- igor@5: | device | sdb5 | sdb6 | sdb7 | igor@5: | weight | 40 (57.0%) | 20 (29.0%) | 10 (14.0%) | igor@5: |-----------------+-------------------+-------------------+-----------------| igor@5: | I/Os (r/w) | 6640( 3272/ 3368)| 3434( 1719/ 1715)| 1689( 857/ 832)| igor@5: | sectors (r/w) | 53120(26176/26944)| 27472(13752/13720)| 13512(6856/6656)| igor@5: | ratio to total | 56.4% | 29.2% | 14.4% | igor@5: --------------------------------------------------------------------------- igor@5: \end{verbatim} igor@5: igor@5: Конфигурация для эксперимента \#2: igor@5: \begin{itemize} igor@5: \item в точности такая же как для эксперимента \#1, за исключением того, что не запускаются процессы, работающие с \texttt{sdb6} igor@5: \end{itemize} igor@5: igor@5: \begin{verbatim} igor@5: результаты эксперимента #2 igor@5: --------------------------------------------------------------------------- igor@5: | device | sdb5 | sdb6 | sdb7 | igor@5: | weight | 40 (57.0%) | 20 (29.0%) | 10 (14.0%) | igor@5: |-----------------+-------------------+-------------------+-----------------| igor@5: | I/Os (r/w) | 9566(4815/ 4751)| 0( 0/ 0)| 2370(1198/1172)| igor@5: | sectors (r/w) | 76528(38520/38008)| 0( 0/ 0)| 18960(9584/9376)| igor@5: | ratio to total | 76.8% | 0.0% | 23.2% | igor@5: --------------------------------------------------------------------------- igor@5: \end{verbatim} igor@5: igor@5: \paragraph{Результаты тестирования управления полосой пропускания для band-групп} igor@5: Конфигурация для эксперимента \#3: igor@5: \begin{itemize} igor@5: \item Создать два раздела \texttt{sdb5} и \texttt{sdb6} igor@5: \item Создать две дополнительные band-группы на \texttt{sdb5}, первая для \texttt{user1} и вторая для \texttt{user2}. igor@5: \item Назначить веса 40, 20, 10 и 10 для band-групп \texttt{user1}, \texttt{user2}, default-групп разделов \texttt{sdb5} и \texttt{sdb6} соответственно igor@5: \item Запустить 128 процессов, выполняющих одновременно случайные операции прямого чтения и прямой записи блоков размером 4KB igor@5: \item Подсчитать количество выполненных операций в течение 60 секунд. igor@5: \end{itemize} igor@5: igor@5: \begin{verbatim} igor@5: результаты эксперимента #3 igor@5: --------------------------------------------------------------------------- igor@5: |dev| sdb5 | sdb6 | igor@5: |---+------------------------------------------------------+----------------| igor@5: |usr| user1 | user2 | other users | all users | igor@5: |wgt| 40 (50.0%) | 20 (25.0%) | 10 (12.5%) | 10 (12.5%) | igor@5: |---+------------------+------------------+----------------+----------------| igor@5: |I/O| 5951( 2940/ 3011)| 3068( 1574/ 1494)| 1663( 828/ 835)| 1663( 810/ 853)| igor@5: |sec|47608(23520/24088)|24544(12592/11952)|13304(6624/6680)|13304(6480/6824)| igor@5: | % | 48.2% | 24.9% | 13.5% | 13.5% | igor@5: --------------------------------------------------------------------------- igor@5: \end{verbatim} igor@5: igor@5: Конфигурация для эксперимента \#4: igor@5: \begin{itemize} igor@5: \item в точности такая же как для эксперимента \#3, за исключением того, что не запускаются процессы, работающие с band-группой \texttt{user2} igor@5: \end{itemize} igor@5: igor@5: \begin{verbatim} igor@5: результаты эксперимента #4 igor@5: --------------------------------------------------------------------------- igor@5: |dev| sdb5 | sdb6 | igor@5: |---+------------------------------------------------------+----------------| igor@5: |usr| user1 | user2 | other users | all users | igor@5: |wgt| 40 (50.0%) | 20 (25.0%) | 10 (12.5%) | 10 (12.5%) | igor@5: |---+------------------+------------------+----------------+----------------| igor@5: |I/O| 8002( 3963/ 4039)| 0( 0/ 0)| 2056(1021/1035)| 2008( 998/1010)| igor@5: |sec|64016(31704/32312)| 0( 0/ 0)|16448(8168/8280)|16064(7984/8080)| igor@5: | % | 66.3% | 0.0% | 17.0% | 16.6% | igor@5: --------------------------------------------------------------------------- igor@5: \end{verbatim} igor@5: igor@5: \paragraph{Выводы} igor@5: \textbf{dm-band} работает хорошо при выполнении случайных операций чтение/запись. igor@5: В будущем планируется провести тестирование на igor@5: реальных приложениях, таких как СУБД и файловые серверы. igor@5: igor@5: \subsubsection{Почему нельзя было просто доработать CFQ?} igor@5: В Linux есть механизмы для приоритезации дискового ввода/вывода. igor@5: Почему нельзя было использовать их? igor@5: igor@5: Ниже перевод письма одного из соавторов dm-band Хироказу Такаши (Hirokazu Takashi) igor@5: в список рассылки Xen-devel\url{http://lists.xensource.com/archives/html/xen-devel/2008-01/msg00852.html}, igor@5: в котором он отвечает на этот вопрос. igor@5: igor@5: \begin{verbatim} igor@5: From: Hirokazu Takahashi igor@5: igor@5: Доработать стандартный планировщик ввода/вывода, который есть в ядре, igor@5: это самый простой подход. Действительно, планировщик CFQ igor@5: можно было бы научить управлять полосой пропускания путём igor@5: относительного небольшой модификации кода. igor@5: Оба подхода (использовать device-mapper и модифицировать CFQ) igor@5: имеют свои плюсы и минусы. igor@5: igor@5: В настоящее время мы выбрали вариант с device-mapper по следующим причинам: igor@5: * он может работать с любым планировщиком. Некоторые хотят использовать планировщик NOOP igor@5: для работы с high-end хранилищами; igor@5: * его должны использовать только те, кому нужно управление пропускной способностью I/O; igor@5: * он независим от других планировщиков и его легко поддерживать; igor@5: * не усложняется сопровождение CFQ. igor@5: igor@5: У сегодняшней реализации планировщика CFQ есть некоторые ограничения, igor@5: которые мешают использовать его для управления полосой пропускания так, igor@5: как хотелось бы. У планировщика есть только 7 уровней приоритета, igor@5: что означает, что у него есть только 7 классов ввода/вывода. igor@5: Если назначить один и тот же приоритет A нескольким виртуальным машинам, igor@5: эти машины должны будут поровну делить полосу ввода/вывода, igor@5: выделенную классу A. Если при этом есть машина, работающая с приоритетом B, igor@5: более низким чем A, и она такая одна, может так получится, что у неё будет igor@5: большая полоса пропускания чем у машин класса A. igor@5: igor@5: Вообще, я думаю, что нужно чтобы в CFQ был планировщик с двумя уровнями. igor@5: Один уровень используется для выбора лучшей группы cgroup или работы (job), igor@5: а второй — для выбора класса с наивысшим приоритетом ввода/вывода. igor@5: igor@5: Второй минус подхода с использованием существующего планировщика в том, igor@5: что у него приоритеты ввода/вывода глобальны, igor@5: и они распространяются на все диски, к которым осуществляется доступ. igor@5: Нельзя сделать так, чтобы у задачи были разные приоритеты при доступе к разным дискам. igor@5: igor@5: У подхода с использованием device-mapper тоже есть свои минусы. igor@5: Сложно получить информацию о возможностях и конфигурации нижележащих устройств, igor@5: такую, например, как информацию о разделах и LUN. И возможно, потребуется разрабатывать igor@5: дополнительные инструменты для настойки. igor@5: \end{verbatim} igor@5: igor@0: \subsection{Дополнительная информация} igor@0: \begin{itemize} igor@5: \item \htmladdnormallinkfoot{Приоритезация ввода/вывода в Xen с помощью планировщика CFQ}{http://xgu.ru/wiki/xen/io} (рус.) igor@5: \item \htmladdnormallinkfoot{Приоритезация ввода/вывода с помощью dm-band}{http://xgu.ru/wiki/dm-band} (рус.) igor@0: \end{itemize}