Sem dúvida, a questão colocada no título do artigo não é nova, foi levantada mais de uma vez e foi alcançado um consenso sobre o assunto “não é realmente necessário e pode até ser prejudicial”.
No entanto, a recente discussão nos comentários me fez pensar novamente.
Com o tempo, qualquer SSD ainda se fragmentará fortemente (internamente, em FTL) ... Um SSD recém-gravado com leitura linear dará uma alta velocidade, mas se já tiver funcionado, será muito menor, porque será linear apenas para você.
Sim, geralmente isso não deve acontecer: ou escrevemos "pouco a pouco" em arquivos pequenos / pequenos blocos de meta-informações do FS (cuja velocidade de leitura linear não nos interessa realmente) ou escrevemos "muito" em arquivos grandes e tudo ficará bem. Também acontece que você adiciona pequenos blocos a arquivos grandes - logs, por exemplo, mas eles são relativamente curtos e não vejo nenhum problema específico aqui.
Mas era fácil imaginar um cenário muito real, no qual toda a mesma fragmentação interna do SSD pode ocorrer: um arquivo de banco de dados no qual existe uma gravação aleatória bastante ativa. Com o tempo, ele (permanecendo sem fragmentação no nível do sistema operacional) ficará fisicamente muito fragmentado, o que pode reduzir significativamente a velocidade da verificação seq, do backup etc.
Para verificação, escrevi um script e executei testes.
Desmancha prazeres: o problema está presente (afeta significativamente o desempenho) em apenas um dos modelos que vieram à mão (e é posicionado pelo fabricante não como um data center, mas como um desktop / laptop).
Sobre o que é tudo isso? O que mais fragmentação dentro do SSD?, SSD . NAND flash ( ) . SSD 512- ( 4096-) , .
- , , FTL (flash translation layer): flash- , ( ) , , - log- .
, , , , — .
, FTL, , , , . , .
.
A idéia do script: criamos um arquivo de vários gigabytes, preenchido com dados aleatórios, medimos a velocidade das leituras seqüenciais.
Em seguida, usando acesso aleatório, reescreva parte do arquivo de teste e meça novamente a velocidade da leitura linear. Se nossas suspeitas forem verdadeiras, agora a leitura do arquivo será mais lenta.
Após cada escrita, fazemos três operações de leitura com um atraso entre eles no caso de alguma movimentação na desfragmentação executa em segundo plano e , em seguida, a velocidade de leitura melhora.
, 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, , ).
, « » .
Resumo: A desfragmentação pode ser útil para alguns SSDs, mas não é a mesma coisa (nem mesmo ?) Quanto ao HDD. É importante para nós não apenas que o arquivo esteja localizado em uma cadeia contínua de setores, mas também que a gravação nesses setores seja seqüencial.
PS: Ficaria grato se os leitores executassem o script em seu lugar e dessem números para seus SSDs, já que minha seleção de unidades é bastante unilateral.