Sans aucun doute, la question posée dans le titre de l'article n'est pas nouvelle, elle a été soulevée plus d'une fois et un consensus s'est dégagé à son sujet «pas vraiment nécessaire, et peut même être nuisible».
Cependant, la récente discussion dans les commentaires m'a fait réfléchir à nouveau.
Au fil du temps, tout SSD se fragmentera encore fortement (en interne, en FTL) ... Un SSD fraîchement enregistré avec une lecture linéaire donnera une vitesse élevée, mais s'il a déjà fonctionné, il sera beaucoup plus faible, car il ne sera linéaire que pour vous.
Oui, cela ne devrait généralement pas se produire: soit nous écrivons «petit à petit» dans de petits fichiers / petits blocs de méta-informations du FS (la vitesse de lecture linéaire dont nous ne nous soucions pas vraiment), soit nous écrivons «beaucoup» dans de gros fichiers et tout ira bien. Il arrive également que vous ajoutiez de petits blocs à des fichiers volumineux - des journaux, par exemple, mais ils sont relativement de courte durée et je ne vois aucun problème particulier ici.
Mais il était facile d'imaginer un scénario très réel, dans lequel la même fragmentation interne du SSD pourrait se produire: un fichier de base de données dans lequel il y a un enregistrement aléatoire assez actif. Au fil du temps, il (restant non fragmenté au niveau du système d'exploitation) sera physiquement très fragmenté, ce qui peut réduire considérablement la vitesse de numérisation, de sauvegarde, etc.
Pour vérification, j'ai écrit un script et exécuté des tests.
Spoiler: le problème est présent (affecte de manière significative les performances) sur un seul des modèles proposés (et il est positionné par le constructeur non pas comme un datacenter, mais comme un ordinateur de bureau / portable).
C'est à propos de quoi? Quoi d'autre fragmentation à l'intérieur du SSD?, SSD . NAND flash ( ) . SSD 512- ( 4096-) , .
- , , FTL (flash translation layer): flash- , ( ) , , - log- .
, , , , — .
, FTL, , , , . , .
.
L'idée du script: on crée un fichier de plusieurs gigaoctets, rempli de données aléatoires, mesure la vitesse des lectures séquentielles.
Ensuite, en utilisant l'accès aléatoire, nous réécrivons une partie du fichier de test et mesurons à nouveau la vitesse de lecture linéaire. Si nos soupçons sont vrais, alors la lecture du fichier va ralentir.
Après chaque écriture, nous faisons trois opérations de lecture avec un retard entre eux au cas où un lecteur dans la Défragmentation PerForm de fond et puis la vitesse de lecture améliorée.
, 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, , ).
, « » .
Résumé: La défragmentation peut être utile pour certains SSD, mais pas tout à fait la même (pas du tout?) Comme pour le disque dur. Il est important pour nous non seulement que le fichier soit situé dans une chaîne continue de secteurs, mais aussi que l'enregistrement dans ces secteurs soit séquentiel.
PS Je serais reconnaissant aux lecteurs d'exécuter le script à leur place et de donner des numéros pour leurs SSD, car ma sélection de disques est plutôt unilatérale.