Последнюю пару лет я переносил со службы домой и обратно «набор рабочих материалов» — видеофайлы и данные проектов, пользуясь внешним SSD-диском стандарта NVMe с интерфейсом Thunderbolt.

Но, когда я синхронизировал данные, это всегда происходило очень медленно. В обычный рабочий день я могу создать новую папку проекта, содержащую 500-1000 файлов. При этом среди них будут дюжины файлов размером 1–10 Гб.
Мой Thunderbolt-диск способен передавать данные со скоростью, значительно превышающей 5 Гб/с, а 10-гигабитное сетевое соединение, имеющееся в моём распоряжении, может выдать 1 Гб в секунду. Недавно я даже обновил диск до Thunderbolt 5, хотя его и нельзя назвать узким местом моей системы.
Я использовал команду rsync
следующего вида для копирования файлов с общего сетевого ресурса, смонтированного на моём Mac, на диск, которому я дал имя Shuttle
:
rsync -au --progress --stats /Volumes/mercury/* /Volumes/Shuttle/Video_Projects
Ресурс mercury
назван именно так из-за того, что он представляет собой быстрый том, базирующийся на NVMe-диске, размещённом на моём NAS (Network-attached Storage, сетевое хранилище данных). Моё сетевое хранилище основано на архитектуре Arm, а все сетевые тома я называю в честь небесных тел.
Я, в качестве теста, удалил один из примерно дюжины активных проектов с диска Shuttle
и запустил копирование данных с помощью rsync
:
$ time rsync -au --progress --stats /Volumes/mercury/* /Volumes/Shuttle/Video_Projects
Radxa Orion O6/
Radxa Orion O6/.DS_Store
6148 100% 4.80MB/s 00:00:00 (xfer#1, to-check=1582/3564)
Radxa Orion O6/Micro Center Visit Details.pages
141560 100% 9.83MB/s 00:00:00 (xfer#2, to-check=1583/3564)
Radxa Orion O6/Radxa Orion O6.md
19817 100% 1.89MB/s 00:00:00 (xfer#3, to-check=1584/3564)
Radxa Orion O6/BIOS and Images/
Radxa Orion O6/BIOS and Images/orion-o6-bios-0.2.2-1.zip
3916964 100% 83.32MB/s 00:00:00 (xfer#4, to-check=1586/3564)
Radxa Orion O6/BIOS and Images/orion-o6-bios-9.0.0-apr-11.7z
4341505 100% 112.62MB/s 00:00:00 (xfer#5, to-check=1587/3564)
Radxa Orion O6/Scratch/
Radxa Orion O6/Scratch/bios 9.0.0 - screen acpi and debian 12 attempt.mp4
254240026 100% 114.11MB/s 00:00:02 (xfer#6, to-check=1589/3564)
...
Number of files: 3564
Number of files transferred: 122
Total file size: 244284287846 B
Total transferred file size: 62947785101 B
Unmatched data: 62947785101 B
Matched data: 0 B
File list size: 444318 B
File list generation time: 9.155 seconds
File list transfer time: 0.078 seconds
Total sent: 62955918871 B
Total received: 2728 B
sent 62955918871 bytes received 2728 bytes 128990035 bytes/sec
total size is 244284287846 speedup is 3.88
real 8:17.57
user 3:13.14
sys 2:45.45
Создание полной копии данных заняло около 8 минут, всего было скопировано около 59 ГиБ файлов. Тут имеются две проблемы:
Команда
rsync
копирует данные в однопоточном режиме, последовательно, то есть — в некий момент времени копируется только один файл.Даже копируя очень большие файлы rsync, похоже, при работе с этим сетевым ресурсом, выходит на максимальную скорость около 350 Мб/с.
Я поэкспериментировал с разными алгоритмами сжатия, пытался сначала задействовать tar
, а потом передавать rsync
то, что получилось. Я даже пробовал запускать демон rsync
вместо использования SSH… Но у меня ни разу не получалось значительно ускорить копирование! На самом деле, применение некоторых режимов сжатия даже замедляло работу, так как мой энергоэффективный NAS работает на достаточно медленных Arm-ядрах, что приводит к некоторому замедлению однопоточных программ.
Команда rclone приходит на помощь
Я многие годы использую команду rclone
, которая является частью моей стратегии резервного копирования «3-2-1». Эта команда замечательно копирует, перемещает, синхронизирует файлы, работая практически с любыми хранилищами (включая облачные хранилища данных, локальные хранилища, NAS-тома и так далее). А я, уж не знаю почему, навесил на неё ярлык инструмента, который предназначен для переноса данных из локального хранилища в облако и обратно. Я никогда не рассматривал rclone в роли команды, пригодной для локального переноса файлов, скажем — для работы с файлами в моей собственной LAN.
А у этой команды есть опция, которая позволяет организовать параллельную работу с файлами: --multi-thread-streams
. Применить её для решения похожих задач предложил кому-то пользователь Stack Overflow dantebarba.
Я решил эту опцию попробовать.
После некоторой возни с подбором точных параметров, соответствующих параметру -a
команды rsync
, после решения вопросов со странными символическими ссылками, вроде директорий .fcpcache
, которые Final Cut Pro запихивает в проекты, я создал следующую конструкцию:
rclone sync \
--exclude='**/._*' \
--exclude='.fcpcache/**' \
--multi-thread-streams=32 \
-P -L --metadata \
/Volumes/mercury/ /Volumes/Shuttle/Video_Projects
Применяя новый метод, я обнаружил, что сетевое соединение моего Mac быстро вышло на максимальную скорость передачи данных, находящуюся в районе 1 Гб/с. Копирование той же директории, что и раньше, заняло 2 минуты:
$ rclone sync \
--exclude='**/._*' \
--exclude='.fcpcache/**' \
--multi-thread-streams=32 \
--progress --links --metadata \
/Volumes/mercury/ /Volumes/Shuttle/Video_Projects
2025/05/06 12:03:57 NOTICE: Config file "/Users/jgeerling/.config/rclone/rclone.conf" not found - using defaults
Transferred: 58.625 GiB / 58.625 GiB, 100%, 0 B/s, ETA -
Checks: 2503 / 2503, 100%
Transferred: 122 / 122, 100%
Server Side Copies: 122 @ 58.625 GiB
Elapsed time: 2m15.3s
Мне не совсем понятно, почему rclone сообщает о копировании 59 Гб, а rsync — о 63 Гб. Может — это из-за исключения папки .fcpcache? Ох, насмешил — дело в единицах измерения — я пытался сравнивать GiB (ГиБ, гибибайты) и GB (Гб, гигабайты) ;).
Тут, в любом случае, у меня напрашивается следующий вывод, особенно после того, как я понаблюдал за полной загрузкой 10-гигабитного соединения: rclone
, при работе в параллельном режиме, примерно в 4 раза быстрее rsync
.
Ещё я провёл сравнения команд, просто заменив несколько файлов. Оказалось, что rclone
и rsync
работают с почти одинаковой скоростью, так как полное сканирование дерева каталогов в поиске изменений метаданных занимает и у одной, и у другой команды примерно одно и то же время (около 18 секунд). Команда rclone
выходит в лидеры только благодаря возможностям по параллельной передаче файлов.
О, а приходите к нам работать? ? ?
Мы в wunderfund.io занимаемся высокочастотной алготорговлей с 2014 года. Высокочастотная торговля — это непрерывное соревнование лучших программистов и математиков всего мира. Присоединившись к нам, вы станете частью этой увлекательной схватки.
Мы предлагаем интересные и сложные задачи по анализу данных и low latency разработке для увлеченных исследователей и программистов. Гибкий график и никакой бюрократии, решения быстро принимаются и воплощаются в жизнь.
Сейчас мы ищем плюсовиков, питонистов, дата-инженеров и мл-рисерчеров.
Комментарии (9)
Lx6g1ZG1
09.06.2025 09:52По идеологии Unix каждая программа выполняет одну свою функцию. В случае с rsync — копирование в одном потоке, а распараллеливание можно реализовать с помощью других инструментов (например, xargs, parallel).
Ryav
Интересно, почему в
rsync
не добавили подобный функционал, напрашивается же.Lx6g1ZG1
Можно как-то так: (используя parallel в 4 потока):
# find /source/dir -type f | parallel -j4 rsync -R {} user@remote:/destination
andreymal
Поздравляю, вы не только сломали синхронизацию свойств каталогов и опции вроде
--delay-updates
или--delete-after
, но и убили производительность постоянными переподключениями SSH-соединений (а ещё такая команда всё равно не работает, потому что parallel не умеет читать из stdin)Слепое следование идеологиям ни к чему хорошему не приводит
Lx6g1ZG1
это пример...приведите свой, который вам кажется лучшим.
Хотел показать что можно параллельно запускать задачи копирования используя rsync.
andreymal
Так вся эта статья посвящена этому самому примеру — rclone
Lx6g1ZG1
автор пишет в завершении статьи:
Команда rclone выходит в лидеры только благодаря возможностям по параллельной передаче файлов.
я привел пример что распараллеливание возможно и в случае с rsync. Про производительность ничего не говорил.
andreymal
Тогда в вашем примере тем более нет смысла
Lx6g1ZG1
однако вы его прокоментировали зачем-то