使用写时复制 (COW) 复制 Python 中的文件
Copy file in Python with copy-on-write (COW)
我的文件系统 (FS)(特别是 ZFS)支持写时复制 (COW),即复制(如果做得好的话)是一种非常便宜的常量操作,实际上并不复制底层内容。内容只复制一次 write/modify 新文件。
实际上,我刚刚发现,ZFS-on-Linux 实际上还没有为用户空间实现它(对吧?)。
但是例如BTRFS 或 XFS 都有。
(参见 here,
here,
here,
here.)
对于 (GNU) cp
实用程序,您将传递 --reflink=always
选项
(参见 here。)
cp
调用 ioctl (dest_fd, FICLONE, src_fd)
(参见 here, here)。
如何在 Python 中获得此行为(如果可能)?
我假设“零拷贝”(例如 here via os.sendfile
) would not result in such behavior, right? Because looking at shutil
s _fastcopy_sendfile
implementation (here),它仍然是一个循环 os.sendfile
使用一些自定义字节数(应该是块大小,max(os.fstat(infd).st_size, 2 ** 23)
).还是会?
COW,这是文件级别的,还是块级别的?
如果可能的话,我希望它也是通用的和跨平台的,尽管我这里的问题有点 Linux 重点。
一个专门关于 Mac 的相关问题似乎是 。
MacOSX cp
具有克隆文件的 -c
选项。
在进一步搜索时,我确实找到了答案,以及相关的问题报告。
Issue 37157 (shutil: add reflink=False to file copy functions to control clone/CoW copies (use copy_file_range))
正是关于这一点,它将在 Linux.
上使用 FICLONE
/FICLONERANGE
所以我假设 shutil
会在即将推出的 Python 版本中支持这一点(可能从 Python 3.9 开始?)。
有os.copy_file_range
(since Python 3.8), which wraps copy_file_range
(Linux).
然而,根据 issue 37159 (Use copy_file_range() in shutil.copyfile() (server-side copy)),Giampaolo Rodola:
Nope, [copy_file_range] doesn't [support CoW] (see man page). We can simply use FICLONE (cp does the same).
但是,我不确定这是否正确,正如 copy_file_range
man page 所说:
copy_file_range() gives filesystems an opportunity to implement
"copy acceleration" techniques, such as the use of reflinks
(i.e., two or more inodes that share pointers to the same copy-
on-write disk blocks) or server-side-copy (in the case of NFS).
Issue 26826 (Expose new copy_file_range() syscall in os module) 有 Giampaolo Rodola 的评论:
I think data deduplication / CoW / reflink copy is better implemented via FICLONE. "cp --reflink" uses it, I presume because it's older than copy_file_range(). ...
我的文件系统 (FS)(特别是 ZFS)支持写时复制 (COW),即复制(如果做得好的话)是一种非常便宜的常量操作,实际上并不复制底层内容。内容只复制一次 write/modify 新文件。
实际上,我刚刚发现,ZFS-on-Linux 实际上还没有为用户空间实现它(对吧?)。 但是例如BTRFS 或 XFS 都有。 (参见 here, here, here, here.)
对于 (GNU) cp
实用程序,您将传递 --reflink=always
选项
(参见 here。)
cp
调用 ioctl (dest_fd, FICLONE, src_fd)
(参见 here, here)。
如何在 Python 中获得此行为(如果可能)?
我假设“零拷贝”(例如 here via os.sendfile
) would not result in such behavior, right? Because looking at shutil
s _fastcopy_sendfile
implementation (here),它仍然是一个循环 os.sendfile
使用一些自定义字节数(应该是块大小,max(os.fstat(infd).st_size, 2 ** 23)
).还是会?
COW,这是文件级别的,还是块级别的?
如果可能的话,我希望它也是通用的和跨平台的,尽管我这里的问题有点 Linux 重点。
一个专门关于 Mac 的相关问题似乎是 cp
具有克隆文件的 -c
选项。
在进一步搜索时,我确实找到了答案,以及相关的问题报告。
Issue 37157 (shutil: add reflink=False to file copy functions to control clone/CoW copies (use copy_file_range)) 正是关于这一点,它将在 Linux.
上使用FICLONE
/FICLONERANGE
所以我假设 shutil
会在即将推出的 Python 版本中支持这一点(可能从 Python 3.9 开始?)。
有os.copy_file_range
(since Python 3.8), which wraps copy_file_range
(Linux).
然而,根据 issue 37159 (Use copy_file_range() in shutil.copyfile() (server-side copy)),Giampaolo Rodola:
Nope, [copy_file_range] doesn't [support CoW] (see man page). We can simply use FICLONE (cp does the same).
但是,我不确定这是否正确,正如 copy_file_range
man page 所说:
copy_file_range() gives filesystems an opportunity to implement "copy acceleration" techniques, such as the use of reflinks (i.e., two or more inodes that share pointers to the same copy- on-write disk blocks) or server-side-copy (in the case of NFS).
Issue 26826 (Expose new copy_file_range() syscall in os module) 有 Giampaolo Rodola 的评论:
I think data deduplication / CoW / reflink copy is better implemented via FICLONE. "cp --reflink" uses it, I presume because it's older than copy_file_range(). ...