【发布时间】:2018-02-07 14:10:41
【问题描述】:
我的任务是在 Windows 中将数百万张图像从一个网络共享驱动器移动到另一个。这些不是很大的图像,只有很多。我有 900,000 个要移动的目录,每个目录包含 1-10 个图像。我的目标是利用操作系统来实现最大的并发性,我认为 asyncio 可能会帮助我实现这一点,因为大部分时间将花在等待网络 io 上。这是我目前所拥有的一个 sn-p,但它似乎仍然太慢,因为我需要 5 分钟来移动大约 250MB 的图像。这是我到目前为止所得到的一个示例,我并不完全相信我的实现是正确的。
async def iter_copytree(src, dst):
try:
shutil.copytree(src, dst)
return []
except Exception e:
return [e]
async def iter_dircmp(src, dst):
dcmp = filecmp.dircmp(src, dst)
if dcmp.funny_files or dcmp.diff_files:
return [dcmp]
return []
async def iter_rmtree(src):
try:
shutil.rmtree(src)
return []
except Exception as e:
return [e]
async def iter_move(src, dst):
if await iter_copytree(src, dst):
return
if await iter_dircmp(src, dst):
return
await iter_rmtree(src)
async def move_files(src_root, dst_root, file_names):
tasks = [iter_move(os.path.join(src_root, i), ...) for i in file_names]
await asyncio.gather(*tasks)
loop = asyncio.get_event_loop()
loop.run_until_complete(move_files(...))
【问题讨论】:
-
为什么你认为使用多线程会加速这种应用程序?如果文件来自一个磁盘,它们转到另一个磁盘,并且有一个网络连接加入它们,我预计应用程序性能将受到操作系统和网络的强烈限制。 (当然,我可能是错的)。您是否尝试过一个简单的测试程序,例如:在单个线程中传输 1000 个文件,然后在两个线程之间拆分相同的工作?您能看出任何性能差异吗?
-
asyncio 库是无线程的,如果操作正确,它应该排队我的阻塞调用,这些调用在事件循环返回时被拾取。
-
那么如果不是多线程的,事件循环如何帮助文件传输更快呢?我仍然认为你受到计算环境的限制,而不是你的 python 程序的速度或结构。使用 Windows 资源管理器将 250 MB 的这些小图像文件从一台 PC 拖到另一台 PC 需要多长时间?我的经验是,无论您如何操作,移动大量小文件都非常缓慢。压缩文件可能会有所帮助。
-
所有的 i/o 调用都是阻塞的,所以我不想一次只做一个,因为 cpu 大部分时间都是空闲的等待网络。
-
这就是我想要表达的观点。如果 (1) CPU 空闲等待网络,并且 (2) 您的应用程序需要网络,那么您无法通过更有效地使用 CPU 来加速您的应用程序。线程、多处理或事件循环只有在允许 CPU 的空闲周期做一些有用的事情时才能有所作为。在我写这篇评论时,我的 CPU 大部分时间都处于空闲状态,等待我输入下一个键。我不认为这是一个问题,因为 CPU 不是阻止我更快完成的东西。
标签: python python-3.5 python-asyncio shutil file-copying