
In questo articolo esamineremo alcune sfumature del sottosistema di input-output e il loro impatto sulle prestazioni.
Alcune settimane fa mi sono trovato a dover rispondere alla domanda sul perché NVMe su un server fosse più lento di SATA su un altro. Ho guardato le specifiche dei server e ho capito che si trattava di una domanda insidiosa: NVMe era di segmento consumer, mentre l'SSD era server.
È evidente che confrontare prodotti di segmenti diversi in ambienti diversi non è corretto, ma non è una risposta tecnica esaustiva. Esploriamo le basi, conduciamo esperimenti e forniamo una risposta alla domanda posta.
Che cos'è fsync e dove viene utilizzato
Per accelerare il lavoro con i dispositivi di archiviazione, i dati vengono memorizzati in un buffer, ossia conservati nella memoria volatile fino a quando non si presenta un'opportunità favorevole per salvare il contenuto del buffer sul dispositivo. I criteri per un 'occasione favorevole' sono determinati dal sistema operativo e dalle caratteristiche del dispositivo. In caso di mancanza di alimentazione, tutti i dati nel buffer andranno persi.
Esistono una serie di compiti nei quali è necessario essere certi che le modifiche a un file siano scritte sul dispositivo e non rimangano nel buffer intermedio. Questa certezza può essere ottenuta utilizzando la chiamata di sistema compatibile con POSIX fsync. La chiamata fsync inizia una scrittura forzata dal buffer al dispositivo.
Dimostreremo l'impatto dei buffer con un esempio artificiale sotto forma di un breve programma in linguaggio 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 di azioni nel programma. Il testo 'risposta alla domanda fondamentale sulla vita, l'universo e tutto quanto' verrà memorizzato nel buffer dal sistema operativo e se si riavvia il server premendo il pulsante di reset durante i 'calcoli', il file risulterà vuoto. Nel nostro esempio, la perdita del testo non è un problema, quindi fsync non è necessario. I database non condividono questo ottimismo.
I database sono programmi complessi che lavorano contemporaneamente con molti file, quindi vogliono essere certi che i dati scritti siano 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 per essere pronti a un'interruzione di corrente in qualsiasi momento. Questo comportamento richiede di utilizzare fsync continuamente in grandi quantità.
A cosa influisce l'uso frequente di fsync
Durante le operazioni di input-output normali, il sistema operativo cerca di ottimizzare la comunicazione con i dischi, poiché gli archivi esterni sono i più lenti nella gerarchia della memoria. Pertanto, il sistema operativo cerca di registrare quanti più dati possibile in un'unica operazione di accesso all'archivio.
Dimostreremo l'impatto dell'uso di fsync con un esempio specifico. I nostri soggetti di test sono i seguenti dischi a stato solido:
- 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 vengono eseguiti su Intel® Xeon® W-2255 sotto il sistema operativo Ubuntu 20.04. Per testare i dischi viene utilizzato sysbench 1.0.18. Sono stati creati un'unica partizione sui dischi, formattata come ext4. La preparazione al test consiste nella creazione di file della dimensione di 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 client è decisamente in testa quando il sistema operativo decide autonomamente come lavorare con i dischi, mentre perde quando si utilizza fsync. Da qui sorgono due domande:
- Perché nel test senza fsync la velocità di lettura supera la capacità di banda fisica del canale?
- Perché gli SSD del segmento server gestiscono meglio un numero elevato di richieste fsync?
La risposta alla prima domanda è semplice: sysbench genera file pieni di zeri. Pertanto, il test è stato condotto su 100 gigabyte di zeri. Poiché i dati sono piuttosto uniformi e prevedibili, entrano in gioco diverse ottimizzazioni del sistema operativo, che accelerano notevolmente l'esecuzione.
Se si mette in dubbio tutti i risultati di sysbench, si può 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 alla caduta delle prestazioni di NVMe con l'uso di fsync è ben evidente. Possiamo passare alla risposta alla seconda domanda.
Ottimizzazione o bluff
In precedenza abbiamo detto che i dati vengono memorizzati nella cache, ma non abbiamo specificato quale, poiché non era fondamentale. E non ci immergeremo nelle complessità dei sistemi operativi e distingueremo due tipi generali di cache:
- software;
- hardware.
Con il buffer di programma ci si riferisce ai buffer presenti nel sistema operativo, mentre con quello hardware si intende la 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 del comando.
Poiché gli SSD mostrano risultati migliori, si possono fare due ipotesi:
- il disco è progettato per carichi di questo tipo;
- il disco "bluffa" e ignora il comando.
Il comportamento disonesto del dispositivo può essere notato eseguendo un test con un'interruzione di corrente. Questo può essere verificato con uno script , che è stato nel 2005.
Questo script richiede due macchine fisiche: "server" e "cliente". Il cliente scrive un piccolo volume di dati sul disco testato, chiama 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 disconnettere l'alimentazione al "cliente" e non ripristinarla per alcuni minuti. È importante interrompere l'alimentazione al dispositivo in test, e non semplicemente eseguire uno spegnimento forzato. Dopo un certo periodo di tempo, si può riconnettere il server e caricare il sistema operativo. Dopo il caricamento del sistema operativo è necessario riavviare diskchecker.pl, ma con l'argomento verify.
.\/diskchecker.pl -s verifyAlla fine del controllo vedrete il numero di errori. Se sono 0, significa che il disco ha superato il test. Per escludere il caso fortunato, il test può essere ripetuto più volte.
Il nostro S4500 non ha mostrato errori in caso di perdita di alimentazione, quindi si può affermare che è pronto per carichi con un alto numero di chiamate a fsync.
Conclusione
Quando si scelgono dischi o intere configurazioni pronte, è importante tenere presente le specificità delle attività da svolgere. A prima vista sembra ovvio che NVMe, cioè SSD con interfaccia PCIe, sia più veloce rispetto agli SSD SATA "classici". Tuttavia, come abbiamo appreso oggi, in condizioni specifiche e con compiti determinati, potrebbe non essere così.
E come testate i componenti dei server quando li affittate da un fornitore IaaS?
Vi aspettiamo nei commenti.
Fonte: habr.com
