Все врут: эпопея с NVMe-серверами и Hi-CPU
У нас, в RUVDS не хватало в линейке NVMe-сервера, чтобы побыстрее и помощнее. Потому что в последний год пошла мода разворачивать на таких Битрикс и 1С. Спрос на услугу есть, у других хостингов она тоже есть и заказывается — в общем, всё шло к тому, что надо просто выбрать конфигурацию и конкретные варианты железа и закупиться во все 11 локаций по миру. А тут надо сказать, что мы поддерживаем сейчас только две конфигурации: побыстрее и помедленнее. Потому что ЗИП, потому что поддержка, потому что софт и так далее — это одна из частей политики адекватных цен. То есть добавится третья, и поменять там что-то можно будет года так через четыре.
У нас везде стоят SSD RAID (даже там, где показывается HDD по тарифу), но мы хотели сильнее, выше и быстрее.
Первое, что мы узнали, — что NVMe не объединяется в RAID нормальными способами, то есть в итоге надёжных дисков ждать не стоит. Второе — в этот же сервер мы хотели запихнуть Hi-CPU и с удивлением установили, что частота 4,5 ГГц — это не серверное, а домашнее десктопное железо и серверных решений такой частоты просто физически не бывает в природе пока.
Плюс по дороге наш админ нашёл фатальный баг в утилите тестирования. В общем, давайте расскажу с тестами, на что именно похоже NVMe-решение в VDS-хостинге.
Сразу скажу, что, возможно, мы что-то не так делали, и если кто-то понимает что — буду очень благодарен.
▍ Ожидания от NVMe
Когда мы переходили с HDD на SSD, разница была как небо и земля. Запускаешь любой тест — и получаешь кратный прирост производительности. На NVMe такого не было. Более того, в столкновении лоб в лоб с нашими уже имеющимися конфигурациями NVMe диски не всегда обходили их. Быстрее они были или медленнее, зависело от условий теста.
Для начала мы купили пару вариантов серверов. Мы обычно покупаем платформу, тестируем, понимаем, что не так, тестируем ещё, потом только раскатываем на 11 локаций, потому что столько ЗИПа сразу и новые процессы поддержки — это дорого. Тут мы купили платформу и сразу наткнулись на невероятно отстойный результат.
В одном и том же гипервизоре на разных гостевых ОС было не отличить, SSD внутри сервера или NVMe. Даже с тестом.
При использовании NVMe в RAID скорость будет ниже, чем у SSD. Грубо говоря, когда мы используем RAID, мы его включаем в одну PCIe-шину и мы ограничены этой PCI Еxpress, и только несколько дисков можем распараллелить по разным шинам. Нужны контроллеры.
Почему так, никто не смог дать нормального ответа. Спрашивали у старого проверенного вендора, у новых вендоров, у вообще левых вендоров. Все разводили плечами и говорили: «Ну вы вообще лохи, кто же втыкает NVMe в RAID — не будет производительности!». Формулировки отличались от приведённой, но смысл оставался неизменным. Так мы поняли, что, наверное, надо использовать NVMe без рейда. Есть одна компания (дружественный конкурент) — так вот, только они пояснили, что у них так же было несколько лет назад. Они выкинули несколько платформ, и в итоге решено было не использовать RAID.
То есть первая проблема — при вылете диска не будет авторебилда на новый, который принесёт админ. Без RAID клиенты будут терять статус виртуалок и данные. Уже не то, но мы пробуем идти дальше.
Дальше есть выбор между U2 и M2. Мы купили дорогие диски U2. Они втыкаются через интерфейс Окулинка в шину. M2 чаще используют в десктопах, они втыкаются в материнку. Тоже протестировали, разницы между ними особо нет. Но если диск втыкается без промежуточного интерфейса прямо в плату, то его сложнее обслуживать, — при выходе из строя надо будет снимать крышку сервера и ковыряться.
▍ Теперь тесты — реальность NVMe
Результат зависит от ОС хоста, версии гипервизора, версии домашней ОС на виртуалке, выбора метода тестирования.
Зависит это от того, что наиболее свежие гипервизоры поддерживают NVMe своими драйверами нативно, а другие работают как оверхед SSD. Это тоже не очень хороший результат, потому что мы привыкли использовать проверенные решения. Есть серверная винта 12–16–19. Мы используем максимальную версию 16. Когда выйдет следующая — будем использовать 19. Потому что последние версии всегда беты. Вообще, в серверном администрировании последнюю версию софта используют только гики и самоубийцы. И да, если у вас сейчас дёрнулась рука, вы гик. Или бета-тестер. Хотя, возможно, вы об этом ещё не знаете. Вендор софта регулярно выкатывает новую версию, даёт ребуты, обновления, патчи — нужно пройти поколение, чтобы это работало стабильно. Как всегда ждём второго сервис пака. Клиенту не объяснишь про новую уязвимость или новую пачку апдейтов от MS. Точнее, мы объяснить сможем, но клиент не всегда верит. С нашим парком машин на 19-ю Винду бежать — не очень хорошо. Если все сервера начнут цветомузыку делать с обновлениями и перезагрузками, в грязь лицом бить не хочется.
Второй важный момент касается странности на файле 45 Гб, сейчас увидите.
Методика: при тестировании мы использовали утилиту diskspd. Вокруг неё навернули CrystalDiskMark, который мы хотели использовать первым, но нашли один очень забавный баг.
Для нас важно, что обе утилиты:
- Позволяют задавать несколько тестируемых файлов одновременно. Причём эти файлы могут быть размещены на разных дисках. Это может быть полезным для проверки общей пропускной способности контроллера при независимом чтении на разные диски. Количество потоков. Сколько будет создано независимых друг от друга потоков, которые будут производить чтение и запись файлов.
- В diskspd number of outstanding IO requests per thread — здесь возможны некоторые разночтения в переводе. Более того, в CrystalDiskMark этот параметр называется Queue, хотя очередью это можно назвать с некоторой натяжкой.
▍ Понимание параметра number of outstanding IO
Для понимания как утилита работает, мы можем заглянуть в её исходный код. Наиболее интересны следующие строки.
Для чтения:
if (useCompletionRoutines)
{
rslt = ReadFileEx(...);
}
else
{
rslt = ReadFile(...);
}
И аналогичные строки для записи:
if (useCompletionRoutines)
{
rslt = WriteFileEx(...);
}
else
{
rslt = WriteFile(...);
}
Аргументы пропущены для наглядности. Нас больше интересует тот факт, что чтение и запись производятся стандартными функциям WinAPI:
ReadFile
WriteFile
И соответствующими асинхронными функциями:
ReadFileEx
WriteFileEx
Если подробнее разобрать код, то можно понять следующее:
При задании number of outstanding IO = 1 будут использованы синхронные варианты ReadFile и WriteFile. Псевдокод для операции записи выглядит примерно так:
void testThreadFunc() {
while (!stopTesting) {
WriteFile(...) // ждем окончания записи
}
}
Если задать number of outstanding IO > 1, то будут использованы асинхронные варианты ReadFileEx и WriteFileEx и число number of outstanding IO задаёт глубину таких вызовов для каждого потока. Псевдокод для операции записи при number of outstanding IO = 3 выглядит так:
void callback1() {
while (!stopTesting) {
WriteFileEx(..., callback1)
}
}
void callback2() {
while (!stopTesting) {
WriteFileEx(..., callback2)
}
}
void callback3() {
while (!stopTesting) {
WriteFileEx(..., callback3)
}
}
void testThreadFunc() {
WriteFileEx(..., callback1) // не ждем окончания записи
WriteFileEx(..., callback2) // не ждем окончания записи
WriteFileEx(..., callback3) // не ждем окончания записи
// ждем когда все операции завершатся
}
Таким образом, number of outstanding IO — это количество асинхронных вызовов в каждом потоке.
▍ Почему мы не использовали CrystalDiskMark
Утилита CrystalDiskMark — это просто графическая оболочка для diskspd. Об этом несложно догадаться, если установить утилиту и зайти в директорию CdmResource\DiskSpd.
Но в реализации этой оболочки есть ряд проблем.
Во-первых, она каким-то образом модифицирует код diskspd. Это несложно понять, если заглянуть в код CrystalDiskMark:
command.Format(L"\"%s\" %s -d%d -A%d -L \"%s\"", ..., GetCurrentProcessId(), ...);
При вызове diskspd ему передаётся параметр -A с указанием Id текущего процесса. Такого параметра у diskspd нет. Автор CrystalDiskMark решил не парсить консольный вывод diskspd и решил получить данные более хитрым способом. Причём способ выбран не самый удачный.
Вот в этой функции происходит непосредственный вызов diskspd:
int ExecAndWait(TCHAR *pszCmd, BOOL bNoWindow, double *latency)
{
DWORD Code = 0;
…
GetExitCodeProcess(pi.hProcess, &Code);
*latency = (double)*pMemory * 1000; // milli sec to micro sec
return Code;
}
К передаче latency через SharedMemory в принципе нет вопросов. Но если рассмотреть далее по коду, где используется значение переменной Code, то становится ясным, что это и есть измеренная скорость диска. Возвращать её через ErrorCode процесса неудачная идея. Например, если процесс завершится с ошибкой по какой-то другой причине, то код ошибки будет просто отображён в результате тестирования.
Ещё есть сомнения в правильности возвращаемого значения latency. При указании ключа -L diskspd возвращает примерно такую табличку:
Например, шестая строка означает, что в 95% случаев задержка будет меньше 54.306ms. CrystalDiskMark же просто возвращает среднее по всем значениям таблицы. Это может вводить в заблуждение.
▍ Параметры тестирования
Для того чтобы увидеть преимущества NVME, необходимо задавать number of outstanding IO достаточно большим. Мы выбрали число 32.
❒ Платформа:
Supermicro SuperServer SYS-6029P-WTRT 2U
❒ Диски:
Intel SSD DC P4610 Series 1.6TB, 2.5in PCIe 3.1×4, 3D2, TLC
❒ Команды для запуска diskspd для файла 10G:
DiskSpd64.exe -b128K -t32 -o32 -w0 -d10 -si -S -c10G G:/testfile.dat
DiskSpd64.exe -b128K -t32 -o32 -w100 -d10 -si -S -c10G G:/testfile.dat
DiskSpd64.exe -b4K -t32 -o32 -w30 -d10 -r -S -c10G G:/testfile.dat
❒ Команды для запуска diskspd для файла 50G:
DiskSpd64.exe -b128K -t32 -o32 -w0 -d10 -si -S -c50G G:/testfile.dat
DiskSpd64.exe -b128K -t32 -o32 -w100 -d10 -si -S -c50G G:/testfile.dat
DiskSpd64.exe -b4K -t32 -o32 -w30 -d10 -r -S -c50G G:/testfile.dat
▍ Результаты
❒ Table 1 Хостовая ОС Windows Server 2019
❒ Table 1 Хостовая ОС Windows Server 2016
Под Hyper-V и гостевой Windows Server получаются результаты, которые сложно объяснить. На небольшом файле порядка 10G мы получаем большой прирост IOPS по сравнению с SSD в рейде. Но если взять файл 45G, мы наоборот получаем значительное падение IOPS.
▍ Теперь переходим к Hi-CPU
Второй сюрприз открылся на процессорах с частотой 4,5 ГГц.
Тут надо сказать, что процессоры в серверных линейках тоже используются на -1 поколение от десктопа. Потому что бета-тестеры — это геймеры, и им можно присылать софтверные патчи. А вот на серверах даже тот же хартблид не сразу поправили и не всё. Все серверные решения надёжные и дорогие, зато всегда уступают по скорости.
У нас недесктопные задачи. Машина делится между многими клиентами. И вот мы видим конфигурации на 4,5 ГГц, которых в природе нет.
Оказывается, реализаций две:
- Либо Hi-CPU реализован за счёт разогнанных десктопных вариантов (был у Интела эксперимент с серверным разгоном, но возникали проблемы с охлаждением). Это можно очень увлекательно решить, если использовать водные контуры, и некоторые так действительно делают. У нас сантехнического опыта не было.
- Либо же это десктопные процессоры, которые имеют turbo boost-частоту, но она максимальная. Именно эта частота используется в маркетинговых материалах! При этом из-под гостевой ОС видно производительность 3,6 вместо 4,5 в бусте. Потому что турбобуст, вообще-то, врубается специфически: процессор старается давать повышенную частоту при наличии питания и запаса по температуре. Это хорошо при пиках на десктопе (но не в играх), но очень плохо для сервера под нагрузкой с несколькими клиентами. То есть турбобуст не врубается на сервере почти никогда.
▍ Итого
Итак, взяли 3,9 и этим закрыли изыскания с процессором.
С NVMe — нахватавшись рандомных результатов от суперстандартной утилиты, как видите, сменили инструмент. Дальше вопрос гипервизора и ОС.
В коммерческом плане эти диски предлагают всё больше, надо учиться работать. Для себя оставляем определённую комбинацию хостовой версии гипервизора и будем дальше тестить, диски представлять тоже. Если хостер пишет NVMe — это ещё ничего не значит. На KVM с определёнными свежими сборками *nix и кропотливой настройкой можно получить отличный выигрыш, но каждый тест надо помечать звёздочкой, — «вот в таких условиях, чуть поменяешь — и вообще всё не так». На 12-й Винде или Дебиане уже всё другое.
В общем, NVMe — безусловный стандарт, но пока это не значит, что на тарифе с ним точно будет быстрее. Мы разворачиваем сервера с ним аккуратно, но пока выигрыш примерно соответствует повышению в цене, никакой магии.