Estou testando a taxa de transferência de um cartão SSD Samsung 950 Pro que usa o protocolo NVMe. Meu método atual de teste é montar um sistema de arquivos em uma partição e gravar um arquivo de tamanho X bytes no sistema de arquivos. Registrando o tempo necessário para isso, os bytes / segundo podem ser calculados.
No meu teste, tenho um loop while que grava até os bytes X em tamanhos de blocos de variáveis, um bloco por vez, especificado por um nível mais alto de loop. Além disso, também tenho outro loop que executará N desses aplicativos em paralelo, cada aplicativo gravando em uma partição diferente do SSD.
Atualmente, estou vendo velocidades ligeiramente mais rápidas do que a velocidade de transferência máxima teórica especificada pela folha de dados Samsung 950 Pro para leitura e escrita. A Samsung especificou que a velocidade máxima de gravação seqüencial para o 950 Pro é de 1,5 GB / se a velocidade de leitura seqüencial máxima é de 2,5 GB / s.
Aqui está a função principal do script bash que percorre o número de aplicativos para executar e bloquear tamanhos:
appInstances=1
while [ $appInstances -le 4 ]
do
for blocksize in 4096 32768 131072 524288 1048576 67108864 268435456 1073741824
do
# Run the test
datetime
echo "[$datetime_v]: Test blocksize: $blocksize appInstances: $appInstances"
run_single_perf_test $blocksize
done
appInstances='expr $appInstances \* 2'
done
exit 0
Aqui está a seção de gravação do run_perf_test. Há também uma seção de leitura após esta parte, que compreende o teste de velocidade de transferência de escrita. Entre os testes, desmonto todas as partições do SSD e remontá-las para permitir que todas as transações NVMe sejam concluídas e impedir que qualquer cache das operações de gravação influencie a medição da taxa de transferência para a operação de leitura.
instCnt=1
childpids=""
while [ $instCnt -le $appInstances ]
do
fsrw -w $blocksize /fsmnt/fs${instCnt}/usernumber1/j.j &
# Save the process ID
childpids="$childpids $!"
# Increment the instace count.
instCnt='expr $instCnt + 1'
done
fsrw é um aplicativo C ++ que, baseado no primeiro argumento, "-r" ou "-w", o segundo argumento, o tamanho do bloco e o terceiro argumento, o nome do arquivo que é um arquivo na partição SSD, construa uma string e tente abrir o arquivo na partição SSD e escreva a string nela. Aqui está a implementação para a função write, que é chamada quando "-w" é fornecido como o primeiro argumento.
/*! \fn perform_writeop()
* \brief The function returns true when the write operation completes successfully.
*
* The function will run until the read is complete or a 35 second timeout is reached.
* It will record the time before the write begins, then also record the time afterward.
* If the timeout is reached this should be about 35 seconds
*/
bool perform_writeop ()
{
// File descriptor.
int32_t fd = -1;
// Function status.
bool status = false;
// Zero writes
int zero_writes = 0;
// Buffer fill index.
int32_t bfidx = 0;
// Character value.
int8_t cv = 33;
// Fill the buffer with printable characters.
for (; bfidx < blocksize; bfidx++, cv++)
{
// Verify the character value is in range.
if (cv >= 127)
{
cv = 33;
}
else
{
// Add to the buffer.
buf[bfidx] = cv;
}
}
// Open the file.
fd = open (fname.c_str (), O_WRONLY | O_CREAT, 0660);
// Verify the file has been opened.
if (fd == -1)
{
cout << get_datetime_string() << "Write open of " << fname
<< " failed. Errno: " << errno << endl;
}
else
{
// Total bytes written.
uint64_t written = 0;
// Notify the start of the test.
cout << get_datetime_string() << "Write test started" << endl;
// Elapsed time.
struct timeval tv = { 0 };
get_elapsed_time (&tv);
struct timeval write_tv = tv;
// Run until it is time for the test to stop.
while (written < READ_LIMIT && zero_writes < 10)
{
ssize_t writesize = write (fd, &buf[0], blocksize);
if (writesize == -1)
{
cout << get_datetime_string << "Write failure. Errno: " << errno << endl;
zero_writes = 10;
}
else if (0 == writesize)
{
cout << get_datetime_string() << "Zero bytes written" << endl;
zero_writes++;
}
else
{
written += writesize;
}
}
string flush_command = "nvme flush /dev/nvme0n1p";
flush_command += fname[9];
system(flush_command.c_str());
// Get the elapsed time.
get_elapsed_time (&write_tv);
// Report the number of bytes written.
cout << get_datetime_string() << "Write " << written << " bytes in "
<< write_tv.tv_sec << "." << write_tv.tv_usec
<< " seconds" << endl;
// Close the file.
close (fd);
// Get the elapsed time.
get_elapsed_time (&tv);
// Report the number of bytes read.
cout << get_datetime_string() << "Write closed. " << written
<< " Bytes written in " << tv.tv_sec << "." << tv.tv_usec
<< " seconds" << endl;
// Report the number of bytes per second.
cout << get_datetime_string() << "Bytes per second "
<< bytes_per_second (&tv, written) << endl;
// Report the cache flush time.
struct timeval flush_tv = { 0 };
timersub (&tv, &write_tv, &flush_tv);
cout << get_datetime_string() << "System cache flush completed in "
<< flush_tv.tv_sec << "." << flush_tv.tv_usec << "seconds" << endl;
// Set the function return status when all write operations have
// been successful.
if (zero_writes < 10)
{
status = true;
}
}
return status;
}
Os dados que estou recebendo parecem
Os números estão próximos dos throughputs teóricos máximos do Samsung 950 Pro, mas alguns são muito altos e isso me incomoda. Por que posso estar recebendo números mais altos do que o rendimento máximo teórico do Samsung 950 Pro?
Tags performance ssd disk samsung nvme