Outra olhada na pergunta "Preciso de desfragmentação para SSD"

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 -


ps

fio; 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 :


50+200+800+4000
intel S3510 SSDSC2BB480G610.710.710.810.810.8
toshiba XG5 KXG50ZNV512G1.92.93.74.86.8
samsung PM963 MZQLW960HMJP2.83.23.53.74.2
samsung PM983 MZQLB960HAJR3.33.63.43.43.4
samsung PM981 MZVLB1T0HALR1.81.82.12.53.5
samsung PM1725b MZPLL1T6HAJQ1.81.92.02.32.9
micron 5200 eco9.39.810.412.210.7
samsung PM883 MZ7LH1T9HMLT7.97.98.18.18.0
intel P3520 (win)5.85.96.06.15.8
intel P4500 (win)4.24.24.34.44.3

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.


All Articles