
In questo articolo esamineremo alcune sfumature del sottosistema di input/output e il loro impatto sulle prestazioni.
Un paio di settimane fa ho affrontato la questione del perché NVMe fosse più lento su un server rispetto a SATA su un altro. Ho controllato le specifiche dei server e ho capito che si trattava di una domanda ingannevole: NVMe era di livello consumer, mentre SSD era di livello server.
È ovvio che confrontare prodotti di diversi segmenti in ambienti diversi non sia corretto, ma questo non è una risposta tecnica esaustiva. Esploreremo le basi, faremo esperimenti e daremo una risposta alla domanda posta.
Cosa è fsync e dove viene utilizzato
Per accelerare l'operazione sui dispositivi di memorizzazione, i dati vengono memorizzati in un buffer, ovvero salvati in memoria volatile fino a quando non si presenta un'opportunità favorevole per scrivere il contenuto del buffer sul dispositivo. I criteri per l' «opportunità favorevole» sono definiti dal sistema operativo e dalle caratteristiche del dispositivo. In caso di interruzione di corrente, tutti i dati nel buffer andranno persi.
Esistono vari compiti in cui è necessario essere certi che le modifiche a un file siano state scritte sul dispositivo e non risiedano in un buffer intermedio. Questa certezza può essere ottenuta utilizzando la chiamata di sistema fsync compatibile con POSIX. La chiamata fsync avvia la scrittura forzata dal buffer al dispositivo.
Dimostreremo l'impatto dei buffer con un esempio artificiale sotto forma di un breve programma in 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;
}I commenti spiegano bene la sequenza delle azioni nel programma. Il testo «risposta alla domanda fondamentale sulla vita, l'universo e tutto quanto» sarà memorizzato in buffer dal sistema operativo e se si riavvia il server premendo il pulsante Reset durante i «calcoli», il file risulterà vuoto. In questo esempio, la perdita di testo non è un problema, quindi fsync non è necessario. I database non sono così ottimisti.
I database sono programmi complessi che lavorano contemporaneamente con molti file, perciò vogliono essere certi che i dati che scrivono verranno salvati sul dispositivo, poiché ciò influisce sulla coerenza dei dati all'interno del DB. I database sono progettati per registrare tutte le transazioni completate e sono pronti a gestire un'interruzione di corrente in qualsiasi momento. Questo comportamento richiede l'uso costante di fsync in grandi quantità.
Quale impatto ha l'uso frequente di fsync
Nel normale input/output, il sistema operativo cerca di ottimizzare la comunicazione con i dischi, poiché nella gerarchia della memoria i dispositivi esterni sono i più lenti. Pertanto, il sistema operativo cerca di scrivere il maggior numero possibile di dati in un singolo accesso al dispositivo.
Dimostreremo l'impatto dell'uso di fsync con un esempio specifico. I nostri soggetti di prova sono i seguenti dispositivi di memorizzazione:
- Intel® DC SSD S4500 480 GB, collegato tramite SATA 3.2, 6 Gb/s;
- Samsung 970 EVO Plus 500GB, collegato tramite PCIe 3.0 x4, ~31 Gb/s.
I test sono condotti su Intel® Xeon® W-2255 con Ubuntu 20.04. Per testare i dischi utilizziamo sysbench 1.0.18. Su ciascun disco è stato creato un solo partizione formattata come ext4. La preparazione per il test consiste nella creazione di file di dimensioni pari a 100 GB:
sysbench --test=fileio --file-total-size=100G prepareAvvio dei test:
# Без 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 runI risultati dei test sono presentati nella tabella.
Test
Intel® S4500
Samsung 970 EVO+
Lettura senza fsync, MiB/s
5734.89
9028.86
Scrittura senza fsync, MiB/s
3823.26
6019.24
Lettura con fsync, MiB/s
37.76
3.27
Scrittura con fsync, MiB/s
25.17
2.18
Non è difficile notare che NVMe del segmento consumer è decisamente in testa quando il sistema operativo gestisce autonomamente il lavoro con i dischi, e perde quando si utilizza fsync. Da qui sorgono due domande:
- Perché nel test senza fsync la velocità di lettura supera la reale capacità del canale?
- Perché SSD del segmento server gestisce meglio un gran numero di richieste fsync?
La risposta alla prima domanda è semplice: sysbench genera file riempiti di zeri. Pertanto, il test è stato eseguito su 100 gigabyte di zeri. Poiché i dati sono molto omogenei e prevedibili, entrano in gioco varie ottimizzazioni del sistema operativo, che velocizzano significativamente l'esecuzione.
Se si mette in discussione tutti i risultati di sysbench, è possibile utilizzare 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/sdbTest
Intel® S4500
Samsung 970 EVO+
Lettura senza fsync, MiB/s
45.5
178
Scrittura senza fsync, MiB/s
30.4
119
Lettura con fsync, MiB/s
32.6
20.9
Scrittura con fsync, MiB/s
21.7
13.9
La tendenza a una diminuzione delle prestazioni di NVMe con l'uso di fsync è ben visibile. Possiamo passare alla risposta alla seconda domanda.
Ottimizzazione o inganno
In precedenza abbiamo detto che i dati vengono memorizzati in un buffer, ma non abbiamo specificato in quale, poiché non era fondamentale. Anche ora non ci addentreremo nei dettagli dei sistemi operativi e distingueremo due tipi generali di buffer:
- software;
- hardware.
Con il buffer di sistema si intendono i buffer presenti nel sistema operativo, mentre con buffer hardware si fa riferimento alla memoria volatile del controller del disco. La chiamata di sistema fsync invia al dispositivo il comando di scrivere i dati dal suo buffer nella memoria principale, ma non può controllare la correttezza dell'esecuzione di questo comando.
Poiché gli SSD mostrano risultati migliori, si possono fare due ipotesi:
- il disco è progettato per carichi simili;
- il disco "bluffa" e ignora il comando.
Comportamenti scorretti del dispositivo possono essere notati eseguendo un test con la perdita di alimentazione. Questo può essere verificato con uno script , sviluppato nel 2005.
Questo script richiede due macchine fisiche: un "server" e un "client". Il client scrive su disco un piccolo volume di dati, richiama fsync e invia al server informazioni su ciò che è stato scritto.
# Запускается на сервере
./diskchecker.pl -l [port]
# Запускается на клиенте
./diskchecker.pl -s <server[:port]> create <file> <size_in_MB>Dopo aver avviato lo script è necessario scollegare l'alimentazione del "client" e non riattivarla per alcuni minuti. È importante scollegare l'alimentazione del dispositivo in test, e non semplicemente eseguire uno spegnimento forzato. Dopo un certo periodo il server può essere riattaccato e avviato nel sistema operativo. Dopo aver caricato il sistema operativo, è necessario riavviare diskchecker.pl, ma con l'argomento verify.
./diskchecker.pl -s verifyAlla fine del test vedrete il numero di errori. Se sono 0, significa che il disco ha superato la prova. Per escludere circostanze favorevoli, l'esperimento può essere ripetuto più volte.
Il nostro S4500 non ha mostrato errori in caso di mancanza di alimentazione, dunque possiamo affermare che è pronto per carichi con un alto numero di chiamate fsync.
Conclusione
Quando si scelgono dischi o configurazioni pronte, è importante tenere a mente la specificità dei compiti da risolvere. A prima vista sembra ovvio che gli NVMe, cioè SSD con interfaccia PCIe, siano più veloci degli SSD SATA "classici". Tuttavia, come abbiamo capito oggi, in determinate condizioni e con determinati compiti questo potrebbe non essere il caso.
E come testate i componenti dei server quando li affittate da un fornitore IaaS?
Aspettiamo i vostri commenti.
Fonte: habr.com
