Zweifellos ist die im Titel des Artikels gestellte Frage nicht neu, sie wurde mehr als einmal aufgeworfen und es wurde ein Konsens darüber erzielt, „nicht wirklich benötigt und kann sogar schädlich sein“.
Die jüngste Diskussion in den Kommentaren hat mich jedoch zum Nachdenken gebracht.
Im Laufe der Zeit wird jede SSD immer noch stark fragmentiert (intern in FTL) ... Eine frisch aufgenommene SSD mit linearem Messwert liefert eine hohe Geschwindigkeit, aber wenn sie bereits funktioniert hat, ist sie viel niedriger, da sie nur für Sie linear ist.
Ja, normalerweise sollte dies nicht passieren: Entweder schreiben wir "Stück für Stück" in kleine Dateien / kleine Blöcke von Metainformationen des FS (deren lineare Lesegeschwindigkeit uns nicht wirklich wichtig ist), oder wir schreiben "viel" in große Dateien, und alles wird gut. Es kommt auch vor, dass Sie großen Dateien kleine Blöcke hinzufügen, z. B. Protokolle. Diese sind jedoch relativ kurzlebig und ich sehe hier keine besonderen Probleme.
Man konnte sich jedoch leicht ein sehr reales Szenario vorstellen, in dem dieselbe interne Fragmentierung der SSD auftreten kann: eine Datenbankdatei, in der eine ziemlich aktive Zufallsaufzeichnung vorliegt. Im Laufe der Zeit wird es (auf Betriebssystemebene unfragmentiert) physisch sehr fragmentiert sein, was die Geschwindigkeit von Seq-Scan, Backup usw. erheblich verringern kann.
Zur Überprüfung habe ich ein Skript geschrieben und Tests durchgeführt.
Spoiler: Das Problem ist nur bei einem der Modelle vorhanden (beeinträchtigt die Leistung erheblich) (und es wird vom Hersteller nicht als Rechenzentrum, sondern als Desktop / Laptop positioniert).
Worum geht es? Welche weitere Fragmentierung innerhalb der SSD?, SSD . NAND flash ( ) . SSD 512- ( 4096-) , .
- , , FTL (flash translation layer): flash- , ( ) , , - log- .
, , , , — .
, FTL, , , , . , .
.
Die Idee des Skripts: Wir erstellen eine Datei mit mehreren Gigabyte, die mit zufälligen Daten gefüllt ist, und messen die Geschwindigkeit sequentieller Lesevorgänge.
Schreiben Sie anschließend mit wahlfreiem Zugriff einen Teil der Testdatei neu und messen Sie erneut die Geschwindigkeit des linearen Lesens. Wenn unser Verdacht wahr ist, wird das Lesen aus der Datei jetzt langsamer.
Nach jedem Schreibvorgang führen wir drei Lesevorgänge mit einer Verzögerung zwischen ihnen aus, falls ein Laufwerk im Hintergrund eine Defragmentierung durchführt und sich dann die Lesegeschwindigkeit verbessert.
, 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, , ).
, « » .
Zusammenfassung: Die Defragmentierung kann für einige SSDs nützlich sein , ist jedoch nicht ganz dasselbe (überhaupt nicht?) Wie für die Festplatte. Für uns ist es nicht nur wichtig, dass sich die Datei in einer fortlaufenden Kette von Sektoren befindet, sondern auch, dass die Aufzeichnung in diesen Sektoren sequentiell war.
PS Ich wäre dankbar, wenn die Leser das Skript an ihrer Stelle ausführen und Nummern für ihre SSDs angeben würden, da meine Auswahl an Laufwerken eher einseitig ist.