Sin lugar a dudas, la pregunta planteada en el título del artículo no es nueva, se ha planteado más de una vez y se ha llegado a un consenso al respecto "no es realmente necesario e incluso puede ser perjudicial".
Sin embargo, la discusión reciente en los comentarios me hizo pensar de nuevo.
Con el tiempo, cualquier SSD seguirá fragmentándose fuertemente (internamente, en FTL) ... Una SSD recién grabada con lectura lineal dará una alta velocidad, pero si ya ha funcionado, será mucho más baja, ya que será lineal solo para usted.
Sí, por lo general esto no debería suceder: o escribimos "poco a poco" en archivos pequeños / pequeños bloques de metainformación del FS (cuya velocidad de lectura lineal realmente no nos importa), o escribimos "mucho" en archivos grandes y todo estará bien. También sucede que agrega bloques pequeños a archivos grandes, por ejemplo, registros, pero son relativamente de corta duración y no veo ningún problema en particular aquí.
Pero fue fácil imaginar un escenario muy real, en el que puede ocurrir la misma fragmentación interna de la SSD: un archivo de base de datos en el que hay una grabación aleatoria bastante activa. Con el tiempo, (quedando sin fragmentar en el nivel del sistema operativo) estará físicamente muy fragmentado, lo que puede reducir significativamente la velocidad de exploración de secuencia, copia de seguridad, etc.
Para la verificación, escribí un script y ejecuté pruebas.
Spoiler: el problema está presente (afecta significativamente el rendimiento) en solo uno de los modelos que se presentaron (y el fabricante lo coloca no como un centro de datos, sino como una computadora de escritorio / portátil).
¿Que es todo esto? ¿Qué más fragmentación dentro del SSD?, SSD . NAND flash ( ) . SSD 512- ( 4096-) , .
- , , FTL (flash translation layer): flash- , ( ) , , - log- .
, , , , — .
, FTL, , , , . , .
.
La idea del guión: creamos un archivo de varios gigabytes, lleno de datos aleatorios, medimos la velocidad de las lecturas secuenciales.
Luego, usando el acceso aleatorio, reescriba parte del archivo de prueba y vuelva a medir la velocidad de la lectura lineal. Si nuestras sospechas son ciertas, entonces la lectura del archivo será más lenta.
Después de cada escritura, hacemos tres operaciones de lectura con un retraso entre ellas en caso de que alguna unidad en segundo plano realice la desfragmentación y luego la velocidad de lectura mejore.
, SSD, , - , , . - , , , , , .
TRIM: SSD «», , FTL. NAND flash, . , , . SSD , .
, , , .
, SSD ( linux /dev/urandom
).
.
linux c dash, coreutils fio debian buster, , freebsd «».
echo preparing...
dd if=/dev/urandom of=testfile bs=1M count=4096 status=none
sync
for A in 1 2 3; do
sleep 10
dd if=testfile of=/dev/null bs=1M iflag=direct
done
for A in 50 200 800 4000; do
echo fio: write ${A}M...
fio --name=test1 --filename=testfile --bs=4k --iodepth=1 --numjobs=1 --rw=randwrite --io_size=${A}M --randrepeat=0 --direct=1 --size=4096M > /dev/null
sync
for B in 1 2 3; do
echo sleep ${B}0
sleep ${B}0
dd if=testfile of=/dev/null bs=1M iflag=direct
done
done
echo sleep 3600
sleep 3600
dd if=testfile of=/dev/null bs=1M iflag=direct
, NVMe- intel windows; , stackexchange -
psfio
; exe- .
$testfile = "c:\temp\testfile"
$fio = "c:\temp\fio-3.18-x64\fio"
echo "preparing..."
$filestream = New-Object System.IO.FileStream($testfile, "Create")
$binarywriter = New-Object System.IO.BinaryWriter($filestream)
$out = new-object byte[] 1048576
For ($i=1; $i -le 4096; $i++) {
(new-object Random).NextBytes($out);
$binarywriter.write($out)
}
$binarywriter.Close()
For ($i=1; $i -le 3; $i++) {
sleep 10
$time = Measure-Command {
Invoke-Expression "$fio --name=test1 --filename=$testfile --bs=1M --iodepth=1 --numjobs=1 --rw=read --direct=1 --size=4096M" *>$null
}
$seconds = $time.Minutes*60+$time.Seconds+$time.Milliseconds/1000
echo "read in $seconds"
}
foreach ($A in 50,200,800,4000) {
echo "fio: write ${A}M..."
Invoke-Expression "$fio --name=test1 --filename=$testfile --bs=4k --iodepth=1 --numjobs=1 --rw=randwrite --io_size=${A}M --randrepeat=0 --direct=1 --size=4096M" *>$null
For ($i=10; $i -le 30; $i+=10) {
echo "sleep $i"
sleep $i
$time = Measure-Command {
Invoke-Expression "$fio --name=test1 --filename=$testfile --bs=1M --iodepth=1 --numjobs=1 --rw=read --direct=1 --size=4096M" *>$null
}
$seconds = $time.Minutes*60+$time.Seconds+$time.Milliseconds/1000
echo "read in $seconds"
}
}
rm $testfile
:
- : , «» ( ) , ;
- windows - (, , , );
- ( ) .
( ) 4 :
DC ( — /); SATA, NVMe, , .
, PM981 ( , , ), — 3.5 , SATA .
, , .
: SSD , , , ( intel, , ; samsung , ).
(, - NAND flash).
XG5: , SMART >>150, — 300-400 , flash , SSD.
: mysql 100. , , «» mysql ( 600/), (>2/).
SSD, : , , . , downtime ( - ). , , .
( ) SSD:
sync
fsfreeze -f /mountpoint
dd if=/dev/nvme0n1p2 of=/dev/nvme0n1p2 bs=512M iflag=direct oflag=direct status=progress
fsfreeze -u /mountpoint
«» . - , , , -. «»: 100%, SSD « , TRIM» ( , TRIM, , ).
, « » .
Resumen: la desfragmentación puede ser útil para algunos SSD, pero no es lo mismo (¿para nada?) Como para el HDD. Es importante para nosotros no solo que el archivo esté ubicado en una cadena continua de sectores, sino también que la grabación en estos sectores fue secuencial.
PD: Agradecería que los lectores ejecutaran el script en su lugar y dieran números para sus SSD, ya que mi selección de unidades es bastante unilateral.