为什么使用 MTP 设备时 rsync 如此慢?

为什么使用 MTP 设备时 rsync 如此慢?

为了使用 定期备份我的手机(Samsung A5 2016 或SM-A510Frsync,我使用了以下命令:

rsync --verbose --progress --omit-dir-times --no-perms --recursive --inplace --progress /run/user/1000/gvfs/mtp\:host\=%5Busb%3A002%2C018%5D/Phone/ /data/phone_back_folder/
  • 1000显然,是我的用户的 UID
  • mtp\:host\=%5Busb%3A002%2C018%5D是安装时为我的手机提供的临时 MTP 主机名(每次安装设备时都会以某种方式更改)
  • --omit-dir-times之所以--no-perms在这里,是因为 MTP 显然不这样做

由于我使用该--progress标志,我可以看到每个文件的估计传输速度,例如:

Phone/DCIM/Camera/20180408_184356.jpg
      2,814,075 100%   16.58MB/s    0:00:00 (xfr#265, to-chk=821/1262)

但这些数字令人难以置信,因为大多数时候,系统似乎处于空闲状态,等待下一个文件传输。

$ dstat -cd --disk-util --disk-tps
----total-cpu-usage---- -dsk/total- sda--sdb--sdc- -dsk/total-
usr sys idl wai hiq siq| read  writ|util:util:util|reads writs
  6   1  93   0   0   0| 344k  166k|0.03:0.37:1.43|   5     6 
  2   0  98   0   0   0|4096B    0 |   0:   0:   0|   0     0 
  3   0  97   0   0   0|   0    52k|   0:1.20:   0|   0     2 
 13   1  87   0   0   0|   0     0 |   0:   0:   0|   0     0 
  3   1  96   0   0   0|   0     0 |   0:   0:   0|   0     0 
  3   0  97   0   0   0|   0   152k|0.80:   0:   0|   0     2 
  3   0  97   0   0   0|   0   648k|   0:3.20:   0|   0    78 
  4   0  96   0   0   0|   0     0 |   0:   0:   0|   0     0 
  3   0  97   0   0   0|   0     0 |   0:   0:   0|   0     0 
  7   1  92   0   0   0|   0     0 |   0:   0:   0|   0     0 
  5   0  94   0   0   0|   0     0 |   0:   0:   0|   0     0 
  6   1  94   0   0   0|   0    12k|   0:0.40:   0|   0     2 
  6   1  93   0   0   0|   0     0 |   0:   0:   0|   0     0 
  6   0  94   0   0   0|   0     0 |   0:   0:   0|   0     0 
  7   1  91   0   0   0|   0   188k|   0:0.80:   0|   0     3 
  4   1  95   0   0   0|   0     0 |   0:   0:   0|   0     0 
  4   0  96   0   0   0|4096B   44M|8.80:   0:   0|   1   189 
  7   1  92   0   0   0|   0   172k|   0:3.20:   0|   0    18 
  6   1  93   0   0   0|   0     0 |   0:   0:   0|   0     0 
  3   0  96   0   0   0|   0     0 |   0:   0:   0|   0     0 
  6   1  93   0   0   0|   0     0 |   0:   0:   0|   0     0 
  6   0  93   0   0   0|   0     0 |   0:   0:   0|   0     0 
  7   2  91   0   0   0|   0   116k|   0:0.80:   0|   0     4 
  5   1  94   0   0   0|   0     0 |   0:   0:   0|   0     0 
  3   1  96   0   0   0|   0     0 |   0:   0:   0|   0     0 
  4   0  96   0   0   0|   0     0 |   0:   0:   0|   0     0 
  4   1  95   0   0   0|   0     0 |   0:   0:   0|   0     0 
  5   0  94   0   0   0|   0     0 |   0:   0:   0|   0     0 
  5   0  94   0   0   0|   0   224k|   0:0.80:   0|   0     3 
  5   1  93   0   0   0|   0     0 |   0:   0:   0|   0     0 
  5   1  95   0   0   0|   0     0 |   0:   0:   0|   0     0 
 12   3  85   0   0   0|   0     0 |   0:   0:   0|   0     0 
  8   1  91   0   0   0|   0   604k|   0:   0:   0|   0    59 
  5   0  94   0   0   0|   0    84k|   0:1.20:   0|   0     2 
  5   0  94   0   0   0|   0     0 |   0:   0:   0|   0     0 
  4   0  96   0   0   0|   0     0 |   0:   0:   0|   0     0 
  3   0  97   0   0   0|   0     0 |   0:   0:   0|   0     0

更新:在卸载并重新安装 MTP 设备后,我又运行了一次,dstat它启动得更快,并且在大部分时间里又回到了空闲状态。

$ dstat -cd --disk-util --disk-tps
----total-cpu-usage---- -dsk/total- sda--sdb--sdc- -dsk/total-
usr sys idl wai hiq siq| read  writ|util:util:util|reads writs
  5   1  94   0   0   0| 219k  603k|0.02:0.36:1.59|   3     7 
  6   3  90   1   0   0|  12k   25M|   0:   0:12.8|   3    44 
  5   2  86   7   0   0|   0    41M|   0:   0:64.0|   0    68 
  5   3  92   0   0   0|4096B 2744k|   0:2.00:1.60|   1   101 
  5   2  92   0   0   0|  20k    0 |   0:   0:3.60|   5     0 
  5   2  92   0   0   0|  16k    0 |   0:   0:2.40|   4     0 
  6   3  90   1   0   0|  12k   17M|   0:   0:14.0|   3    27 
  5   2  78  14   0   0|  12k   69M|   0:   0:92.0|   3   113 
  7   2  90   0   0   0|  12k    0 |   0:   0:2.80|   3     0 
  5   3  92   0   0   0|  12k   68k|   0:0.40:2.00|   3     2 
  6   2  92   0   0   0|  20k    0 |   0:   0:2.40|   5     0 
  5   2  94   0   0   0|4096B    0 |   0:   0:0.80|   1     0 
  3   1  91   5   0   0|   0    62M|   0:   0:45.2|   0   106 
  4   1  90   6   0   0|   0  2500k|   0:1.20:49.6|   0    67 
  4   1  95   0   0   0|   0   104k|   0:0.40:   0|   0     2 
  4   1  95   0   0   0|   0   192k|   0:0.80:   0|   0     3 
  4   2  94   0   0   0|   0    28k|0.40:   0:   0|   0     3 
  4   1  95   0   0   0|   0    40k|   0:   0:2.40|   0     2 
  4   1  95   0   0   0|   0     0 |   0:   0:   0|   0     0 
  4   2  94   0   0   0|   0     0 |   0:   0:   0|   0     0 
  4   1  95   0   0   0|   0    48k|   0:0.40:   0|   0     2 
  3   1  95   0   0   0|   0    16k|   0:   0:   0|   0     4 
  4   1  95   0   0   0|   0     0 |   0:   0:   0|   0     0 
  4   1  96   0   0   0|   0     0 |   0:   0:   0|   0     0 
  4   2  94   0   0   0|   0   332k|   0:   0:   0|   0    59 
  4   1  95   0   0   0|   0     0 |   0:   0:   0|   0     0 
  3   1  96   0   0   0|   0     0 |   0:   0:   0|   0     0 
  4   2  95   0   0   0|   0    16k|   0:0.80:   0|   0     2 
  3   1  96   0   0   0|   0     0 |   0:   0:38.4|   0     0 
  6   2  92   0   0   0|   0   104k|   0:   0:10.4|   0    14 
  5   2  93   0   0   0|   0     0 |   0:   0:   0|   0     0 
  4   1  95   0   0   0|   0     0 |   0:   0:   0|   0     0 
  3   1  95   0   0   0|   0   448k|   0:   0:   0|   0     1 
  3   1  95   0   0   0|   0    48k|   0:0.80:   0|   0     2 
  3   1  96   0   0   0|   0    32k|   0:   0:   0|   0     7 
  4   1  94   0   0   0|   0   548k|   0:2.00:   0|   0    66 
  4   1  95   0   0   0|   0    92k|   0:1.60:   0|   0     9 
  3   1  96   0   0   0|   0    28k|   0:1.20:   0|   0     3 
  7   1  92   0   0   0|   0     0 |   0:   0:   0|   0     0 
  3   2  95   0   0   0|   0     0 |   0:   0:   0|   0     0 
  3   1  96   0   0   0|   0     0 |   0:   0:   0|   0     0 
  3   1  96   0   0   0|   0   384k|   0:   0:   0|   0    44 
  4   2  95   0   0   0|   0    60k|   0:0.80:   0|   0     2 
  3   1  96   0   0   0|   0     0 |   0:   0:2.40|   0     0 
  3   1  96   0   0   0|   0  2560k|   0:   0:47.6|   0     5 
  4   2  94   0   0   0|   0     0 |   0:   0:   0|   0     0 
  3   2  95   0   0   0|   0   520k|   0:0.40:   0|   0    48 
  3   1  96   0   0   0|   0     0 |   0:   0:   0|   0     0

我想知道是否一切正常,并且无论哪种方式,为什么 MTP 传输如此慢,尤其是通过rsync.

按照这个速度,备份我的手机数据(没有之前的备份)似乎需要几个小时,这不是我真正可以做的完全备份。对于增量备份来说,这可能是可以接受的,但这不是这里的问题。

郑重声明一下,上次我尝试使用 Shotwell 之类的工具备份照片(那是不久前的事),似乎并没有花费很长时间(但我并没有太关注它)。

  • 除了使用不同的库来处理 MTP 访问之外,还有什么会产生影响呢?
  • 目前 Linux 上的 MTP 支持状况如何?我听说有些人使用jmtpfsFUSE 安装 MTP 设备,但并非总是没有问题。
  • 如果我错了,请纠正我,但我认为gvfslibmtp在幕后使用。

系统和机器详细信息

$ uname -svro
Linux 4.9.0-8-amd64 #1 SMP Debian 4.9.144-3.1 (2019-02-19) GNU/Linux

$ lsusb | grep MTP
Bus 002 Device 018: ID 04e8:6860 Samsung Electronics Co., Ltd Galaxy (MTP)

$ lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda      8:0    0 238.5G  0 disk 
├─sda1   8:1    0 107.8G  0 part /
├─sda2   8:2    0  13.5G  0 part [SWAP]
├─sda3   8:3    0   500M  0 part 
└─sda4   8:4    0 116.7G  0 part 
sdb      8:16   0 119.2G  0 disk 
└─sdb1   8:17   0 119.2G  0 part /home
sdc      8:32   0   2.7T  0 disk 
└─sdc1   8:33   0   2.7T  0 part /data
  • 我手机中的数据写入sdc1硬盘的唯一分区。

  • 正如您所看到的,sda这是根文件系统和交换区(以及与此处无关的其他分区sda3sda4)的所在位置,而sdb专用于我的home目录。

答案1

MTP 是一种古老的协议,手机制造商很懒,通常会实现参考实现(发货速度很快!)。 MTP 很慢,因为它一开始就设计得很快。

除此之外,rsync 需要遍历所有文件来找到它们,以便将其与现有文件进行比较,并且由于驱动程序尝试将文件列表模拟为文件系统,因此您还可以在点击实际的 MTP 列表之前添加更多层,这也需要时间。对于 rsync 找到的每个文件,它都会添加到要复制的文件列表中,并重新估计剩余时间。找到下一个发现,列表会变长,估计也会增加。

也许将所有图像复制到临时文件夹,然后在临时文件夹和存储文件夹之间进行 rsync?

答案2

rsync 使用基于 POSIX 流的输入输出模型,具有 open(2)、lseek(2)、read(2) 和 write(2) 等系统调用,而 MTP 是一种基于对象的协议,具有更高级别的操作,如“复制对象”。 MTP对部分修改文件的支持较差,并且必须用MTP协议手段低效地模拟相应的POSIX功能。

要将大量文件复制到 MTP 驱动器,您最好使用 GNOME 文件管理器,右键单击文件夹并选择“复制到”。这使用了更高级别的 MTP 文件复制操作,并且比 rsync 快得多。

由于这个原因和其他兼容性原因(文件名、权限、时间戳等),MTP 对于从 Linux 系统备份数据来说是一个糟糕的选择。

相关内容