[Документация Yandex Cloud](../../index.md) > [Yandex Compute Cloud](../index.md) > [Концепции](index.md) > Диски и файловые хранилища > Операции чтения и записи

# Операции чтения и записи

Для [дисков](disk.md) и [файловых хранилищ](filesystem.md) действуют технические ограничения на операции чтения и записи. Ограничения относятся как к целым диску или хранилищу, так и к каждой отдельной единице выделения дискового пространства — блоку размещения (allocation unit). Величина блока размещения зависит от [типа диска или хранилища](limits.md#compute-limits-disks).

Операции чтения и записи имеют предельные возможные значения по следующим параметрам:
* Максимальное значение IOPS — максимальное количество операций чтения и записи в секунду.
* Максимальная пропускная способность (bandwidth) — суммарное количество байт, которые можно прочитать или записать в секунду.

Фактическое значение IOPS зависит как от характеристик диска или хранилища, так и от совокупного значения пропускной способности и размера запроса в байтах. Обеспечиваемый IOPS определяется по формуле:

![image](../../_assets/compute/iops.svg)

Где:
* _Макс. IOPS_ — [максимальное значение IOPS](limits.md#limits-disks) для диска или хранилища.
* _Макс. bandwidth_ — [максимальное значение пропускной способности](limits.md#limits-disks) для диска или хранилища.

Операции чтения и записи потребляют один и тот же дисковый ресурс — чем больше производится операций чтения, тем меньше операций записи, и наоборот. Суммарное количество операций и чтения, и записи в секунду определяется по формуле:

![image](../../_assets/compute/max-iops.svg)

Где:
* ![image](../../_assets/compute/alpha.svg) — доля операций записи из общего количества операций чтения и записи, выполняемых в секунду. Возможные значения — &alpha;&isin;[0,1].
* _WriteIOPS_ — значение IOPS на запись, полученное по формуле расчета фактического значения IOPS.
* _ReadIOPS_ — значение IOPS на чтение, полученное по формуле расчета фактического значения IOPS.

Подробнее про максимально допустимые значения IOPS и пропускной способности читайте в разделе [Квоты и лимиты](limits.md#limits-disks).

{% note warning %}

На ВМ с [уровнем производительности vCPU](performance-levels.md) меньше 100% скорость работы с сетевыми дисками может быть ниже.

Сервисные ядра сетевых дисков [не зависят](../../vpc/concepts/software-accelerated-network.md#reg-vm) от параметров ВМ, но снижение уровня производительности vCPU напрямую влияет на скорость чтения и записи на диски.

{% endnote %}


## Производительность дисков и файловых хранилищ {#performance}

Производительность работы ВМ с дисками определяется одновременно двумя группами лимитов:
* [Лимиты ВМ на работу с дисками](limits.md#compute-limits-vm-disks) — задают потолок суммарной нагрузки на все диски ВМ. Эти лимиты масштабируются пропорционально количеству vCPU ВМ.
* [Лимиты дисков и файловых хранилищ](limits.md#compute-limits-disks) — задают потолок нагрузки на отдельный диск и зависят от его типа и размера.

Фактическая производительность диска ограничена меньшим из двух значений.

Максимальные значения IOPS достигаются на операциях чтения и записи размером 4 КБ. Сетевые SSD-диски и файловые хранилища предоставляют существенно большие значения IOPS на чтение, а также меньшие значения времени обработки запроса.

Чтобы получить максимальные значения пропускной способности, рекомендуется делать операции чтения и записи размером 4 МБ.

Производительность диска или хранилища зависит от его объема — чем выше количество блоков размещения, тем выше значения IOPS и пропускной способности.

Для HDD-дисков небольшого размера предусмотрен механизм увеличения характеристик до уровня дисков размером 1 ТБ на период повышенной нагрузки. Работая на [базовом уровне производительности](limits.md#compute-limits-disks) в течение 12 часов, небольшой диск накапливает «кредиты на операции», которые будут потрачены автоматически при увеличении нагрузки (например, при старте ВМ). Небольшие HDD-диски могут работать с увеличенными характеристиками около 30 минут в день. «Кредиты на операции» могут быть потрачены как за один раз, так и небольшими промежутками. Для HDD-хранилищ механизм не предусмотрен.

### Тестирование производительности дисков {#test-performance}

Для тестирования производительности сетевых дисков можно воспользоваться утилитой [fio](https://fio.readthedocs.io/en/latest/fio_doc.html):

1. [Подключите](../operations/vm-control/vm-attach-disk.md) диск к ВМ.
1. Установите утилиту [fio](https://fio.readthedocs.io/en/latest/fio_doc.html) на ВМ:

    Пример команды для ОС Ubuntu:

    ```bash
    sudo apt-get update && sudo apt-get install fio -y
    ```

1. Запустите утилиту `fio` и выполните сценарий:

    ```bash
    sudo fio \
    --name=<имя_задачи>
    --filename=<путь_к_точке_монтирования>/testfile.bin \
    --filesize=1G \
    --direct=1 \
    --rw=write \
    --bs=4k \
    --ioengine=libaio \
    --iodepth=64 \
    --runtime=120 \
    --numjobs=8 \
    --time_based \
    --group_reporting \
    --eta-newline=1
    ```

    Где:

    * `--name` — произвольное имя задания.
    * `--filename` — путь к точке монтирования того диска, производительность которого вы хотите протестировать.

        {% note alert %}

        При тестировании операций записи не используйте идентификатор диска (например, `/dev/vdb`) в качестве значения для параметра `--filename`. Все данные на диске могут быть потеряны.

        {% endnote %}

    * `--filesize` — размер файла, который создается утилитой и используется для тестирования ввода-вывода.
    * `--direct` — использование буферизации, где `0` — использовать, `1` — не использовать.
    * `--rw` — шаблон нагрузки. Возможные значения: 
      * `read` — последовательное чтение;
      * `write` — последовательная запись;
      * `rw` — последовательные чтения/записи;
      * `randrw` — случайные чтение/запись;
      * `randwrite` — случайная запись;
      * `randread` — случайное чтение.
    * `--bs` — размер блока чтения/записи:
      * чтобы получить лучший результат по количеству операций чтения и записи в секунду (IOPS), укажите значение меньшее или равное размеру блока диска;
      * чтобы получить лучший результат по пропускной способности (bandwidth), укажите значение 4 МБ (`4M`).
    * `--ioengine` — определение порядка ввода-вывода теста в файл. При передаче значения `libaio` будет использован асинхронный ввод-вывод Linux, который позволяет выполнять несколько операций параллельно, без блокирования. Подробности о возможных вариантах ввода-вывода читайте в [документации утилиты fio](https://fio.readthedocs.io/en/latest/fio_doc.html#i-o-engine).
    * `--iodepth` — глубина блоков io на каждое задание (`job`).
    * `--runtime` — длительность тестирования, в секундах.
    * `--numjobs` — количество заданий чтения/записи.
    * `--time_based` — привязка длительности теста к значению параметра `runtime`. Если флаг активен, тест будет продолжать выполняться даже в случае, если чтение или запись данных были завершены.
    * `--group_reporting` — включение группировки статистики по каждому из заданий.
    * `--eta-newline` — включает принудительный перенос строки каждый раз, когда проходит указанный период времени. Период указывается в секундах.

### Примеры сценариев {#test-examples}

#### Тестирование IOPS, последовательная запись {#iops-write-example}

```bash
sudo fio \
--name=readio \
--filename=<путь_к_точке_монтирования>/testfile.bin \
--filesize=1G \
--direct=1 \
--rw=write \
--bs=4k \
--ioengine=libaio \
--iodepth=96 \
--runtime=120 \
--numjobs=4 \
--time_based \
--group_reporting \
--eta-newline=1
```

Результат:

```yaml
---
  write: IOPS=39.7k, BW=155MiB/s (162MB/s)(5112MiB/33001msec); 0 zone resets
    slat (usec): min=2, max=19776, avg= 5.25, stdev=47.15
    clat (usec): min=874, max=5035.1k, avg=9677.38, stdev=40976.63
     lat (usec): min=889, max=5035.1k, avg=9682.81, stdev=40976.66
---
```

#### Тестирование IOPS, случайная запись {#iops-random-write-example}

```bash
sudo fio \
--name=randwrite \
--filename=<путь_к_точке_монтирования>/testfile.bin \
--filesize=1G \
--direct=1 \
--rw=randwrite \
--bs=4k \
--ioengine=libaio \
--iodepth=96 \
--runtime=120 \
--numjobs=1 \
--time_based \
--group_reporting \
--eta-newline=1
```

Результат:

```yaml
---
write: IOPS=9596, BW=37.5MiB/s (39.3MB/s)(4499MiB/120011msec); 0 zone resets
    slat (usec): min=2, max=338, avg= 5.21, stdev= 4.52
    clat (usec): min=680, max=161320, avg=9996.54, stdev=10695.67
     lat (usec): min=698, max=161323, avg=10001.94, stdev=10695.77
---
```

#### Тестирование пропускной способности, последовательная запись {#bandwidth-write-example}

```bash
sudo fio \
--name=writebw \
--filename=<путь_к_точке_монтирования>/testfile.bin \
--filesize=1G \
--direct=1 \
--rw=write \
--bs=4M \
--ioengine=libaio \
--iodepth=32 \
--runtime=120 \
--numjobs=1 \
--time_based \
--group_reporting \
--eta-newline=1
```

Результат:

```yaml
---
   write: IOPS=112, BW=449MiB/s (471MB/s)(52.8GiB/120237msec); 0 zone resets
    slat (usec): min=166, max=270963, avg=8814.82, stdev=10995.16
    clat (msec): min=58, max=661, avg=276.06, stdev=28.21
     lat (msec): min=60, max=679, avg=284.88, stdev=27.91
---
```

#### Тестирование IOPS, последовательное чтение {#iops-read-example}

```bash
sudo fio \
--name=readio \
--filename=<путь_к_точке_монтирования>/testfile.bin \
--filesize=1G \
--direct=1 \
--rw=read \
--bs=4k \
--ioengine=libaio \
--iodepth=128 \
--runtime=120 \
--numjobs=8 \
--time_based \
--group_reporting \
--eta-newline=1
```

Результат:

```yaml
---
  read: IOPS=62.2k, BW=243MiB/s (255MB/s)(28.5GiB/120008msec)
    slat (usec): min=2, max=123901, avg= 6.88, stdev=151.96
    clat (usec): min=859, max=168609, avg=16450.99, stdev=8226.23
     lat (usec): min=877, max=168611, avg=16458.07, stdev=8229.16
---
```

#### Тестирование пропускной способности на чтение {#bandwidth-read-example}

```bash
sudo fio \
--name=readbw \
--filename=<путь_к_точке_монтирования>/testfile.bin \
--filesize=1G \
--direct=1 \
--rw=read \
--bs=4M \
--ioengine=libaio \
--iodepth=32 \
--runtime=120 \
--numjobs=1 \
--time_based \
--group_reporting \
--eta-newline=1
```

Результат:

```yaml
---
  read: IOPS=112, BW=449MiB/s (470MB/s)(52.7GiB/120227msec)
    slat (usec): min=85, max=177850, avg=8878.47, stdev=9824.19
    clat (msec): min=50, max=4898, avg=276.36, stdev=45.16
     lat (msec): min=52, max=4898, avg=285.24, stdev=44.94
---
```

#### Тестирование IOPS, случайное чтение {#iops-random-read-example}

```bash
sudo fio \
--name=randread \
--filename=<путь_к_точке_монтирования>/testfile.bin \
--filesize=1G \
--direct=1 \
--rw=randread \
--bs=4k \
--ioengine=libaio \
--iodepth=16 \
--runtime=120 \
--numjobs=8 \
--time_based \
--group_reporting \
--eta-newline=1
```

Результат:

```yaml
---
 read: IOPS=17.0k, BW=66.4MiB/s (69.6MB/s)(7966MiB/120006msec)
    slat (usec): min=2, max=114, avg= 9.05, stdev= 5.36
    clat (usec): min=172, max=251507, avg=7519.93, stdev=6463.84
     lat (usec): min=179, max=251511, avg=7529.25, stdev=6464.41
---
```

### Троттлинг {#throttling}

Если в какой-то промежуток времени ВМ не укладывается в [дисковые лимиты](limits.md#compute-limits-disks), срабатывает троттлинг.

_Троттлинг_ — это принудительное ограничение быстродействия. При срабатывании троттлинга дисковые операции откладываются. В этот момент повышается показатель ожидания выполнения дисковых операций — `iowait`. Процессы, которые обеспечивают работу [сетевых дисков](disk.md), отделены от пользовательской нагрузки и выполняются на вычислительных ядрах из [отдельного пула](software-accelerated-network.md#reg-vm) — сервисных ядрах. При сильной нагрузке на системные диски могут наблюдаться сетевые проблемы. Это возможно как с виртуальной машиной, так и с любым физическим сервером.

> Например, лимит 300 IOPS на запись. Лимит разбивается на 10 частей и отрабатывает раз в 100 мс. Таким образом, будет разрешено сделать 300 / 10 = 30 IOPS на запись в 100 мс. Если разово отправить 30 запросов и затем в течение 100 мс еще 30 запросов (равномерно распределив их по интервалу в 100 мс), сработает троттлинг и отправятся только первые 30. Остальные попадут в очередь и будут обработаны в следующие 100 мс. Если запись производить скачкообразно, троттлинг может создавать довольно большие задержки. В некоторые моменты на диске будет до N IOPS запросов за 100 мс.

Производительность диска зависит от его [объема](disk.md#maximum-disk-size). Для повышения общего быстродействия дисковой подсистемы используйте ВМ с сетевыми SSD-дисками (`network-ssd`). С каждым шагом в 32 ГБ увеличивается количество блоков размещения и, соответственно, быстродействие.

Выбрать тип накопителя можно только при создании ВМ. Однако вы можете [сделать снимок](../operations/disk-control/create-snapshot.md) диска и [создать новую ВМ](../operations/vm-create/create-from-snapshots.md) из этого снимка с `network-ssd`.

### Влияние дисковой нагрузки на сеть ВМ {#disk-load-network-impact}

Без [программно ускоренной сети](software-accelerated-network.md) пользовательская нагрузка и обработка сетевого трафика ВМ распределяются по [одним и тем же вычислительным ядрам](software-accelerated-network.md#reg-vm), выделенным виртуальной машине. При высокой нагрузке на диски ВМ, например при создании [снимков](snapshot.md) или [резервном копировании](backups.md) больших дисков, пользовательские процессы могут потреблять значительную долю ресурсов vCPU. Из-за этого у процессов обработки сетевого трафика остается меньше вычислительных ресурсов, и возможны кратковременные сетевые проблемы: возросшие задержки или потери пакетов. Такое поведение характерно не только для виртуальных машин, но и для любого физического сервера с высокой одновременной нагрузкой на диски и сеть.

{% note tip %}

Чтобы снизить влияние дисковой нагрузки на сеть ВМ, используйте один из подходов:
* Снижайте интенсивность операций резервного копирования и других задач, которые создают пиковую нагрузку на диски.
* Включите для ВМ [программно ускоренную сеть](software-accelerated-network.md) — обработка сетевого трафика будет вынесена на отдельные вычислительные ядра и перестанет конкурировать с пользовательской нагрузкой.

{% endnote %}