
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 <taka@valinux.co.jp>
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}




