Estou fazendo um programa para mover o local da partição por diversão. Ele basicamente encontra a partição lendo o esquema de partição como GPT ou MBR, então ele lê um setor( 512B
) da partição e então grava no novo local. Mas por algum motivo esse processo é muito lento, na verdade essa unidade vai até 2 GB/s mas esse processo está conduzindo apenas a 700 KB/s. É porque eu deveria ler/gravar dados brutos maiores de uma vez e por quê? Existe algum outro truque que eu possa fazer para acelerar? Ele está testando em um HP P900 1TB Portable SSD
. Eu também editei o código para fazê-lo ler/gravar com 1 página SSD inteira que é 4096B
. O desempenho proliferou para 8Mb/s
mas isso ainda não está nem remotamente perto do desempenho que eu estou esperando. Então eu fiz ele mover 1 Gib por rodada, e ele foi capaz de atingir a velocidade de 1 Gib/S. Mas já que o tamanho da página do SSD é de apenas 4 KB por que haveria uma diferença em termos de desempenho entre r/w 4kib
de uma vez e 1gib
de uma vez?
relate perguntas
-
Sistema que pode ler o disco rígido e gravar exclusivamente na RAM?
-
Devo substituir/atualizar meu disco rígido após 5 anos?
-
Devo particionar um SSD secundário (sem sistema operacional) usado para armazenamento? [fechado]
-
A execução do CrystalDiskMark causa BSOD no Windows 10
-
O fenômeno 'Write cliff' só acontece com discos SSD?
Com tamanho pequeno (512 bytes) onde você deve mover pelo menos centenas de megabytes, você está enfrentando problemas com setores de 4096 bytes - no cenário real, você está lendo 4096 bytes da fonte, depois lendo dados de destino (4096 B), adicionando seus 512 bytes a isso e gravando novamente 4096 bytes. Discos SSD têm setores de 4096, então quando você move apenas 512 bytes, a unidade precisará ler 4096 bytes. Ela é projetada dessa forma.
Além disso, quando você move megabytes, você deve tomar cuidado se estiver movendo os dados para frente ou para trás. Se for para trás - você não deve sobrescrever os próximos dados que serão movidos. Se for para frente - não há problema aqui. Isso é resolvido na instrução assembler memcpy, que se os dados de destino estiverem antes na RAM (aqui no disco), ele moverá os dados do fim, não do início.
Então sua solução é mover muito mais dados, eu digo 100 MB de uma vez. Pare de mover tantos dados quando chegar ao fim da partição, mova apenas parte deles então. E finalmente se você mover dados de volta, você deve movê-los do fim, não do começo. Somente se você estiver sobrescrevendo o mesmo espaço de onde você leu.
Com 512 bytes movidos, você está perdendo muito tempo com duas coisas:
É provável que a maior parte do seu tempo seja gasto emitindo solicitações de leitura/gravação em vez de realmente ler/escrever alguma coisa.
Se meus cálculos estiverem corretos, então 2 GB/s se traduzem em aproximadamente 0,3 µs para ler 512 bytes, mas sempre há uma latência diferente de zero para cada solicitação, que eu acho que é em torno de 100 µs? – então, se você ler um megabyte usando solicitações individuais de 512 bytes (0,3 × 2048 + 100 × 2048), então 99,997% do seu tempo total será "desperdiçado" fazendo a solicitação.
Enquanto isso, se você fizer uma única solicitação de leitura de 1 megabyte (0,3×2048 + 100×1), então a sobrecarga de fazer a solicitação é de apenas 14%, e com uma leitura de 128 MB é de 0,1%. [Esses são números muito aproximados.]
(Para HDDs, seria igualmente lento – um HDD SATA moderno pode ler ou gravar a ~200 MB/s, desde que esteja lendo um bloco contínuo, mas se você o forçar a buscar do local de "leitura" para o local de "gravação" todas as vezes, então facilmente 90% do seu tempo total será gasto movendo as cabeças e não realmente lendo/gravando.)
Então o "truque" é realmente fazer solicitações maiores e em menor quantidade.