Dlaczego mój NVMe jest wolniejszy niż mój dysk SSD?

Dlaczego mój NVMe jest wolniejszy niż mój dysk SSD?
W tym artykule przyjrzymy się niektórym niuansom podsystemu we/wy i ich wpływowi na wydajność.

Kilka tygodni temu stanąłem przed pytaniem, dlaczego NVMe na jednym serwerze jest wolniejszy niż SATA na innym. Przyjrzałem się specyfikacjom serwerów i zdałem sobie sprawę, że to trudne pytanie: NVMe pochodziło z segmentu użytkowników, a dyski SSD z segmentu serwerów.

Oczywiście porównywanie produktów z różnych segmentów w różnych środowiskach jest niesprawiedliwe, ale nie jest to pełna odpowiedź techniczna. Przestudiujmy podstawy, przeprowadźmy eksperymenty i udzielmy odpowiedzi na postawione pytanie.

Co to jest fsync i gdzie się go używa?

Aby przyspieszyć pracę z dyskami, dane są buforowane, czyli przechowywane w pamięci ulotnej do czasu, aż pojawi się dogodna możliwość zapisania zawartości bufora na dysku. Kryteria „możliwości” zależą od systemu operacyjnego i charakterystyki dysku. W przypadku awarii zasilania wszystkie dane znajdujące się w buforze zostaną utracone.

Istnieje wiele zadań, podczas których należy mieć pewność, że zmiany w pliku zostaną zapisane na dysku, a nie w buforze pośrednim. Tę pewność można uzyskać, korzystając z wywołania systemowego fsync zgodnego z POSIX. Wywołanie fsync wymusza zapis z bufora na dysk.

Zademonstrujmy działanie buforów na sztucznym przykładzie w postaci krótkiego programu w 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;
}

Komentarze dobrze wyjaśniają kolejność działań w programie. Tekst „odpowiedź na główne pytanie życia, Wszechświata i tak dalej” zostanie zbuforowany przez system operacyjny, a jeśli zrestartujesz serwer, naciskając przycisk Reset podczas „obliczeń”, plik będzie pusty. W naszym przykładzie utrata tekstu nie stanowi problemu, więc fsync nie jest potrzebne. Bazy danych nie podzielają tego optymizmu.

Bazy danych to złożone programy, które jednocześnie pracują z wieloma plikami, dlatego chcą mieć pewność, że zapisywane przez nich dane zostaną zapisane na dysku, ponieważ od tego zależy spójność danych wewnątrz bazy danych. Bazy danych są zaprojektowane tak, aby rejestrować wszystkie zakończone transakcje i być gotowe na utratę zasilania w dowolnym momencie. To zachowanie wymaga ciągłego używania fsync w dużych ilościach.

Jaki jest efekt częstego używania fsync?

Podczas normalnego we/wy system operacyjny próbuje zoptymalizować komunikację z dyskami, ponieważ dyski zewnętrzne są najwolniejsze w hierarchii pamięci. Dlatego system operacyjny stara się zapisać jak najwięcej danych w jednym dostępie do dysku.

Zademonstrujmy wpływ użycia fsync na konkretnym przykładzie. Jako dyski testowe posiadamy następujące dyski SSD:

  • Intel® DC SSD S4500 480 GB, podłączony przez SATA 3.2, 6 Gbit/s;
  • Samsung 970 EVO Plus 500 GB, podłączony przez PCIe 3.0 x4, ~31 Gbit/s.

Testy przeprowadzono na komputerze Intel® Xeon® W-2255 z systemem Ubuntu 20.04. Do testowania dysków służy Sysbench 1.0.18. Na dyskach utworzono jedną partycję w formacie ext4. Przygotowanie do testu polega na utworzeniu plików o rozmiarze 100 GB:

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

Testy uruchomieniowe:

# Без 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

Wyniki testu przedstawiono w tabeli.

Test
Intel® S4500
Samsunga 970 EVO+

Odczyt bez fsync, MiB/s
5734.89
9028.86

Nagrywanie bez fsync, MiB/s
3823.26
6019.24

Odczyt za pomocą fsync, MiB/s
37.76
3.27

Nagrywanie z fsync, MiB/s
25.17
2.18

Łatwo zauważyć, że NVMe z segmentu klienckiego śmiało przoduje, gdy system operacyjny sam decyduje o tym, jak pracować z dyskami, i przegrywa, gdy stosuje się fsync. Rodzi to dwa pytania:

  1. Dlaczego prędkość odczytu w teście bez fsync przekracza fizyczną przepustowość kanału?
  2. Dlaczego dysk SSD segmentu serwerowego lepiej radzi sobie z dużą liczbą żądań fsync?

Odpowiedź na pierwsze pytanie jest prosta: sysbench generuje pliki wypełnione zerami. Tym samym test przeprowadzono na ponad 100 gigabajtach zer. Ponieważ dane są bardzo jednolite i przewidywalne, w grę wchodzą różne optymalizacje systemu operacyjnego, które znacznie przyspieszają wykonanie.

Jeśli kwestionujesz wszystkie wyniki sysbencha, możesz użyć 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

Test
Intel® S4500
Samsunga 970 EVO+

Odczyt bez fsync, MiB/s
45.5
178

Nagrywanie bez fsync, MiB/s
30.4
119

Odczyt za pomocą fsync, MiB/s
32.6
20.9

Nagrywanie z fsync, MiB/s
21.7
13.9

Wyraźnie widoczna jest tendencja do pogarszania się wydajności NVMe podczas korzystania z fsync. Możesz przejść do odpowiedzi na drugie pytanie.

Optymalizacja lub blef

Wcześniej mówiliśmy, że dane są przechowywane w buforze, ale nie określiliśmy w jakim, ponieważ nie było to istotne. Nawet teraz nie będziemy zagłębiać się w zawiłości systemów operacyjnych i wyróżnimy dwa ogólne typy buforów:

  • program;
  • sprzęt komputerowy.

Bufor programowy odnosi się do buforów istniejących w systemie operacyjnym, a bufor sprzętowy odnosi się do pamięci ulotnej kontrolera dysku. Wywołanie systemowe fsync wysyła do napędu polecenie zapisania danych z jego bufora do pamięci głównej, ale nie ma możliwości sprawdzenia, czy polecenie zostało wykonane poprawnie.

Ponieważ dysk SSD wykazuje najlepsze wyniki, można przyjąć dwa założenia:

  • dysk jest zaprojektowany na podobne obciążenie;
  • dysk „blefuje” i ignoruje polecenie.

Nieuczciwe zachowanie napędu można zauważyć, jeśli przeprowadzisz test utraty mocy. Można to sprawdzić za pomocą skryptu dyskchecker.pl, to było stworzony przez w 2005 roku.

Skrypt ten wymaga dwóch fizycznych maszyn – „serwera” i „klienta”. Klient zapisuje niewielką ilość danych na testowany dysk, wywołuje fsync i wysyła do serwera informację o tym, co zostało zapisane.

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

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

Po uruchomieniu skryptu należy wyłączyć zasilanie „klienta” i nie przywracać zasilania przez kilka minut. Ważne jest, aby odłączyć testowaną osobę od prądu, a nie tylko dokonać całkowitego wyłączenia. Po pewnym czasie serwer można podłączyć i załadować do systemu operacyjnego. Po załadowaniu systemu operacyjnego należy go uruchomić ponownie dyskchecker.pl, ale z argumentem zweryfikować.

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

Na koniec sprawdzania zobaczysz liczbę błędów. Jeśli jest ich 0, oznacza to, że dysk przeszedł test. Aby wykluczyć szczęśliwy zbieg okoliczności dla dysku, eksperyment można powtórzyć kilka razy.

Nasz S4500 nie wyświetlał żadnych błędów w przypadku utraty zasilania, co oznacza, że ​​jest gotowy na obciążenia wymagające dużej liczby wywołań fsync.

wniosek

Wybierając dyski lub całe gotowe konfiguracje, należy pamiętać o specyfice problemów, które należy rozwiązać. Na pierwszy rzut oka wydaje się oczywiste, że NVMe, czyli dysk SSD z interfejsem PCIe, jest szybszy od „klasycznego” dysku SSD SATA. Jednak, jak się dzisiaj dowiedzieliśmy, w określonych warunkach i przy niektórych zadaniach może tak nie być.

Jak testować komponenty serwera w przypadku wynajmu od dostawcy IaaS?
Czekamy na Was w komentarzach.

Dlaczego mój NVMe jest wolniejszy niż mój dysk SSD?

Źródło: www.habr.com

Dodaj komentarz