Защо моят NVMe е по-бавен от моето SSD?

Защо моят NVMe е по-бавен от моето SSD?
В тази статия ще разгледаме някои от нюансите на I/O подсистемата и тяхното влияние върху производителността.

Преди няколко седмици бях изправен пред въпроса защо NVMe на един сървър е по-бавен от SATA на друг. Погледнах спецификациите на сървъра и осъзнах, че това е труден въпрос: NVMe беше от потребителския сегмент, а SSD беше от сървърния сегмент.

Очевидно не е честно да се сравняват продукти от различни сегменти в различни среди, но това не е пълен технически отговор. Нека да изучим основите, да проведем експерименти и да дадем отговор на поставения въпрос.

Какво е fsync и къде се използва?

За да се ускори работата с устройствата, данните се буферират, т.е. съхраняват се в енергонезависима памет, докато не се появи удобна възможност за запазване на съдържанието на буфера на устройството. Критериите за „възможност“ се определят от операционната система и характеристиките на устройството. В случай на прекъсване на захранването, всички данни в буфера ще бъдат загубени.

Има редица задачи, при които трябва да сте сигурни, че промените във файл се записват на устройството, а не в междинен буфер. Тази увереност може да бъде получена чрез използване на POSIX-съвместимото системно извикване fsync. Извикването на fsync принуждава запис от буфера към устройството.

Нека демонстрираме ефекта на буферите с изкуствен пример под формата на кратка програма на C.

#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(void) {
    /* Открываем файл answer.txt на запись, если его нет -- создаём */
    int fd = open("answer.txt", O_WRONLY | O_CREAT);
    /* Записываем первый набор данных */
    write(fd, "Answer to the Ultimate Question of Life, The Universe, and Everything: ", 71);
    /* Делаем вид, что проводим вычисления в течение 10 секунд */
    sleep(10);
    /* Записываем результат вычислений */
    write(fd, "42n", 3); 

    return 0;
}

Коментарите обясняват добре последователността от действия в програмата. Текстът „отговорът на основния въпрос за живота, Вселената и всичко това“ ще бъде буфериран от операционната система и ако рестартирате сървъра, като натиснете бутона Reset по време на „изчисления“, файлът ще бъде празен. В нашия пример загубата на текст не е проблем, така че fsync не е необходим. Базите данни не споделят този оптимизъм.

Базите данни са сложни програми, които работят едновременно с много файлове, така че те искат да са сигурни, че записаните от тях данни ще бъдат запазени на устройството, тъй като последователността на данните в базата данни зависи от това. Базите данни са проектирани да записват всички завършени транзакции и да са готови да загубят мощност по всяко време. Това поведение изисква използването на fsync постоянно в големи количества.

Какъв е ефектът от честото използване на fsync?

По време на нормален I/O операционната система се опитва да оптимизира комуникацията с дисковете, тъй като външните устройства са най-бавните в йерархията на паметта. Следователно операционната система се опитва да запише възможно най-много данни с един достъп до устройството.

Нека демонстрираме въздействието от използването на fsync с конкретен пример. Разполагаме със следните SSD като тестови устройства:

  • Intel® DC SSD S4500 480 GB, свързан чрез SATA 3.2, 6 Gbit/s;
  • Samsung 970 EVO Plus 500GB, свързан чрез PCIe 3.0 x4, ~31 Gbit/s.

Тестовете се провеждат на Intel® Xeon® W-2255 с Ubuntu 20.04. Sysbench 1.0.18 се използва за тестване на дискове. На дисковете е създаден един дял, форматиран като ext4. Подготовката за теста включва създаване на 100 GB файлове:

sysbench --test=fileio --file-total-size=100G prepare

Текущи тестове:

# Без fsync
sysbench --num-threads=16 --test=fileio --file-test-mode=rndrw --file-fsync-freq=0 run

# С fsync после каждой записи
sysbench --num-threads=16 --test=fileio --file-test-mode=rndrw --file-fsync-freq=1 run

Резултатите от теста са представени в таблицата.

Тест
Intel® S4500
Samsung 970 EVO+

Четене без fsync, MiB/s
5734.89
9028.86

Запис без fsync, MiB/s
3823.26
6019.24

Четене с fsync, MiB/s
37.76
3.27

Запис с fsync, MiB/s
25.17
2.18

Лесно е да се види, че NVMe от клиентския сегмент уверено води, когато операционната система сама решава как да работи с дискове и губи, когато се използва fsync. Това повдига два въпроса:

  1. Защо скоростта на четене в теста без fsync надвишава физическата честотна лента на канала?
  2. Защо сървърният сегмент SSD е по-добър при обработката на голям брой fsync заявки?

Отговорът на първия въпрос е прост: sysbench генерира файлове, пълни с нули. По този начин тестът беше извършен над 100 гигабайта нули. Тъй като данните са много еднакви и предсказуеми, различни оптимизации на ОС влизат в действие и значително ускоряват изпълнението.

Ако поставите под въпрос всички резултати от sysbench, можете да използвате fio.

# Без fsync
fio --name=test1 --blocksize=16k --rw=randrw --iodepth=16 --runtime=60 --rwmixread=60 --fsync=0 --filename=/dev/sdb

# С fsync после каждой записи
fio --name=test1 --blocksize=16k --rw=randrw --iodepth=16 --runtime=60 --rwmixread=60 --fsync=1 --filename=/dev/sdb

Тест
Intel® S4500
Samsung 970 EVO+

Четене без fsync, MiB/s
45.5
178

Запис без fsync, MiB/s
30.4
119

Четене с fsync, MiB/s
32.6
20.9

Запис с fsync, MiB/s
21.7
13.9

Тенденцията за влошаване на производителността на NVMe при използване на fsync е ясно видима. Можете да преминете към отговора на втория въпрос.

Оптимизация или блъф

По-рано казахме, че данните се съхраняват в буфер, но не уточнихме кой, тъй като това не беше важно. Дори сега няма да се задълбочаваме в тънкостите на операционните системи и ще подчертаем два общи вида буфери:

  • програма;
  • хардуер.

Софтуерният буфер се отнася до буферите, които съществуват в операционната система, а хардуерният буфер се отнася до енергонезависимата памет на дисковия контролер. Системното извикване fsync изпраща команда до устройството за запис на данни от неговия буфер в основното хранилище, но няма начин да провери дали командата е изпълнена правилно.

Тъй като SSD показва най-добри резултати, могат да се направят две предположения:

  • дискът е проектиран за подобно натоварване;
  • дискът "блъфира" и игнорира командата.

Нечестното поведение на устройството може да се забележи, ако проведете тест за загуба на мощност. Можете да проверите това със скрипт diskchecker.pl, това беше създаден 2005 година.

Този скрипт изисква две физически машини - "сървър" и "клиент". Клиентът записва малко количество данни на тествания диск, извиква fsync и изпраща информация до сървъра за това, което е написано.

# Запускается на сервере
./diskchecker.pl -l [port]

# Запускается на клиенте
./diskchecker.pl -s <server[:port]> create <file> <size_in_MB>

След стартиране на скрипта трябва да изключите захранването на „клиента“ и да не връщате захранването няколко минути. Важно е да изключите лицето, което се тества от електричеството, а не просто да извършите пълно изключване. След известно време сървърът може да бъде свързан и зареден в операционната система. След зареждане на ОС трябва да я стартирате отново diskchecker.pl, но с аргумент провери.

./diskchecker.pl -s <server[:port]> verify <file>

В края на проверката ще видите броя на грешките. Ако има 0, тогава дискът е преминал теста. За да се изключи щастлива случайност за диска, експериментът може да се повтори няколко пъти.

Нашият S4500 не показа грешки при загуба на захранване, което означава, че е готов за натоварвания с много fsync повиквания.

Заключение

Когато избирате дискове или цели готови конфигурации, трябва да запомните спецификата на проблемите, които трябва да бъдат решени. На пръв поглед изглежда очевидно, че NVMe, тоест SSD с PCIe интерфейс, е по-бърз от „класическия“ SATA SSD. Но както разбрахме днес, при конкретни условия и при определени задачи това може да не е така.

Как тествате сървърни компоненти, когато наемате от IaaS доставчик?
Очакваме ви в коментарите.

Защо моят NVMe е по-бавен от моето SSD?

Източник: www.habr.com

Добавяне на нов коментар