Por que gravar um arquivo existente é mais rápido do que gravar um novo arquivo vazio?

3

Eu uso o MappedByteBuffer para gravar arquivos no linux.

File file = new File("testFile");
RandomAccessFile raf = new RandomAccessFile(file, "rw");
FileChannel fc = raf.getChannel();
MappedByteBuffer mbf = fc.map(FileChannel.MapMode.READ_WRITE, 0, file.length());
mbf.put(buffer);

Se o testFile tiver 500MB de gravação e gravar os 500MB de dados duas vezes, será necessário 1s.mas quando eu testar o rfFile, gravar os 500MB de dados, serão necessários 4s.

Por que substituir um arquivo é mais rápido do que gravar um novo arquivo? Como posso escrever um novo arquivo tão rápido quanto substituir um arquivo?

    
por user209913 11.01.2017 / 20:14

2 respostas

2

Se a sobrescrita ou a criação de um novo arquivo é mais rápida depende do tipo de sistema de arquivos. Muitos sistemas de arquivos sobrescrevem dados de arquivos no lugar; então, a sobrescrita é mais rápida, pois exige apenas a gravação dos dados, enquanto a criação de um novo arquivo requer primeiro a alocação de espaço e a gravação dos dados no espaço recém-alocado. Eu não esperaria uma grande diferença embora. Alguns sistemas de arquivos não sobrescrevem um bloco existente (para permitir que uma gravação seja desfeita ) e, em seguida, sobrescrevem um O arquivo existente é feito escrevendo os novos dados, seguido da exclusão dos dados antigos. Eu não esperaria uma grande diferença em ambos os casos embora.

As camadas subjacentes podem ter efeitos semelhantes para tornar uma operação mais cara que a outra. Por exemplo, substituir em um sistema que mantém instantâneos mantém os dados antigos de modo que o instantâneo possa ser restaurado. A mídia Flash só pode ser apagada em massa para que novos dados sejam gravados em setores livres, mas a substituição de alguns dados acabará levando à sua liberação, o que leva tempo.

De longe, a coisa com o maior efeito no tempo de leitura e gravação é o armazenamento em buffer e o armazenamento em cache. Certifique-se de fazer seus benchmarks em uma configuração de cache conhecida (você deve provavelmente esvaziar o cache de disco antes de iniciar cada operação comparada) e termina com todos os buffers escritos (termine chamando sync ) a menos que você queira medir o cache quente / temporizações de buffers. Por exemplo, fazer duas gravações consecutivas em que a primeira gravação apenas grava em buffers de memória não custará muito mais do que fazer uma única gravação.

Em qualquer caso, se forem necessários 4s para realizar a operação desejada, serão necessários 4s. Não há maneira mágica de torná-lo 4 vezes mais rápido.

    
por 12.01.2017 / 01:36
1

Um teste rápido usando dd mostra que anexar dados a um arquivo não é mais rápido:

Meu tamanho de teste é 1024MB. O tamanho final do arquivo anexado é de 2048MB.

creating a new file
real    0m3,052s
user    0m0,523s
sys     0m0,578s

overwriting existing file
real    0m3,510s
user    0m0,695s
sys     0m0,867s

appending to existing file
real    0m3,226s
user    0m0,602s
sys     0m0,594s

deleting file
real    0m0,273s
user    0m0,086s
sys     0m0,195s

test.sh:

#!/usr/bin/env bash
printf "creating a new file\n"
time dd if=/dev/zero of=./test.img count=1024 bs=1M && sync -f

printf "\noverwriting existing file\n"
time dd if=/dev/zero of=./test.img count=1024 bs=1M && sync -f

printf "\nappending to existing file\n"
time dd if=/dev/zero bs=1M count=1024 >> ./test.img && sync -f

printf "\ndeleting file\n"
[[ -f ./test.img ]] && time rm ./test.img && sync -f
    
por 12.01.2017 / 01:19