为什么写入现有文件比写入新的空文件更快?

为什么写入现有文件比写入新的空文件更快?

我使用 MappedByteBuffer 在 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);

如果testFile已经写入500MB,并且写入500MB数据两次,需要1s。但是当我rm testFile,写入500MB数据时,需要4s。

为什么覆盖文件比写入新文件更快?如何才能像覆盖文件一样更快地写入新文件?

答案1

覆盖或创建新文件是否更快取决于文件系统类型。许多文件系统会就地覆盖文件数据;那么覆盖速度更快,因为它只需要写入数据,而创建新文件则需要先分配空间,然后在新分配的空间中写入数据。但我预计不会有很大的差异。某些文件系统不会覆盖现有块(以允许要撤消的写入),然后通过写入新数据并删除旧数据来覆盖现有文件。但我不认为这两种情况会有很大差异。

底层可能具有类似的效果,使一项操作的成本高于另一项操作的成本。例如,在保留快照的系统上进行覆盖会保留旧数据,以便可以恢复快照。闪存介质只能批量擦除,因此新数据会写入空闲扇区,但覆盖某些数据最终会导致其被释放,这需要时间。

到目前为止,对读写时序影响最大的是缓冲和缓存。确保您在已知的缓存配置中进行基准测试(您可能应该在开始每个基准测试操作之前刷新磁盘缓存)并以所有写入的缓冲区结束(通过调用完成sync),除非您想测量热缓存/缓冲区计时。例如,执行两次连续写入(其中第一次写入仅写入内存缓冲区)不会比执行一次写入花费更多。

无论如何,如果需要 4 秒才能完成您想要的操作,那么就需要 4 秒。没有什么神奇的方法可以让它快 4 倍。

答案2

使用快速测试dd表明将数据附加到文件并不更快:

我的测试文件大小是 1024MB。最终附加文件大小为 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

测试.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

相关内容