Por que meu NVMe é mais lento que meu SSD?



Neste artigo, veremos algumas das nuances do subsistema de E / S e seu impacto no desempenho.



Algumas semanas atrás, me perguntei por que o NVMe em um servidor é mais lento do que o SATA em outro. Eu olhei para as características dos servidores e percebi que esta era uma pegadinha: NVMe era do segmento de usuário e o SSD era do segmento de servidor.



Obviamente, comparar produtos de segmentos diferentes em ambientes diferentes não é correto, mas esta não é uma resposta técnica abrangente. Vamos aprender o básico, experimentar e responder à pergunta.



O que é fsync e onde é usado



Para acelerar o trabalho com drives, os dados são armazenados em buffer, ou seja, armazenados na memória volátil até que uma oportunidade conveniente se apresente para salvar o conteúdo do buffer no drive. Os critérios de "oportunidade" são determinados pelo sistema operacional e pelas características da unidade. No caso de falha de energia, todos os dados do buffer serão perdidos.



Existem várias tarefas nas quais você precisa se certificar de que as alterações em um arquivo são gravadas na unidade, e não em um buffer intermediário. Essa confiança pode ser adquirida usando a chamada de sistema fsync compatível com POSIX. A chamada fsync inicia uma gravação forçada do buffer para a unidade.



Vamos demonstrar o efeito dos buffers com um exemplo artificial na forma de um programa C curto.



#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, "42\n", 3); 

    return 0;
}


Os comentários explicam bem a sequência de ações do programa. O texto "a resposta para a questão principal da vida, o Universo e tudo isso" será armazenado em buffer pelo sistema operacional, e se você reiniciar o servidor pressionando o botão Reset durante os "cálculos", o arquivo ficará vazio. Em nosso exemplo, a perda de texto não é um problema, portanto, o fsync não é necessário. Os bancos de dados não compartilham desse otimismo.



Bancos de dados são programas complexos que trabalham simultaneamente com muitos arquivos, portanto, eles querem ter certeza de que os dados que gravam serão salvos na unidade, uma vez que a consistência dos dados dentro do banco de dados depende disso. Os bancos de dados são projetados para registrar todas as transações concluídas e estar prontos para quedas de energia a qualquer momento. Esse comportamento nos obriga a usar fsync em grandes quantidades o tempo todo.



O que o uso frequente de fsync afeta



Com E / S normal, o sistema operacional tenta otimizar sua comunicação com os discos, uma vez que as unidades externas são as mais lentas na hierarquia de memória. Portanto, o sistema operacional tenta gravar o máximo de dados possível em uma chamada para a unidade.



Vamos demonstrar o impacto do uso de fsync com um exemplo específico. Temos os seguintes SSDs como assuntos de teste:



  • Intel® DC SSD S4500 480 GB, conectado via SATA 3.2, 6 Gb / s;
  • Samsung 970 EVO Plus 500 GB, PCIe 3.0 x4, ~ 31 Gbps.


Os testes são conduzidos no Intel® Xeon® W-2255 executando o Ubuntu 20.04. O Sysbench 1.0.18 é usado para testar discos. Uma partição é criada nas unidades, formatada como ext4. A preparação para o teste consiste na criação de arquivos de 100 GB:



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


Testes em execução:



#  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


Os resultados do teste são apresentados na tabela.

Teste Intel® S4500 Samsung 970 EVO +
Leitura sem fsync, MiB / s 5734,89 9028,86
Gravação sem fsync, MiB / s 3823,26 6019,24
Leia com fsync, MiB / s 37,76 3,27
Gravação Fsync, MiB / s 25,17 2,18
É fácil ver que o NVMe do segmento de cliente lidera com segurança quando o próprio sistema operacional decide como trabalhar com discos e perde quando o fsync é usado. Isso levanta duas questões:



  1. Por que no teste sem fsync a velocidade de leitura excede a largura de banda física?
  2. Por que um SSD do lado do servidor é melhor para lidar com um grande número de solicitações fsync?


A resposta à primeira pergunta é simples: o sysbench gera arquivos preenchidos com zeros. Assim, o teste foi realizado em 100 gigabytes de zeros. Como os dados são muito monótonos e previsíveis, várias otimizações do sistema operacional entram em ação e aceleram significativamente a execução.



Se você questionar todos os resultados do sysbench, poderá usar o 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
Teste Intel® S4500 Samsung 970 EVO +
Leitura sem fsync, MiB / s 45,5 178
Gravação sem fsync, MiB / s 30,4 119
Leia com fsync, MiB / s 32,6 20,9
Gravação Fsync, MiB / s 21,7 13,9
A tendência de queda do desempenho do NVMe ao usar o fsync é claramente visível. Você pode prosseguir para a resposta à segunda pergunta.



Otimização ou blefe



Anteriormente, dissemos que os dados são armazenados em um buffer, mas não especificamos qual, pois não era importante. Não vamos nos aprofundar nas complexidades dos sistemas operacionais agora e destacar dois tipos gerais de buffers:



  • programa;
  • hardware.


O buffer de software se refere aos buffers que estão no sistema operacional e o buffer de hardware se refere à memória volátil do controlador de disco. A chamada de sistema fsync envia um comando para a unidade para gravar dados de seu buffer para o armazenamento principal, mas não pode controlar a exatidão da execução do comando.



Como os SSDs têm melhor desempenho, duas suposições podem ser feitas:



  • o disco é projetado para tal carga;
  • o disco blefa e ignora o comando.


Você pode ver o comportamento desonesto da unidade se executar um teste de falha de energia. Você pode verificar isso usando o script diskchecker.pl , que foi criado em 2005.



Este script requer duas máquinas físicas - "servidor" e "cliente". O cliente grava uma pequena quantidade de dados no disco em teste, chama fsync e envia informações ao servidor sobre o que foi gravado.



#   
./diskchecker.pl -l [port]

#   
./diskchecker.pl -s <server[:port]> create <file> <size_in_MB>


Após executar o script, é necessário desenergizar o "cliente" e não religar a alimentação por vários minutos. É importante desconectar a pessoa que está sendo testada da eletricidade, e não apenas realizar um desligamento forçado. Depois de algum tempo, o servidor pode ser conectado e carregado no sistema operacional. Após a inicialização do sistema operacional, você precisa executar diskchecker.pl novamente , mas com o argumento verify .



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


Ao final da verificação, você verá a quantidade de erros. Se houver 0, o disco passou no teste. Para excluir uma combinação de circunstâncias bem-sucedidas para o disco, o experimento pode ser repetido várias vezes.



Nosso S4500 não apresentou erros de perda de energia, portanto, pode-se argumentar que está pronto para cargas com muitas chamadas fsync.



Conclusão



Ao escolher discos ou configurações prontas completas, você deve se lembrar das especificidades das tarefas que precisam ser resolvidas. À primeira vista, parece óbvio que o NVMe, ou seja, o SSD com interface PCIe, é mais rápido que o SSD SATA "clássico". No entanto, como entendemos hoje, em condições específicas e com determinadas tarefas, pode não ser esse o caso.



Como você testa os componentes do servidor ao alugar de um provedor IaaS?

Estamos esperando por você nos comentários.






All Articles