NVMe встречается в каждом сравнении хостингов и почти никогда не объясняется, из-за чего он стал означать «быстро» так же расплывчато, как «премиальное оборудование». Это не более быстрый сервер. Это протокол хранения с примерно десятой долей задержки на запрос по сравнению с SSD на SATA и очередями, рассчитанными на параллелизм, и он важен ровно настолько, насколько ваша нагрузка обращается к диску. Для шутера, упирающегося в CPU, это почти ноль. Для базы данных, коммитящей транзакции, или большого мира, записывающего сохранение каждые десять минут, или архива backup на 40 ГБ это разница между подтормаживанием, которого никто не замечает, и таким, которое стоит вам игроков. Эта статья о том, как отличить эти случаи.
Что такое NVMe на самом деле#
Путаница возникает оттого, что сравнивают не то. NVMe - это не тип флеш-памяти; микросхемы в диске NVMe и в SSD на SATA - одно и то же. Различие в том, как компьютер с ними разговаривает.
SSD на SATA использует AHCI - протокол, разработанный в 2004 году для механических дисков. В AHCI одна очередь команд глубиной 32, и он исходит из того, что дорогая часть запроса - это перемещение физического рычага. Канал SATA III на практике упирается примерно в 550 МБ/с.
NVMe спроектирован для флеш-памяти и подключается прямо к PCIe. Он поддерживает до 65 535 очередей по 65 536 команд, что кажется абсурдом, пока не вспомнишь, что флеш внутренне параллелен по десяткам микросхем, а AHCI никогда не мог загрузить их все. Диск PCIe 3.0 x4 даёт примерно 3 500 МБ/с; диск PCIe 4.0 x4 - примерно 7 000 МБ/с.
| HDD 7200 об/мин | SSD SATA | NVMe (PCIe 3.0) | |
|---|---|---|---|
| Последовательное чтение | 150-200 МБ/с | ~550 МБ/с | ~3 500 МБ/с |
| IOPS случайного чтения 4K | 100-200 | 80 000-100 000 | 300 000-1 000 000 |
| Типичная задержка запроса | 5-10 мс | 100-200 мкс | 20-100 мкс |
| Глубина очереди | 1 | 32 | практически неограниченна |
Строка про пропускную способность - та, которую цитирует маркетинг, и та, что важна меньше всего. Почти ничто из того, что делает игровой сервер, не является последовательным чтением на 3 ГБ. Важны последние две строки: сколько занимает один мелкий запрос и сколько их может выполняться одновременно. Именно там лежит разница на порядок, и поэтому нагрузка из тысяч мелких чтений и записей - а именно такие сохранение мира и коммит базы - ведёт себя совершенно иначе.
Хранилище - это ещё и не только диск. RE:NODE использует NVMe повсюду, на пуле ZFS, а такая файловая система, как ZFS, добавляет своё поведение: каждый блок получает контрольную сумму, так что скрытое повреждение обнаруживается, а не отдаётся; запись работает по принципу copy-on-write, так что при потере питания остаётся целостная файловая система, а не наполовину записанная; а кэш чтения в RAM означает, что горячий рабочий набор часто вообще не доходит до диска. Диск задаёт нижнюю границу; файловая система решает, как часто вы о неё ударяетесь.
Где игровой сервер обращается к диску#
В большем числе мест, чем принято думать, и всплесками, а не непрерывно.
Работа с диском на игровом сервере делится на семь задач с очень разными профилями:
- Сохранения мира. Периодические, и обычно хотя бы частично в главном потоке. Minecraft записывает изменённые чанки в файлы регионов (
region/r.0.0.mca, каждый содержит блок чанков 32x32); Valheim записывает один файл.dbна весь мир; Palworld и survival-игры на Unreal записывают большие блобы сохранений. Сохранение большого мира - это тысячи мелких записей или одна огромная, и то и другое упирается в диск. - Загрузка чанков и зон. Игрок, заходящий на неисследованную территорию, вызывает чтение с диска либо генерацию и последующую запись. Именно это даёт подтормаживание, когда кто-то летит через карту.
- Журналы. Непрерывные, мелкие, только дозапись. Дёшево, пока какой-нибудь плагин не начнёт логировать каждую постановку блока.
- Базы данных плагинов и модов. Файлы пользователей EssentialsX, журнал блоков CoreProtect, файл SQLite, который долбит каждое действие на сервере. Тихо это самая тяжёлая дисковая нагрузка на многих серверах Minecraft.
- Запуск. Чтение jar или бинарников игры, списка модов, плагинов и стартовых чанков. Серверу с модами приходится прочитать несколько гигабайт, прежде чем он примет подключение.
- Backup. Чтение всего мира и запись сжатого архива. Почти чистая работа с диском.
- Обновления и загрузки из Workshop. Большие последовательные записи плюс проверочные чтения.
Где NVMe заметен, по порядку#
| Операция | Что это | Что меняет NVMe |
|---|---|---|
| Периодическое сохранение мира | Тысячи мелких записей | Замирание становится короче, порой невидимым |
| Backup и восстановление | Прочитать всё, записать архив | Минуты превращаются в малую их долю |
| Запуск сервера | Большие последовательные и случайные чтения | Заметно быстрее на серверах с модами |
| Загрузка чанков при исследовании | Мелкие случайные чтения | Меньше подтормаживаний при движении игроков |
| Коммит базы данных | fsync на каждую транзакцию | Самая большая разница из всех |
| Записи SQLite плагинов | Постоянные мелкие синхронные записи | Убирает распространённую скрытую стоимость тика |
| Записи журнала | Мелкие дозаписи | Ничего заметного |
Случай с сохранением заслуживает подробностей, потому что именно его игроки чувствуют. Большинство игр сериализуют мир и записывают его, пока симуляция ждёт. На мире, выросшем до десятков гигабайт, эта запись - самый долгий одиночный блок цикла тика, и она происходит по таймеру, вечно. Valheim - чистый пример: весь мир - один файл, записываемый каждые -saveinterval секунд, и на зрелом мире пауза измерима. Сокращение интервала уменьшает то, что можно потерять при сбое, и увеличивает частоту, с которой вы платите паузой, а быстрое хранилище делает этот обмен дешёвым. Настройки сохранения разобраны в руководстве по Valheim.
Backup - вторая честная победа, и это почти чистая работа с диском. Ночное задание, читающее мир на 30 ГБ и записывающее сжатый архив, делает ровно ту работу, на которую рассчитано хранилище. На медленных дисках это задание пересекается с вечером, конкурирует с игрой и превращается в загадочный лаг, в котором все обвиняют хостера. На NVMe оно заканчивается, прежде чем кто-то заметит. Оно меняет и то число, которое действительно важно в аварии: не сколько шёл backup, а сколько занимает восстановление; см. резервные копии, которые действительно восстанавливаются и проверка восстановления до того, как оно понадобится.
Где он не меняет ничего#
Эту часть страницы хостингов опускают.
Tick rate на сервере, упирающемся в CPU. Если симуляция не может завершить шаг в отведённый бюджет, потому что симулировать слишком много, диск в этом не участвовал. Более быстрое хранилище ничего не меняет, а деньги лучше было бы потратить на тактовую частоту. Как понять, что у вас, помогает статья CPU или RAM.
Сетевая задержка. Игрок с 180 мс находится в 180 мс от сервера. У хранилища на это нет мнения.
Всё, что уже в памяти. Активный мир, список сущностей, состояние плагинов, куча JVM: между сохранениями ничто из этого не обращается к диску. Сервер с памятью, достаточной для его рабочего набора, читает с диска редко, и именно поэтому добавление памяти иногда исправляет то, что выглядит как проблема хранилища.
Установившаяся производительность небольшого сервера. Сервер Counter-Strike на статичной карте читает карту один раз и остаток вечера практически не выполняет дискового ввода-вывода. Хранилище в таком тарифе - просто место, где лежат файлы.
Плохая конфигурация. Плагин, делающий синхронный запрос к базе в главном потоке на каждом тике, медленный и на NVMe. Просто медленный чуть быстрее.
Базы данных - там, где он действительно доминирует#
Если вы запускаете базу данных - экземпляр Postgres или MongoDB, сервер FiveM с настоящим хранилищем, экономический плагин Minecraft с тысячами транзакций - задержка хранилища задаёт жёсткий потолок пропускной способности, а арифметика безжалостна.
Надёжная база вызывает fsync, прежде чем подтвердить коммит, потому что коммит, который есть только в page cache, - это обещание, которое она не выдержит при потере питания. Этот fsync - синхронный круговой путь до устройства, и одно соединение не может коммитить быстрее, чем по одному fsync за раз:
max commits per second, per connection = 1 / fsync latencyHDD, 8 ms fsync -> 125 commits/sSATA, 1 ms fsync -> 1,000 commits/sNVMe, 50 us fsync -> 20,000 commits/sЭто потолки, а не прогнозы, и реальные системы группируют коммиты от нескольких соединений и достигают большего. Но именно такая форма объясняет, почему приложение с интенсивной записью на медленном хранилище упирается в стену, которую не убирает никакая настройка запросов, и почему то же приложение на NVMe просто ничего не замечает. Настройки, связанные с этим, описаны в статье настройка PostgreSQL для небольших серверов, а вторая половина - сами запросы - в статье explain analyze для медленных запросов.
Производительность чтения важна иначе. Запрос, находящий данные в кэше, вообще не касается диска - потому shared_buffers и page cache операционной системы настраивают первыми. NVMe меняет то, что происходит при промахе кэша, а на рабочем наборе, превышающем память, это происходит большую часть времени. Тарифы хостинга баз данных рассчитаны с учётом этого, но общее правило верно везде: память убирает чтения, а быстрое хранилище делает дешёвыми те чтения, которые убрать нельзя.
Как измерить самостоятельно#
Не верьте листу спецификации и особенно не верьте dd.
# Misleading: writes through the page cache, measures RAM$ dd if=/dev/zero of=test bs=1M count=1024# Better, but still only sequential throughput$ dd if=/dev/zero of=test bs=1M count=1024 oflag=direct conv=fdatasyncПоследовательная пропускная способность - наименее значимое число. Вам нужны задержка и IOPS мелкого случайного ввода-вывода:
$ fio --name=randread --ioengine=libaio --direct=1 --rw=randread \ --bs=4k --iodepth=32 --numjobs=1 --size=1G --runtime=30 \ --time_based --group_reporting$ fio --name=syncwrite --ioengine=sync --fsync=1 --rw=write \ --bs=4k --size=256M --runtime=30 --time_basedПервый даёт IOPS случайного чтения и распределение задержек. Второй - тест fsync, и именно он предсказывает поведение базы данных. Читайте 99-й процентиль задержки, а не среднее: среднее говорит, как обычно себя ощущается, а хвост - как выглядит замирание.
Для быстрой проверки без установки чего-либо ioping -c 20 . печатает задержку по запросам в текущем каталоге. Для наблюдения за работающим сервером:
$ iostat -xz 1Смотрите r_await и w_await - среднее число миллисекунд ожидания запроса - и aqu-sz, среднюю глубину очереди. Игнорируйте %util на устройстве NVMe: он создавался для дисков с одной очередью и показывает 100 % на диске, который почти не работает, потому что измеряет, был ли в полёте хоть один запрос, а не насыщено ли устройство. Высокий %util при w_await 0,1 мс - это здоровый диск NVMe, а не узкое место.
На хостинге с панелью у вас не будет fio, а полезная замена - график диска рядом с графиками памяти и CPU. Пилообразный график диска, точно совпадающий с подтормаживаниями, о которых сообщают игроки, - это ваш ответ, а формы графиков разобраны в статье как читать график нагрузки сервера.
Место на диске - отдельный вопрос от скорости диска#
В тарифах указан размер диска, и все читают это как объём хранилища, каким оно и является, но это число влияет на производительность двумя способами, о которых стоит знать.
Работа почти на полном диске медленна. Флешу нужны свободные блоки для записи, и почти полный диск тратит время на перетасовку данных, чтобы освободить место. Файловым системам с copy-on-write, включая ZFS, для эффективной работы нужно свободное место. Держать заполнение ниже примерно 80 % - это настройка производительности, а не просто аккуратность.
Backup лежат в том же месте, если только не лежат отдельно. Встроенная функция резервного копирования игры пишет рядом с миром, а значит, мир на 30 ГБ с четырьмя хранимыми копиями требует 150 ГБ и защищает ровно от одного вида сбоя: повреждённого сохранения. Она ничего не делает против удалённого сервера или неудачного восстановления. Платформенные backup на RE:NODE копируются на отдельное оборудование, проверяются и по расписанию чистятся, а слоты резервных копий в панели хранятся вне машины, которую они защищают, - именно это свойство делает backup резервной копией, а не второй копией файла на том же диске.
Отсюда совет по выбору размера: выбирайте диск по миру, который ожидаете через год, плюс место для архивов, а не по тому, каков мир сегодня. Миры только растут, а предварительная генерация ограниченного мира - единственный приём, делающий этот рост предсказуемым.
FAQ#
Стоит ли переплачивать за NVMe?
Если это отдельная строка в счёте, сначала посмотрите на свою нагрузку. Он стоит своих денег для баз данных, для больших миров, которые часто сохраняются, и для всего, где часто делают backup. Он не стоит наценки для небольшого шутера или бота Discord, которые после запуска почти не трогают диск. На RE:NODE это не отдельная строка: каждый тариф на NVMe, включая самый дешёвый, потому что альтернатива - ложная экономия на оборудовании, составляющем малую часть затрат.
Исправит ли NVMe лаг моего сервера?
Только если лаг периодический и совпадает с сохранениями, backup или исследованием мира игроками. Лаг, который постоянен, растёт с числом сущностей и проявляется как высокое время тика при спокойном графике диска, - это проблема CPU, и хранилище её не тронет.
Ускорит ли NVMe запуск моего сервера?
Да, заметно, на всём с большим миром или длинным списком модов: такой запуск - это в основном чтение файлов. Ванильный сервер с маленьким миром стартует за несколько секунд на чём угодно, так что там разница не видна.
В чём разница между NVMe и SSD?
SSD - это флеш-хранилище; NVMe - протокол для работы с ним по PCIe. Большинство «SSD» в рекламе хостингов - это SSD на SATA с AHCI, протоколом 2004 года с одной неглубокой очередью. Те же микросхемы, но очень разные задержка и параллелизм.
Нужен ли NVMe для сервера Minecraft?
Он помогает больше, чем принято думать, потому что дисковая работа Minecraft - это мелкие случайные чтения и записи: загрузка чанков при исследовании, файлы регионов при сохранении и базы плагинов вроде CoreProtect, пишущие постоянно. Всё это не пропускная способность, а задержка, а именно её NVMe и меняет.
Может ли медленное хранилище вызывать низкий TPS?
Да, косвенно и с перебоями. Сохранение или синхронная запись плагина, блокирующие главный поток, тратят бюджет тика, что проявляется огромным максимальным временем тика при нормальном среднем. Этот узор - проблема хранилища, маскирующаяся под проблему CPU, а как отличить одно от другого, описано в статье что на самом деле означает tick rate.




Комментарии
Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.