2

Я заметил огромную разницу между следующими двумя сценариями копирования файла:

  1. Копирование файла в новый файл.
  2. Копирование файла в существующий файл и его перезапись.

Я ожидаю, что обе операции занимают одинаковое количество времени. Но первый сценарий намного быстрее на практике. Я пробовал это на двух разных файловых системах, получая одинаковый результат. Есть идеи, почему первый сценарий намного быстрее?

Пример в Linux:

$ dd bs=1024 count=1000000 if=/dev/zero of=dummyfile.txt
1000000+0 records in
1000000+0 records out
1024000000 bytes (1.0 GB) copied, 7.45639 s, 137 MB/s
$ while [ "1" == "1" ]; do time cp dummyfile.txt dummyfile2.txt ; rm dummyfile2.txt ; done

real    0m0.850s
user    0m0.003s
sys     0m0.847s

real    0m0.778s
user    0m0.000s
sys     0m0.776s

real    0m0.775s
user    0m0.004s
sys     0m0.772s

real    0m0.775s
user    0m0.003s
sys     0m0.770s

real    0m0.776s
user    0m0.008s
sys     0m0.766s
^C
$ rm dummyfile2.txt -f
$ while [ "1" == "1" ]; do time cp dummyfile.txt dummyfile2.txt ;  done

real    0m0.839s
user    0m0.003s
sys     0m0.834s

real    0m6.056s
user    0m0.005s
sys     0m1.683s

real    0m6.614s
user    0m0.002s
sys     0m1.405s

real    0m6.858s
user    0m0.003s
sys     0m1.436s

РЕДАКТИРОВАТЬ: тест выполняется на диске SSD. Я наблюдал такую же тенденцию на HDD, но разрыв ниже, чем на SDD (в 2-3 раза). На следующей странице объясняется, почему твердотельные накопители значительно медленнее перезаписывают жесткие диски:

Trim (вычислительная) страница Википедии

2 ответа2

2

На самом деле физическое копирование занимает столько же времени. Но драйвер файловой системы ext4 close() ожидает, пока данные действительно не будут записаны, когда операция выполняется на существующем i-узле, и не ожидает операции записи, если она выполняется на новом узле. Я провел несколько экспериментов и понял, что это особенность ext4. Я не видел такой разницы с копированием на btrfs, zfs, ext3, ext.

Как я могу сказать, что закрытие - это трудоемкая операция? strace предоставляет информацию:

$ strace -tt -T cp bigfile newfile
...
14:36:41.985437 open("bigfile", O_RDONLY)   = 3 <0.000009>
14:36:41.985466 fstat(3, {st_mode=S_IFREG|0664, st_size=647608649, ...}) = 0 <0.000007>
14:36:41.985495 open("newfile", O_WRONLY|O_CREAT|O_EXCL, 0664) = 4 <0.000086>
14:36:41.985602 fstat(4, {st_mode=S_IFREG|0664, st_size=0, ...}) = 0 <0.000007>
14:36:41.985633 fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0 <0.000008>
... a lot of reads and writes
14:36:43.584223 close(4)                = 0 <0.000009>
14:36:43.584248 close(3)                = 0 <0.000008>
...
$ strace -tt -T cp bigfile existingfile
...
14:36:52.393034 open("bigfile", O_RDONLY)   = 3 <0.000010>
14:36:52.393071 fstat(3, {st_mode=S_IFREG|0664, st_size=647608649, ...}) = 0 <0.000009>
14:36:52.393104 open("existingfile", O_WRONLY|O_TRUNC) = 4 <0.097058>
14:36:52.490211 fstat(4, {st_mode=S_IFREG|0664, st_size=0, ...}) = 0 <0.000007>
14:36:52.490278 fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0 <0.000009>
... a lot of reads and writes
14:36:54.047408 close(4)                = 0 <5.346015>
14:36:59.393466 close(3)                = 0 <0.000011>
...

Обратите внимание, что close(4) занимает более 5 секунд, тогда как в случае копирования в существующий файл и непосредственно при создании нового файла.

Я запускаю iostat, чтобы проверить, что делает система. Чтение bigfile было выполнено перед тестом, чтобы избежать эффекта кэширования файловой системы.

# iostat sda 1 100
Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               0.00         0.00         0.00          0          0
sda               0.00         0.00         0.00          0          0
--------------- copy to a new file starts here -----------------------
sda              24.00         0.00      8340.00          0       8340
sda             174.00         8.00     86596.00          8      86596
sda             170.00         0.00     86020.00          0      86020
--------------- copy to a new file finishes here ---------------------
sda             177.00         4.00     90112.00          4      90112
sda             176.00         4.00     89600.00          4      89600
sda             166.00         0.00     84992.00          0      84992
sda             161.00         4.00     81920.00          4      81920
sda             157.00         0.00     78888.00          0      78888
sda              52.00         0.00     26224.00          0      26224
sda               0.00         0.00         0.00          0          0
sda               0.00         0.00         0.00          0          0
sda               0.00         0.00         0.00          0          0
--------------- copy to the existing file starts here ----------------
sda              12.00         0.00      4128.00          0       4128
sda             172.00         4.00     87040.00          4      87040
sda             180.00         4.00     91648.00          4      91648
sda             175.00         0.00     89600.00          0      89600
sda             173.00         4.00     88064.00          4      88064
sda             168.00         4.00     83532.00          4      83532
sda             159.00         0.00     81408.00          0      81408
sda             181.00         4.00     92160.00          4      92160
sda              30.00         0.00     14960.00          0      14960
--------------- copy to the existing file finishes here --------------
sda               0.00         0.00         0.00          0          0
sda               3.00         0.00        28.00          0         28

Обратите внимание, что копирование в новый файл заканчивается до записи данных, а операция записи продолжается, хотя cp выполняется с точки зрения пользователя.

0

Перезапись требует операции поиска ...

Права доступа к файлу должны быть прочитаны, чтобы узнать, можете ли вы перезаписать его (что может быть или не быть проблемой в зависимости от вашей файловой системы). Также файл должен быть обрезан.

Для этого требуется, чтобы привод искал позицию, в которой находится файл.

Копирование в новый файл создает новые разрешения и использует для записи самые близкие свободные блоки и не требует поиска.

Изучите файловые системы «копирование при записи» (например, ZFS), которые этого не делают ..

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .